› Sviluppare funzionalita su Microsoft Office con VBA › Variabile pubblica che si azzera "da sola"
-
AutoreArticoli
-
Buongiorno,
capisco l'assurdità del titolo, ma, apparentemente sembra quello che mi succede. Allora:
In un progetto, definisco una variabile intera pubblica:
Public ZAZ As IntegerSuccessivamente all'apertura di una cartella la imposto su un valore (il nr delle righe articoli presenti, ma non ha importanza):
Set AA = Workbooks("LOGISTA_ARTICOLI.xls").Worksheets("ARTICOLI") ZAZ = AA.Range("A8")Dove in A8 è presente il nr delle righe articoli.
bene, la variabile è correttamente impostata, diciamo al valore di 500, ma ad un certo punto, nell'esecuzione di una sub scopro che la variabile è "azzerata"!
Allora, domanda: a parte la più che ovvia obiezione che da qualche parte c'è un'istruzione che la azzera (ma non c'è!), che l'istruzione di cui sopra: ZAZ = AA.Range("A8") viene riseguita e AA.Range("A8") è uguale a "zero" (ma non è così!), a parte queste ovviassimo obiezioni, ci può essere un altro motivo (che so ... variabile dichiarata in un modulo, sub in un altro modulo, ma è pubblica!) nel VBA che azzera la variabile?
Capisco la stupidità della domanda, ma apparentemente è quello che sembra succedere, ed è un fenomeno che avevo già osservato in un altro caso, di una variabile pubblica impostata all'inizio da, 0 a 1, per dire programma aperto, e poi di ritrovarmela a zero nel corso delle elaborazioni ...
???
Grazie, anticipatamente, per la vostra attenzione,
Abramo
Ciao
Così come l'hai postata dici bene che sembra un'assurdità.
Prima di esprimere un azzardato giudizio sarebbe il caso di vedere il resto del codice. In qualche punto ci DEVE essere qualcosa che azzera la variabile.
Se è possibile prova ad eseguire il codice passo-passo (per intenderci con F8) e vedi se ti vien fuori l'errore.
Ciao,
Mario
Potresti provare anche a bloccare la cella A8 dopo che hai impostato la variabile , a questo punto se c'è qualcosa che la cancella lo vedi subito
Il fenomeno è questo:
Cliccando un tasto (una forma associata ad una macro) viene eseguita la macro seguente:
Sub M_SALVA_CAR() ' Set MM = Workbooks("LOGISTA_MACRO.xls").Worksheets("MACRO") Set AA = Workbooks("LOGISTA_ARTICOLI.xls").Worksheets("ARTICOLI") MsgBox "1 " & ZAZ Call X_MSG_ini("", "SALVA CARICO MATRIX", 29) ....Viene visualizzato il messaggio 1 0 (valore di ZAZ)
La Call X_MSG_ini è la seguente:
Sub X_MSG_ini(ByVal MSGP As String, ByVal MSGQ As String, Optional ByVal RIGT As Integer) ' Set MM = Workbooks("LOGISTA_MACRO.xls").Worksheets("MACRO") MM.Activate Application.ScreenUpdating = True MM.Range("A14").Select If RIGT <> 0 Then If RIGT = MM.Range("G15") Then If MM.Range("G14") <> 0 _ Or MM.Range("E14") <> 0 Then RIGS = -1 Call X_XTIME End If End If End If MsgBox "2 " & ZAZ Call X_MSG_okk("CONFERMA Esecuzione", MSGQ, 1) ....viene visualizzato il messaggio 2 0 (Valoredi ZAZ)
La Call X_MSG_okk è la seguente:
Sub X_MSG_okk(ByVal MSGC As String, ByVal MSGD As String, ByVal RIGX As Integer) ' Set MM = Workbooks("LOGISTA_MACRO.xls").Worksheets("MACRO") 'If MM.Range("K14") <> MM.Range("L14") Then ' MsgBox ("Date Progressivo INCOERENTI !!!") ' End 'End If MsgBox "3 " & ZAZ If ZAZ <> MM.Range("G38") + 10 Then MM.Range("G19") = ZAZ MsgBox "(ZAZ) CONTROLLO RIGHE ARTICOLI ERRATO (" & ZAZ & ")" Call E_APRI_ARTICOLI_Z MsgBox "6 " & ZAZ End End If .....Viene visualizzato il messaggio 3 0 (Valore di ZAZ)
Poiché MM.Range("G38") è uguale a 500
Viene visualizzato il messaggio di errore (ZAZ) CONTROLLO RIGHE ARTICOLI ERRATO (0)
La Call E_APRI_ARTICOLI_Z è la seguente:
Sub E_APRI_ARTICOLI_Z() Application.Calculation = xlCalculationManual MsgBox "4 " & ZAZ ZAZ = AA.Range("A8") ZBZ = AA.Range("A9") ZCZ = AA.Range("A4") MM.Range("G19") = ZAZ - 10 Application.Calculate MsgBox "5 " & ZAZ End SubViene visualizzato il messaggio 4 0 (valore di ZAZ)
poi il messaggio 5 510 (valore di ZAZ)
poi il messaggio 6 510 (valore di ZAZ)
E la procedura termina con End
Dunque, a questo punto ZAZ è uguale a 510
Bene, riparto con l'esecuzione di M_SALVA_CAR e si ricomincia da capo:
Viene visualizzato il messaggio 1 0 (valore di ZAZ)
ecc. ecc.
Cosa diavolo AZZERA ZAZ ...
Continuo l'indagine, ma per ora: ?????
Ma no! Ho stupidamente capito! quando termina una procedura VBA ogni variabile torna a ZERO se non viene reimpostata:
dopo la end la procedura termina e, quando si riparte, ZAZ riparte da ZERO: deve essere reimpostata da AA.Range("A8")
...
mah!
grazie, rispondere a Voi mi ha fatto arrivare alla soluzione ...
Non vedo la macro Call X_XTIME
Non vedo Public ZAZ As Integer 'in un Modulo, meglio se longNon è vero (con End Sub), la variabile rimane attiva. Qui sotto avvia con F8 Sub M_SALVA_CAR sino alla fine. Dopo premi Sub A()
Public ZAZ As Integer Sub a() MsgBox ZAZ End Sub Sub M_SALVA_CAR() MsgBox "1 " & ZAZ Call X_MSG_ini("", "SALVA CARICO MATRIX", 29) MsgBox "macro in fase di termine" End Sub Sub X_MSG_ini(ByVal MSGP As String, ByVal MSGQ As String, Optional ByVal RIGT As Integer) MsgBox "2 " & ZAZ Call X_MSG_okk("CONFERMA Esecuzione", MSGQ, 1) End Sub Sub X_MSG_okk(ByVal MSGC As String, ByVal MSGD As String, ByVal RIGX As Integer) MsgBox "3 " & ZAZ Call E_APRI_ARTICOLI_Z MsgBox "6 " & ZAZ End Sub Sub E_APRI_ARTICOLI_Z() MsgBox "4 " & ZAZ ZAZ = 500 'Range("A8") MsgBox "5 " & ZAZ End SubHo cercato di simulare il tuo problema ma non ci sono riuscito; qui funziona tutto a dovere.
Dato che hai fatto solo un estratto, non hai indicato se stai utilizzando la funzione Option Explicit in testa al modulo delle macro, non hai esattamente indicato in quale posizione hai inserito la dichiarazione della variabile ZAZ (se è nello steso modulo dove hai le macro o altrove, e dove), mi sorge spontaneo un dubbio: per quello che ho potuto verificare la variabile ZAZ in questa situazione, se impostata correttamente, si può azzerare solo al riavvio del file.
Non è vero (con End Sub), la variabile rimane attiva
Ma lui ha usato End, non End Sub, forse potrebbe risolvere con Exit Sub
Allora, è tutto chiaro, la causa è proprio l'uscita dal VBA e il rientro in EXCEL, o meglio, come Patel ha ben specificato (e io non lo sapevo) se si esce con End le variabili sono tutte azzerate, altrimenti NO (confermo, ho fatto una prova). E questo mi spiega perché il fenomeno era altalenante, a volte la variabile me la ritrovavo impostata e a volte la variabile me la trovavo a ZERO: dipendeva da come uscivo dalla cascata delle sub che eseguivo.
Normalmente si esce dalla sub iniziale alla fine con end sub, e allora le variabili rimangono impostate, ma in alcune condizioni, quando si vuole interrompere l'intera esecuzione delle sub in cascata, occorre per forza uscire con end (o no?) e allora ecco che mi trovavo con le variabili AZZERATE.
E' evidente, almeno per me, che la necessità di uscire con END è sempre possibile e dunque occorre sempre di principio reimpostare tutte le variabili ad ogni lancio di un'esecuzione. Vediamo il mio caso personale:
Ho un'anagrafica di articoli di magazzino per la quale ho previsto 500 righe di articoli, ma prima erano 300, poi 400, ...
Dunque mi capitava di dover allungare le righe e questo mi costringeva a modificare tutte le istruzioni, tipo
AA.Range("AU11:AU510") = AA.Range("AQ11:AQ510").Valueo anche i sort:
AA.Rows("11:510").Sort Key1:=AA.Range("CF11"), Order1:=xlDescending, _ Key2:=AA.Range("FA11"), Order2:=xlDescendingAllora ho risolto di impostare una variabile ZAZ all'apertura della cartella Articoli con il massimo numero di riga disponibile, 510 in questo momento, partendo dalla riga 11 (510 - 10 = 500), e modificare tutte le istruzioni con il valore 510 impostato, per esempio:
AA.Range("AU11:AU" & ZAZ) = AA.Range("AQ11:AQ" & ZAZ).Valuee così via ...
Quando aprivo la cartella Articoli impostavo la variabile ZAZ, ma ... pensavo rimanesse impostata "per sempre", invece no, quando uscivo con END mi si azzerava, altrimenti NO, e, non sapendolo, non capivo la logica e vi ho interpellato, e ragionando con voi ho capito.
Ho risolto che, poiché tutte le procedure lanciate passano da una sub di conferma del lancio, una volta confermata l'esecuzione, viene eseguita, ogni volta, l'impostazione della variabile (prendendolo dal RIF.RIGA(510) impostato in A8 in Articoli).
E' tutto, grazie per avermi chiarito le idee.
P.S. Sicuramente avrete delle critiche sul mio modo di procedere, critiche che sicuramente attenderò con impazienza per migliorare le mie conoscenze del VBA.
Grazie, grazie.
Abramo
quando si vuole interrompere l'intera esecuzione delle sub in cascata, occorre per forza uscire con end (o no?)
Se usi Exit Sub, sapendo dove rientra la macro potresti sempre attivare una flag boolean prima dell'Exit Sub da sfruttare nella macro mittente ed uscire in modo 'pulito' da li.
Capisco, è vero, ma dovrebbe essere gestito in ogni sub, che lancia una sub, che lancia una sub, ... e poi, forse è possibile se impostato fin dall'inizio della progettazione, ma ora in un progetto con non meno di 200 sub ...
Una domanda però: come è possibile, in VBA, assegnare ad una variabile il valore presente in una cella:
ZAZ = RANGE("A8").Value
è possibile compiere l'operazione contraria?
Cioè in EXCEL assegnare ad una cella il valore di una variabile VBA, tipo:
in EXCEL, nella cella A8 inserire = Funzione???(ZAZ)
Credo di no, però ...
Ma nel progetto quanti "End" ci sono che che possono interferire quando ZAZ è valorizzata ?
è possibile compiere l'operazione contraria?
Scusa ma forse non ho capito:
RANGE("A8") = ZAZ
Ogni End interferisce e sono tantissime, tutti i test di controllo di correttezza di avvio delle procedure terminano con End.
Poi:
RANGE("A8") = ZAZ
è un istruzione in VBA e se ZAZ contiene 500 in A8 finisce 500.
Bene, ma se esco con End, ZAZ va a ZERO e in A8 rimane 500.
Se invece ci fosse, in A8, un'ipotetica funzione del tipo =FUNZ.IPOTETICA(ZAZ) allora dopo la End ci sarebbe ZERO in A8.
Ma sicuramente non c'è.
Grazie!
@patel OK per End
Questo codice mi risulta "strambo". Tra tutti i test di contollo non si potrebbe usare un semplice ZAZ=ultima riga?
Se potesse servire...
Risposta = MsgBox(prompt:="Desideri uscire?", Buttons:=vbYesNo)
If Risposta = vbYes Then
ZAZ = ???
A8 = ???
Exit Sub
Else
ZAZ = ???
A8 = ???
End
End IfZAZ=ultima riga
No, in coda alle righe articoli ci sono altre righe di controllo, "ultima riga" mi darebbe l'ultima di queste e quindi poi dovrei, da questa all'ultima risalire all'ultima riga destinata agli articoli (= Ultima riga - Nr righe di controllo).
Ma in seguito potrei anche modificare in più o in meno queste righe di controllo e quindi poi intervenire sul Nr righe di controllo.
Invece in A8 ho inserito =RIF.RIGA(510) ultima riga articoli attuale. Se inserisco p.e., dopo la riga 490 10 righe articoli, la riga 510 diventa la riga 560 e il valore di A8 "segue" automaticamente l'inserimento diventando =RIF.RIGA(560) e in ZAZ entra automaticamente il nuovo valore della Cella A8: 560 appunto, senza alcuna correzione da parte mia.
-
AutoreArticoli
