PDA

Visualizza versione completa : Excel 2000 e VBA :problema con ciclo For...Next


damiano
21-06-2007, 18.07.15
Ciao .Ho un problema con un ciclo For...next.Situazione: nel Foglio1 nell'intervallo a1:a10 ho dei numeri (supponiamo dall'1 al 10 ).Nella cella F1 dello stesso foglio inserisco un valore a mia scelta attraverso un'altra piccola macro.Ora voglio che quando clicco in una cella qualsiasi del Foglio1 parta una macro che controlli se tra i valori presenti nell'intervallo a1:a10 e' presente il valore inserito in F1.Se Si quella cella deve essere selezionata se No un messaggio mi deve avvisare.Esempio:Supponiamo che in F1 ci sia 3,cliccando in un punto qualsiasi del Foglio1si dovrebbe selezionare la cella a3 che contiene appunto il valore 3.Supponiamo che in F1 ci sia 15 la macro mi dovrebbe avvisare con un messaggio che il valore non e' presente e poi interrompersi.Per fare cio ho usato un ciclo for..next inserito nel parte SelectionChange del Worksheet (foglio 1 chiaramente):

Private Sub Worksheet_SelectionChange(ByVal Target As Range)
ScreenUpdating = False 'si puo' anche omettere

Dim CL2 As Object

For Each CL2 In Worksheets(1).Range("a1:a10")
If CL2.Value = [f1] Then

CL2.Select

'inizio parte incriminata
Else
MsgBox ("valore non presente")
Exit Sub
'fine parte incriminata

End If
Next
End Sub

In questa situazione pero' la macro mi da comunque il messaggio e non mi seleziona la cella anche se il valore e' presente.Se toglo la parte "incriminata" (Else...fino a.. Exit Sub) la cella viene correttamente selezionata se contiene il valore presente in f1 e non succede nulla se il valore non e' presente.A me invece serve anche che se il valore non e' presente parta il msgbox (che potrebbe essere,in base a quello che serve,anche qualche altra cosa ).Tutto qui.Spero di essermi spiegato bene.Come si puo' fare,non mi riesce .
Grazie.

Alexsandra
22-06-2007, 09.32.50
nel foglio inserisci questo codicePrivate Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
trova
End Sub facendo doppio click in una cella qualsiasi lanci la macro "trova".
In un modulo inserisci questo codiceSub trova()
b = "": a = "" 'azzera le variabili all'inizio
a = ActiveSheet.[F1]
riga = 1
Do Until Cells(riga, 1) = Empty
If Cells(riga, 1).Value = a Then
Cells(riga, 1).Select
b = a
End If
riga = riga + 1
Loop
If b = "" Then MsgBox "Nessuno dato trovato"
End Sub vedi se ti và bene questo codice

damiano
22-06-2007, 19.01.23
Si va benissimo!Grazie.
Mi sta pero' venendo in mente una cosa a cui non avevo pensato,scusami.E' possibile che nell'intervallo contenente i numeri da ricercare siano presenti delle celle vuote.In questo caso la macro non considererebbe i numeri presenti nelle celle successive alla prima cella vuota e lancerebbe,a prescindere, il msgbox.
Ti andrebbe di fare un'aggiustatina alla macro in modo tale che se ne freghi delle eventuali celle vuote presenti tra il primo e l'ultimo dato dell'elenco?
Grazie in ogni caso.
ciao

Alexsandra
22-06-2007, 21.36.09
:) :) mi aspettavo questa richiesta :) :)

dovresti nella tua macro verificare se ci sono valori doppi, se ci sono cele vuote e ... tante altre cose .......

io farei una cosa, perchè non esponi a 360° il tuo progetto? che lo vediamo assieme.

Ti dico questo per esperienza, nel senso che tu magari vedi le cose come le hai descritte nel tuo post, mentre magari puoi trovare una soluzione diversa, è solo avendo una visione chiara di tutto il progetto che puoi attingere a tante altre info.

posta quello che hai bisogno e ... troveremo una soluzione

