VBA 2 Вопросы, касающиеся переменной области и срока службы - PullRequest
0 голосов
/ 24 марта 2012

Я столкнулся с двумя проблемами, связанными с тем, что я пытаюсь сделать с VBA, касательно области действия и времени жизни переменной.вновь и вновь.Например, целое число, которое определяет столбец как столбец даты, cDate или приложение как приложение.Так как у меня есть большой раздел объявлений, я хотел поместить это в отдельный модуль, используя Global, но это не сработало.Имеет ли значение, как я устанавливаю здесь область действия процедуры?Как я могу это сделать?

Аналогично Q1, как насчет инициализации переменных?В частности, вместо того, чтобы копировать и вставлять один и тот же блок, который находит заголовки столбцов (например, cDate), я поместил его в свою собственную процедуру.Я сталкиваюсь со многими проблемами, пытаясь заставить это работать.Я надеюсь, что это возможно, а может и нет.

Скажите, если вам нужно увидеть код.Скажи мне, что ты хочешь увидеть, и я бросаю это здесь.(PS- Я прошел через Справку VBA, MSDN, Goole и т. Д., И здесь я кое-что не понимаю)

Редактировать: добавить отредактированный код, потому что реальная вещь довольно длинная.Все разделы находятся в отдельных стандартных модулях.Я прочитал, что Глобальные объявления работают только на уровне рабочей книги и ниже, поэтому я также попытался объявить и установить app, wb и wrk как Public в каждом модуле (здесь не показано): Вот мои объявления:

Option Explicit

Global app As Application
Global wb As Workbook
Global wrk As Worksheet

Global cInvoice As Byte

Global iEndCol As Integer
Global lEndRow As Long
Global x As Integer

Global sString1 As String

Global rng As Range

Private Sub Not_Really_a_sub()
    'No code. I read that any declaration needed to be in a module 
    ' with a procedure. I tried it with out the dummy sub also
End Sub
 'green text, read me and notes

И сабвуфер, который выполняет вызов:

   Dim modulevariables As Integer

Sub Calling_Sub()

 'doing things

 lEndRow = 1 'blah blah blah
 iEndCol = 1 ' blah blah blah
 app.Run "'" & ThisWorkbook.Name & "'!Header_Finder"

  'Code using cInvoice etc.

End Sub

И искатель заголовка:

Private Sub Header_Finder()
  With wb.ActiveSheet
    For x = 1 To iEndCol
        If InStr(UCase(.Cells(x, 1)), UCase("Invoice")) > 0 Then
            cInvoice = x
        ElseIf .Cells(1, x) = "next thing" Then
            cNextThing = x
        End If
    Next
 End With
End Sub

Спасибо уже.

Ответы [ 3 ]

2 голосов
/ 24 марта 2012

Поскольку это не относится к моему другому (не) ответу, но еще раз мне нужно включить код, я добавлю его сюда.

В вашем модуле "переменных" вы объявляете переменных:

dim wb as Workbook

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

set wb = ThisWorkbook
set wb = ActiveWorkbook
set wb = Application.Workbooks(1)

Если вы не инициализируете эту переменную перед обращением к ней, как в этом примере:

dim wb as Workbook
debug.print wb.name

Вы получите сообщение об ошибке: «Ошибка времени выполнения 91»: переменная объекта или переменная блока не установлена ​​»

Только объектные переменные требуют инициализации. Другие типы данных нет. Проще говоря, необъектные типы данных следующие. Значения по умолчанию (инициализируются при объявлении) заключены в скобки:

  • Целое число [0]
  • Long [0]
  • String [""]
  • Двойной [0]
  • Single [0]
  • Дата [0 или 30 декабря 1899 г.]
  • байт [0]
  • Boolean [False]
  • Валюта [$ 0]

Все остальное является объектом и требует некоторой инициализации. Вот пример:

Option Explicit

Dim wb as Workbook
Dim app as Excel.Application
Dim wrk as Worksheet

Set app = Application
Set wb = app.workbooks(1)
Set wrk = wb.sheets(1)

'If any of the lines preceding this line are skipped, an error will occur.
debug.print wrk.name

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

1 голос
/ 24 марта 2012

Не совсем ответ, но мне нужно было включить код.В качестве теста я поместил следующий код в один модуль (Module1):

Public wb As Workbook

И этот код в другом модуле (Module2):

Sub test()

    Set wb = ThisWorkbook
    Debug.Print wb.Name

End Sub

У меня это работало нормально.Можете ли вы попытаться сделать то же самое в новой книге, и дайте мне знать, как это происходит?Кроме того, вы можете попробовать более явно указать, на какие переменные вы ссылаетесь, например, так (все еще в Модуле 2):

Sub test()

    Set wb = ThisWorkbook
    Debug.Print Module1.wb.Name

End Sub
1 голос
/ 24 марта 2012

Q1.

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

Чтобы объявить переменную на уровне модуля, просто объявите ее вне первой процедуры, например

Dim app As Application

Sub mySub()
...

Эта переменная будет доступна для всех процедур в модуле.Чтобы сделать переменную доступной для процедур в других модулях, вы можете использовать публичное объявление, например,

Public app As Application

Sub mySub()
....

Q2.

Самый простой способ сделать это, если есть процедура, которая инициализирует переменные, которые могутвызываться из других процедур по мере необходимости.Например, приведенный ниже код создает открытую переменную с именем PubStr и инициализирует ее в первой процедуре, которая вызывается из второй.

Option Explicit
Public PubStr As String

Sub InitVar()
PubStr = "Hello World!"
End Sub

Sub RunMe()
Call InitVar
MsgBox PubStr
End Sub

Запуск «RunMe» вызовет процедуру InitVar, которая инициализирует открытую переменную PubStr.

Надеюсь, это поможет.

...