Почему Excel VBA код не работает на открытом? - PullRequest
1 голос
/ 24 сентября 2019

У меня есть код, который должен работать на открытом, но я не понимаю, почему он не работает.Если я шагну по коду, я буду работать нормально.И я могу запустить его вручную просто отлично, но код никогда не работает при открытом.

У меня есть код в ThisWorkbook, и я искал другие потоки, но не могу найти исправление.Есть идеи, что происходит?

 Private Sub RefreshAndClose_Open()

    If DateDiff("h", "12", Hour(Now)) <= 0 And DateDiff("n", "50", Minute(Now)) <= 50 Then
        ThisWorkbook.RefreshAll
        DoEvents
        ThisWorkbook.Save
        DoEvents
        Application.Quit
    End If

End Sub

1 Ответ

1 голос
/ 24 сентября 2019

Представьте, что вы Excel.

У вас открыт Workbook, а Worksheet активен.Теперь пользователь щелкает куда-то, и Selection меняется.Чтобы это произошло, нужно запустить много низкоуровневого кода, не относящегося к VBA, но в тот или иной момент это происходит (псевдокод) где-то в кишках Worksheet объекта:

RaiseEvent SelectionChange(ActiveCell)

Это вызывает событие Worksheet.SelectionChange:

Members of 'Worksheet', with 'SelectionChange' event selected (as seen in the Object Browser)

Когда это событие возникает, если для этого события есть обработчик , именно тогда оно будет вызвано.Этот обработчик должен быть подключен - вы можете сделать это самостоятельно, используя объектную переменную WithEvents, но модули документов в Excel упрощают подключение обработчика - просто перейдите к модулю Worksheet, который выдля обработки событий рабочего листа выберите Worksheet в раскрывающемся меню панели слева ...

code pane dropdowns, left one is dropped, 'Worksheet' is selected

... и VBE создаст для вас процедуру-обработчик -обратите внимание на содержимое двух выпадающих списков:

Worksheet::SelectionChange handler signature was added automatically by the editor

Процедура обработчика названа очень специфическим образом:

LeftSideDropdownValue_RightSideDropdownValue

"Значение раскрывающегося списка слева""это интерфейс , для которого вы хотите реализовать член;«раскрывающееся значение справа» - это конкретный элемент, который вы внедряете.

Если вы поместите курсор внутри своей процедуры, в раскрывающемся списке слева будет указано (General) - это означает, что это просто еще одна процедура,и если ничто не вызывает его, то это просто еще одна неиспользованная процедура, которая также может не существовать.

Итак, вы приложение Excel и открываете книгу.То же самое происходит: много низкоуровневого кода, не относящегося к VBA, должны запускаться, поскольку куча объектов десериализуется из файла книги с поддержкой макросов .xlsm, загруженного с диска, и когда все идет хорошо, это происходит (псевдокод) где-то в открытых Workbook кишках объекта:

RaiseEvent Open

Это вызывает событие Workbook.Open:

Members of 'Workbook', with 'Open' event selected (as seen in the Object Browser)

Еще раз мымог бы объявить переменную объекта WithEvents и подключить обработчик самостоятельно, но проект VBA, размещенный в Excel, всегда будет иметь модуль документа Workbook, который уже делает это для нас - поэтому для обработки события Workbook.Open,мы можем перейти к модулю ThisWorkbook, выбрать Workbook из раскрывающегося списка слева и заставить VBE автоматически сгенерировать правильно сформированный для нас обработчик:

Private Sub Workbook_Open()

End Sub

Опять же, причина, по которой VBA знаетэта процедура обрабатывает событие Workbook.Open, потому что имя говорит так:

[Interface]_[Member]

Если мы пойдем и изменим имя на что-то еще, мы сломаем эту ссылку, и мы знаем, что ссылка сломана, потому чтоКроме того, в раскрывающемся меню слева будет 1067 *, а не Workbook.

. Эта специальная схема именования также является причиной, по которой вам следует избегать подчеркивания в именах собственных процедур: они создают процедуры выглядят как обработчики событий, но это не так.В некоторых конкретных дополнительных сценариях использование подчеркивания в именах элементов может даже привести к ошибкам компиляции.Лучше воспользуйтесь хорошей привычкой на раннем этапе, придерживаясь простых PascalCase для имен процедур.

Если мы пойдем и изменим список параметров любым способом, который делает его несовместимым с объявлением события, мы получим компиляциюошибка:

Procedure declaration does not match description of event or procedure having the same name

Вы можете безопасно изменять имена параметров (хотя я не могу придумать какой-либо веской причины для этого), но типы данных параметров и их порядок не могутбыть измененным.

См. все, что вы когда-либо хотели знать о событиях для получения дополнительной информации (я написал эту статью).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...