2015-09-08 6 views
2

Я хочу, чтобы определить глобальную переменную как лист на открытие файла, так что я использовал следующий код:Глобальные переменные сбрасываются автоматически

В Module1:

Public mySheet As Worksheet 

В ThisWorkbook:

Sub Workbook_Open() 
    Set mySheet = Sheet1 
End Sub 

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

Работает изначально - когда я открываю файл, задается переменная, а макрос содержит mySheet.Unprotect, mySheet.Protect и mySheet.Range("A1"). Однако, когда я пытаюсь запустить его снова, я получаю сообщение об ошибке Object variable or With block variable not set, и отладка возвращает меня к строке mySheet.Unprotect, которая является ссылкой на первый раз.

Как я могу определить этот рабочий лист в глобальной переменной, чтобы определить это определение?

Для справки, конкретный макрос, я имею в виду ниже, хотя у меня была аналогичная проблема с различными битами кода:

Sub mySub() 
    mySheet.Unprotect 
    With Application.FileDialog(msoFileDialogOpen) 
     .AllowMultiSelect = False   
     If .Show <> 0 Then 
      mySheet.Range("A1") = .SelectedItems(1) 
     End If   
    End With 

    mySheet.Protect   
End Sub 
+0

определяют 'mysheet' как' 'constant' с sheet1', будет эта работа? – psychicebola

+0

@psychicebola VBA не поддерживает объектные константы, они должны быть инициализированы внутри процедуры. –

+0

Попробуйте [отладить] (http://www.cpearson.com/excel/DebuggingVBA.aspx) свой код, используя окно locals, чтобы узнать, что происходит с переменной. Тот факт, что он работает в первый раз, говорит мне, что что-то не так с процедурой - не то, как вы назначаете переменную. –

ответ

4

Лично я хотел бы предложить вам создать функцию, которая возвращает этот лист.Затем вы можете в основном использовать имя функции в качестве переменной Worksheet. (Хотя, если вы хотите всегда один и тот же лист можно просто использовать Sheet1 позывной)

Function MySheet() As Excel.Worksheet 
    Set MySheet = Sheet1 
End Function 

и использования, например:

Sub foo() 
    MsgBox MySheet.Name 
End Sub 
+0

Очень хорошая идея !!!! –

+0

Мне нравится эта идея, спасибо! – apkdsmith

1

here for a very similar post См ... Повторим, что там сказано, это поведение может быть вызвано следующими причинами:

  1. Использование «End» (не «End Sub», просто «End» заявление по себе).
  2. Unhandled ошибка во время выполнения (так что если какой-либо из вашего кода выдает ошибку, вы потеряете ваши глобальные переменные)
  3. Редактирование кода (включая нажатие на кнопку стоп)
  4. Закрыв книгу, содержащую проект VB (что-то вы исключено уже в разделе комментариев).

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

+0

Это должен быть комментарий. Каков ваш вклад? Вы просто перешли по ссылке, скопировали информацию и подвели ее! –

+0

Нет, это не должно быть комментарий, потому что он отвечает на вопрос, почему это происходит. Вы не хотите хоронить ответ в комментариях. Я могу самостоятельно самостоятельно проверить этот ответ и предпочесть включить ссылку, чтобы обосновать это. Это не просто копия и вставка, информация была добавлена ​​и оценена в соответствии с вопросом OP. Я предположил, что решение создания отдельной переменной переинициализации подпрограмма будет очевидна с учетом этой информации. – u8it

+0

Ваше последнее редактирование имеет больше смысла. Отменил нисходящий голос :) –

5

Как уже упоминалось в ссылке из другого ответа, вы можете понять, почему это происходит.

Вот что я хотел бы рекомендовать обойти проблему.

Создайте процедуру в модуле. Назовите это сказать, Init

Public mySheet As Worksheet 

Sub Init() 
    Set mySheet = Sheet1 
End Sub 

И тогда в вашем Workbook_Open() сделать это.

Sub Workbook_Open() 
    Init 
End Sub 

Теперь, где бы вы используете этот объект просто добавить еще одну строку

Sub mySub() 
    If mySheet is Nothing then Call Init '<== Add this 

    mySheet.Unprotect 

    With Application.FileDialog(msoFileDialogOpen) 
     .AllowMultiSelect = False 
     If .Show <> 0 Then 
      mySheet.Range("A1") = .SelectedItems(1) 
     End If 
    End With 
    mySheet.Protect 
End Sub 
+0

++ nice suggestion :) –

+0

Это хорошее обходное решение для рассмотрения, спасибо. – apkdsmith