ciao

damiano
23-06-2007, 18.35.56
Certo hai ragione.Facciamo prima.Ti allego il file xls.Si tratta di un file (un po farraginoso e ripetitivo nel codice) che serve a conteggiare i costi di una vecchia connessione adsl al consumo e a crearne un calendario con i relativi dettagli.
Ho lasciao solo una piccola parte del calendario a scopo indicativo.

Nel foglio "Leggimi" del file allegato trovi una breve spiegazione del funzionamento del foglio e la descrizione del problema (se lo volgiamo chiamare cosi).
ciao

Alexsandra
24-06-2007, 23.10.33
Ho fatto qualche modifica, prova a vedere se ti và bene così.

Io non userei tante volte Set, allochi troppa memoria.

PS. non mi funziona "gestione allegati" te lo metto quì
http://freefilehosting.net/download/MjI5NjU0

damiano
25-06-2007, 22.41.23
Grazie Alex ,sono riuscito ad ottenere esattamente quello che volevo grazie alla tua ultima macro.Ho aggiunto a quella che avevo fatto un pezzo della tua (quello relativo alla variabile Alex) ed e' andata bene.
Per scaricare dalla memoria le variabili create ho spalmato alla fine un po' di Nothing...magari qualcuno anche inutile. :) ...,non so bene.
Questo il codice finale:

Private Sub Worksheet_SelectionChange(ByVal Target As Range)
ScreenUpdating = False 'si puo' anche omettere

Dim Alex As String

Dim CL1 As Object

Set ac = ActiveCell
x = ac.Address

For Each CL1 In Worksheets(2).Range("g2:g1000")
If CL1.Address = x And CL1 <> "" Then
Selection.End(xlToLeft).Select
y = ActiveCell.Value


For Each CL2 In Worksheets(3).Range("a2:a1000")
If CL2.Value = y Then
Sheets("Dettagli").Select
CL2.Select

Alex = "1"

End If
Next

If Alex <> "1" Then MsgBox "Valore non trovato"

End
End If
Next

Set ac = Nothing
Set x = Nothing
Set y = Nothing

End Sub



ciao :act:

Alexsandra
26-06-2007, 08.37.35
Ti dirò che io non amo molto il Set, con le istruzioni che c'erano nel modulo Alex il codice è molto più leggeroSub trova()
Dim Alex As String
Application.ScreenUpdating = False
y = Cells(ActiveCell.Row, 1)

Sheets("Dettagli").Activate

[A2].Select
ActiveCell.CurrentRegion.Select


For ind = 2 To 1000
If Range("A" & ind) = y Then
Range("A" & ind).Select
Alex = "1"
End If
Next
If Alex <> "1" Then MsgBox "Valore non trovato": Sheets("Foglio1").Select
End Sub l'unica cosa che non mi convince molto è il lancio della macro trova che ora fai dal foglio Calendario sfruttanto questo eventoPrivate Sub Worksheet_SelectionChange(ByVal Target As Range)
trova
End Sub comunque prova pure così, i metodi sono molti e prevale sempre la soggettività di chi programma.

PS. Controlla anche la macro che hai nel modulo ThisWorkbook Private Sub Workbook_Open() secondo me ti può creare qualche problema all'avvio in questo punto'inserimento nuova data in Calendario
ActiveCell.Offset(1, 0).Select
ActiveCell.Value = Worksheets("Foglio1").Range("A9")
non hai nessun controllo sulla cella (se fosse in A1 ti genera errore con l'istruzione Offset)

ciao

damiano
26-06-2007, 20.39.55
Si,quell'errore all'apertura l'avevo notato .Ti dico il motivo di alcune scelte in generale.Faccio quello che sono capace a fare(non tantissimo) quindi le scelte sulle istruzioni da inserire per ottenere questo e quell'altro sono anche un po' obbligate:)
Per quanto riguarda la scelta di non usare per intero il "codice Alex" ma solo integrarne una parte nel vecchio codice sta principalmente nel fatto che facendo nell'altro modo (effettivamente piu' pesante) il msgbox o la selezione della cella si ottengono solo se si clicca sulle celle del Calendario con scritto "clic x dettagli" ,solo quelle,altrimenti non succede nulla.E questo era quello che volevo ottenere.Usando il "codice Alex" non si ottiene l'identica cosa.Ma questo perche' ,su questo punto, non sono stato molto chiaro io.Ma va bene cosi comunque..........va bene.


