Переменные модуля не сохраняются в CodeModule.Вызов InsertLines

#vba #excel

#vba #excel

Вопрос:

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

 Dim btnShowTable
Set btnShowTable = ActiveSheet.Buttons.Add(rowRange.Left   10, rowRange.Top   10, rowRange.Width - 20, rowRange.Height - 20)
btnShowTable.Caption = "Show table data"
btnShowTable.OnAction = AddClickHandler_ShowSheet("ClickModule", "TableView", tableSheet)


Function AddClickHandler_ShowSheet(ByVal moduleName As String, ByVal btnName As String, ws As Worksheet)
  Dim methodName As String
  methodName = btnName amp; "_" amp; AddClickHandler_GetId() amp; "_Click"
  Dim LineNum As Long
  Dim VBCodeMod As CodeModule
  Set VBCodeMod = ThisWorkbook.VBProject.VBComponents(moduleName).CodeModule
  With VBCodeMod
    LineNum = .CountOfLines   1
      .InsertLines LineNum, _
        "Sub " amp; methodName amp; "()" amp; Chr(13) amp; _
        "    " amp; ws.CodeName amp; ".Select" amp; Chr(13) amp; _
        "End Sub"
  End With
  AddClickHandler_ShowSheet = moduleName amp; "." amp; methodName
End Function
  

Функция, создающая кнопку, находится в одном модуле, а AddClickHandler_ShowSheet — в другом.

Идея в том, что у меня был бы отдельный модуль, который содержал бы все эти обработчики щелчков, чтобы я мог легко удалить их все. Это работает нормально. Обработчики созданы, и кнопки работают должным образом. Проблема, с которой я сталкиваюсь, заключается в том, что при вызове этого метода InsertLines все переменные моего модуля в модуле, который содержит функцию для создания кнопок, теряются. У меня есть 4 переменные модуля

 Dim xmldoc As New MSXML2.DOMDocument
Dim xmlDataMap() As DataNode
Dim xmlDataMapLast As Integer
Dim xmlTables As Collection
  

после вызова InsertLines все они стали пустыми, за исключением xmlDataMapLast, который содержит правильное значение 14.

Если я попытаюсь отладить этот метод, когда я перехожу к вызову InsertLines, я получаю сообщение об ошибке «В данный момент не удается перейти в режим прерывания». и я ничего не могу отладить, пока моя функция не завершится. Если я закомментирую вызов AddClickHandler_ShowSheet, мои переменные останутся нетронутыми, так что это должно быть что-то, связанное с этим вызовом.

Я пытаюсь достичь невозможного или просто делаю это неправильно?

Ответ №1:

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

Зачем вам хранить переменные в модуле, который вы используете для генерации кода?
Сохраните их в отдельном модуле и используйте этот модуль только для генерации кода.


С учетом сказанного, зачем вам вообще динамически добавлять код?
OnAction поддерживает параметры:

 Sub asdff()
  Worksheets(1).Buttons(1).OnAction = "'Module1.ParametrizedHandler 5, ""Hi there""'"
End Sub

Public Sub ParametrizedHandler(ByVal foo As Long, ByVal bar As String)
  MsgBox foo, vbInformation, bar
End Sub
  

Обратите внимание на отсутствие круглых скобок в строке вызова и одинарных кавычек вокруг нее.

Комментарии:

1. Спасибо. Вы спасаете жизнь. Я не знал, что могу использовать подобные параметры.

2. КСТАТИ. Кнопка была сгенерирована в модуле A. Функция, сгенерировавшая обработчик, находилась в модуле B, а обработчик был помещен в модуль C. Переменные находились в модуле A, поэтому я не думал, что добавление кода в модуль C повлияет на них. У вас есть какая-нибудь ссылка, которая могла бы немного прояснить, что на самом деле произошло?