2014-10-28 24 views
6

Sto lavorando a un foglio Excel in cui ogni riga deve indicare l'ultima volta che qualsiasi cella all'interno di quella riga è stata modificata. Il metodo più semplice che ho trovato per farlo è quello di mettere un po 'piccola quantità di VBA nel codice del foglio di lavoro, in questo modo:VBA di Excel: SendKeys ha esito negativo su alcuni computer

Private Sub Worksheet_Change(ByVal Target As Range) 
    Application.EnableEvents = False 
    If (Target.Row > 2) And (Cells(Target.Row, "A") <> "") Then 
     Cells(Target.Row, "N").Value = Date 
    End If 
    Application.EnableEvents = True 
End Sub 

Questo cambierà in modo efficace la data nella colonna "N" ogni volta che qualsiasi altro elemento in quella riga è modificata. Grande! Risolto, eccetto ...

Poiché sto cambiando il valore della cella nel codice, lo stack di annullamento viene immediatamente perso e, naturalmente, questo significa che QUALSIASI lavoro in questo foglio di lavoro non può essere annullato.

Quindi, un'alternativa a questo è ingannare eccellere nel pensare che non ho modificato una cella. Questo codice conserva la stack di annullamento mentre cambia la data:

Private Sub Worksheet_Change(ByVal Target As Range) 
    Dim cursorLocation As Range 
    Application.EnableEvents = False 
    If Target.Row > 2 And Cells(Target.Row, "A") <> "" Then 
     Set cursorLocation = ActiveCell 
     Cells(Target.Row, "N").Select 
     SendKeys "^;~", True 
     cursorLocation.Select 
    End If 
    Application.EnableEvents = True 
End Sub 

In questo caso, selezioniamo la cella, utilizzare SendKeys per l'editing finta cella e il ripristinare il cursore nella sua posizione originale. "^; ~" sta usando Excel "Ctrl +;" collegamento per inserire la data. Grande! Risolto, tranne ...

Questo codice funziona correttamente sulla mia macchina (Win7, Excel 2010) ma non funziona sulla macchina di un collega (Win8, Excel 2010, forse un po 'più veloce). Sulla macchina Win8 (non importa se è il sistema operativo che è il problema, btw), ciò che accade è che ogni volta che una cella viene cambiata, ogni cella immediatamente al di sotto di quella cella diventa la data corrente e, naturalmente, conservare la cronologia di annullamento non ha senso perché l'esecuzione Un Annulla riattiva immediatamente il codice del foglio di lavoro e trasforma nuovamente tutto in date.

Ho capito da solo che la stessa cosa accadrà sulla mia macchina se rimuovo "Wait" inerente al comando SendKeys. Cioè, se io uso la linea:

SendKeys "^;~", False 

Quindi, quello che sto indovinando è che per qualsiasi ragione, anche quando si utilizza la stessa versione di Excel, il mio computer è in attesa per il comando SendKeys per finire, ma il computer del mio collega non lo è. Qualche idea?

+1

A beneficio di chiunque altro provare questo, ho cambiato il mio "se" per consentire di modificare manualmente la data posteriore: 'Se Target.Row> 2 e cellule (Target.Row, "A") <> "" E Target.Column <> 14' –

risposta

5

Hai ragione. Dà quel problema in Excel 2010/Win8.

Prova questo. Utilizzare il codice personalizzato Wait che ho scritto. (Testato in Excel 2010/Win8)

Private Sub Worksheet_Change(ByVal Target As Range) 
    Dim cursorLocation As Range 
    Application.EnableEvents = False 
    If Target.Row > 2 And Cells(Target.Row, "A") <> "" Then 
     Set cursorLocation = ActiveCell 
     Cells(Target.Row, "N").Select 
     SendKeys "^;~" 
     Wait 1 '<~~ Wait for 1 Second 
     cursorLocation.Select 
    End If 
    Application.EnableEvents = True 
End Sub 

Private Sub Wait(ByVal nSec As Long) 
    nSec = nSec + Timer 
    While nSec > Timer 
     DoEvents 
    Wend 
End Sub 

enter image description here

alternativa

Utilizzando Doevents ha anche l'effetto desiderato.

Private Sub Worksheet_Change(ByVal Target As Range) 
    Dim cursorLocation As Range 
    Application.EnableEvents = False 
    If Target.Row > 2 And Cells(Target.Row, "A") <> "" Then 
     Set cursorLocation = ActiveCell 
     Cells(Target.Row, "N").Select 
     SendKeys "^;~" 
     DoEvents 
     cursorLocation.Select 
    End If 
    Application.EnableEvents = True 
End Sub 
+0

Beh, questo funziona di sicuro, ma 1 secondo sembra un tempo terribile da attendere, in termini informatici. C'è un timer più veloce che posso usare? –

+0

Vedere 'Alternative' che ho dato :) Potrebbe essere necessario aggiornare la pagina. –

+0

Non importa, DoEvents sembra minimizzare il ritardo. –

Problemi correlati