Volevo piuttosto capire meglio una cosa Alex:Il codice l'ho inserito direttamente nel Worksheet (sfruttando l'evento SelectionChange) e non in mudulo senza una ragione particolare(....abitudine).Non so,c'e qualche differenza sostanziale nell'usare ,in questo caso, un modulo di classe( oppure un modulo)come hai fatto tu rispetto all'inserire il codice direttamente nel Worksheet?
Anche un'altra cosa:qual'e' il motivo per cui hai usato un modulo di classe?Ho sempre usato solo i moduli e sono curioso di capire.
Grazie ciao.

Alexsandra
27-06-2007, 22.20.06
Usa il codice che ti piace di più che così và bene, ognuno vede le cose sempre dal suo punto di vista :)

prova questo codice: nel foglio metti questoPrivate Sub worksheet_selectionchange(ByVal target As Range)
If Intersect(target, Range("A1:F100")) Is Nothing Then trova
End Sub se poi nascondi le colonne dopo la colonna G ottieni quello che cercavi.

Poi io non ho usato un modulo di classe, ho usato un modulo semplice, se sfrutti l'evento non hai associazione con l'oggetto perchè non lo controlli, cioè se tu copi il codice del modulo Alex e lo metti in una sub sotto all'evento worksheet_selectionchange ti genera un errore, è sempre meglio sfruttare l'evento per lanciare un'altra macro, così ottieni un modulo "intercambiabile" (chiamiamolo cosi) e non più legato all'evento.

mi sono spiegata .... da cani, ma penso che tu abbia capito (spero) :)

PS. a giorni posterò nel mio blog come fare le userform, si parlerà di Oggetti Eventi e controlli e subito dopo dei moduli di classe, anche se devo dire che sono poco usati anche da programmatori avanzati, trovo molto più semplice e lineare l'uso dei moduli normali.

damiano
28-06-2007, 18.10.08
In riferimento al modulo di classe hai pienamente ragione:non lo hai usato...ho preso io una svista madornale,pardon...come non detto. :timid:

Mi hai dato uno spunto molto interessante:L'istruzione "If Intersect(Target, Range("A1:F100")) Is Nothing Then trova" che non conoscevo proprio e che puo' tornare molto utile.Utilizzandola e nascondendo le colonne dopo la colonna G ,come dicevi,tutto torna.Rimanevano solo,nella colonna G,sotto l'ultima cella contenente il testo "clic x dettagli", quelle celle vuote che cliccate mi attivavano inutilmente il foglio Dettagli:ho rimediato inserendo ,nel modulo Alex,un semplice If y <> "" Then appena prima di Sheets("Dettagli").Activate e chiudendo con End If prima di End Sub.
Ho fatto anche un paio di ritocchi nel modulo ThisWorkbook per evitare la comparsa di errori....mi sembra che vada liscio.
Ora ottengo esattamente quello che volevo sia utilizzando il codice Alex sia il remix del mio (mio+parte di Alex).Direi che la faccenda si puo' dire conclusa.

ciao Alex .... grazie :)
ps: interessante il tuo blog

Alexsandra
29-06-2007, 22.37.20
..Mi hai dato uno spunto molto interessante... :) Guarda che se mi stimoli ...... io ci vado a nozze.
Mi piacciono quelli che vogliono "scoprire".

Invece di nascondere le colonne, prova questo codice.Private Sub Worksheet_Activate()
Sheets("Calendario").ScrollArea = "A2:G20"
End Sub
mettilo nel foglio "Calendario" e vedi cosa fà :act:

ciao ... alla prossima :)