Excel VBA: SendKeys не работает на некоторых компьютерах

Я работаю над листом Excel, в котором каждая строка должна указывать время последнего изменения какой-либо ячейки в этой строке. Самый простой способ, который я нашел для этого, - это добавить небольшое количество VBA в код рабочего листа, например:

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

Это эффективно изменит дату в столбце «N» всякий раз, когда редактируется любой другой элемент в этой строке. Большой! Решено, кроме ...

Поскольку я изменяю значение ячейки в коде, стек отмены немедленно теряется, и, конечно же, это означает, что ЛЮБАЯ работа на этом листе не может быть отменена.

Итак, альтернатива этому - обмануть excel и заставить его думать, что я не редактировал ячейку. Этот код сохраняет стек отмены при изменении даты:

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

В этом случае мы выбираем ячейку, используем SendKeys для имитации редактирования ячейки и восстанавливаем курсор в исходное положение. «^; ~» использует Excel «Ctrl +;» ярлык для ввода даты. Большой! Решено, кроме ...

Этот код отлично работает на моей машине (Win7, Excel 2010), но не работает на машине коллеги (Win8, Excel 2010, может быть, немного быстрее). На машине Win8 (не знаю, проблема ли в ОС, кстати) происходит то, что всякий раз, когда ячейка изменяется, каждая ячейка сразу под этой ячейкой становится текущей датой, и, конечно, сохранение истории отмены бессмысленно, потому что выполнение Отмена немедленно активирует код рабочего листа и снова превращает все в даты.

Я самостоятельно выяснил, что то же самое произойдет на моей машине, если я удалю «Подождите», присущее команде SendKeys. То есть, если я использую строку:

SendKeys "^;~", False

Итак, я предполагаю, что по какой-то причине, даже при использовании той же версии Excel, мой компьютер ждет завершения команды SendKeys, а компьютер моего коллеги - нет. Любые идеи?


person Adam Hoffman    schedule 28.10.2014    source источник
comment
Для удобства всех, кто пытается это сделать, я изменил свое Если, чтобы вы могли вручную изменить дату назад: If Target.Row > 2 And Cells(Target.Row, "A") <> "" And Target.Column <> 14   -  person Adam Hoffman    schedule 29.10.2014


Ответы (1)


Ты прав. Это дает эту проблему в Excel 2010 / Win8.

Попробуй это. Используйте собственный код Wait, который я написал. (Проверено в 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

введите описание изображения здесь

Альтернатива

Использование Doevents также дает желаемый эффект.

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
person Siddharth Rout    schedule 28.10.2014
comment
Что ж, это точно работает, но 1 секунда кажется ужасно долгим с точки зрения вычислений. Можно ли использовать более быстрый таймер? - person Adam Hoffman; 29.10.2014
comment
См. Alternative, который я дал :) Возможно, вам придется обновить страницу. - person Siddharth Rout; 29.10.2014
comment
... Теперь выясним, как отменить изменение этой даты, если вы отмените то, из-за чего она изменилась в первую очередь! - person Adam Hoffman; 29.10.2014
comment
Посмотрите, поможет ли ЭТО? Не тестировал с помощью sendkeys ... - person Siddharth Rout; 29.10.2014
comment
Я попробую, но тогда, если бы у меня был правильный обработчик отмены VBA, мне вообще не понадобились бы SendKeys. Спасибо за помощь! - person Adam Hoffman; 29.10.2014
comment
Правда. Я хотел предложить это раньше, но не был уверен, что вы хотите пойти по этому пути. :) - person Siddharth Rout; 29.10.2014