programing

워크북을 전역 변수로 선언

bestprogram 2023. 6. 26. 21:32

워크북을 전역 변수로 선언

여러 워크북에 적용할 수 있는 코드를 작성하기 시작했지만 항상 동일한 참조 워크북을 사용합니다.코드에는 많은 하위 항목이 포함될 것이며, 모든 하위 항목의 참조 워크북에 대한 변수가 희미해지는 것을 방지하기 위해 글로벌로 선언하고 싶습니다.

처음에는 다음과 같이 했습니다.

Global Locations As Excel.Workbook
Set Locations = Workbooks.Open("M:\My Documents\MSC Thesis\Italy\Merged\locXws.xlsx")

그래서 나는:

"컴파일 오류:잘못된 외부 절차"

몇 번 검색한 결과 다음과 같은 코드가 어딘가에 이르렀습니다.

Public Const Locations As Excel.Workbook = "Workbooks.Open("M:\My Documents\MSC Thesis\Italy\Merged\locXws.xlsx")"

그래서 나는:

"컴파일 오류: 예상: 유형 이름"


편집:

사용:

Public Const Locations As Excel.Workbook = "Workbooks.Open('M:\My Documents\MSC Thesis\Italy\Merged\locXws.xlsx')"

(워크북에 따옴표가 하나 있습니다.열린 문)은 큰따옴표를 사용할 때와 동일한 오류로 결과가 나타납니다.

내가 뭘 잘못하고 있는지 누가 알겠어요?

편집 2:

저는 또한 다음을 사용하여 이 답변에 따라 "이 워크북"의 변수를 선언하려고 했습니다.

Private Sub Workbook_Open()
Dim Locations As Excel.Workbook
Dim MergeBook As Excel.Workbook
Dim TotalRowsMerged As String


Locations = Workbooks.Open("M:\My Documents\MSC Thesis\Italy\Merged\locXws.xlsx")
MergeBook = Workbooks.Open("M:\My Documents\MSC Thesis\Italy\Merged\DURUM IT yields merged.xlsm")
TotalRowsMerged = MergeBook.Worksheets("Sheet1").UsedRange.Rows.Count
End Sub

하지만 그 다음에 그것은 반환합니다.

"필요한 개체"

내 모듈 내에서.

편집 3:

저는 이제 작동하는 이것을 가지고 있지만, 모든 서브에 SET 라인을 복사해야 하는 단점이 있는데, 이것을 하는 더 나은 방법이 있어야 합니까?

Global Locations As Workbook
Global MergeBook As Workbook
Global TotalRowsMerged As String

Sub Fill_CZ_Array()
Set Locations = Application.Workbooks("locXws.xlsx")
Set MergeBook = Application.Workbooks("DURUM IT yields merged.xlsm")
TotalRowsMerged = MergeBook.Worksheets("Sheet1").UsedRange.Rows.Count

합니다.Public Property Get절차. 부르지할 수 , 이 열려 가 없습니다코드를 호출하지 않고 먼저 참조할 수 있으며, 파일이 열려 있는지 여부에 대해 걱정할 필요가 없습니다.

다음은 변수 중 하나에 대한 샘플 모듈 코드입니다.

Private wLocations As Workbook

Public Property Get Locations() As Workbook
  Const sPath As String = "M:\My Documents\MSC Thesis\Italy\Merged\locXws.xlsx"
  Dim sFile As String

  If wLocations Is Nothing Then
      'extract file name from full path
      sFile = Dir(sPath)

      On Error Resume Next

      'check if the file is already open    
      Set wLocations = Workbooks(sFile)

      If wLocations Is Nothing Then
        Set wLocations = Workbooks.Open(sPath)
      End If

      On Error GoTo 0
  End If
  Set Locations = wLocations
End Property

코드의 모든 위치에서 글로벌 변수로 사용할 수 있습니다.

Sub Test()
  Debug.Print Locations.Worksheets.Count
End Sub

이 질문은 변수가 아니라 전역 워크북 상수를 원한다는 것을 의미합니다.VBA에서는 프로시저 외부에서 개체를 초기화할 수 없으므로 개체 상수를 지정할 수 없습니다.가장 좋은 방법은 이벤트에서 초기화되는 공개 워크북 변수를 사용하는 것입니다.


글로벌 변수를 선언할 수는 있지만 프로시저 외부에 값을 할당하는 코드를 실행할 수는 없습니다.

Public myBook As Excel.Workbook

Sub AssignWorkbook()
    Set myBook = Workbooks.Open("C:\SomeBook.xlsx") '// <~~ valid, inside sub
End Sub

Sub TestItWorked()
    MsgBox myBook.Name
End Sub

따라서 일반 모듈에서는 다음을 수행할 수 있습니다.

Public myBook As Excel.Workbook

그리고 당신의 안에서Workbook_Open() 트이벤::

Private Sub Workbook_Open()
    Set myBook = Workbooks.Open("C:\SomeOtherBook.xlsx")
End Sub

그러면 사용할 수 있습니다.myBook코드의 다른 곳에서 다시 검색할 필요가 없습니다.

여기에서 VBA의 다양한 범위에 대한 Chip Pearson의 기사를 볼 가치가 있습니다.

당신이 원하는 것은 정적 속성을 가진 팩토리의 일종입니다. 예를 들어, 별도의 모듈에 있습니다.

mFactoryWkbs

Private m_WkbLocations           As Workbook
Private m_WkbMergeBook           As Workbook

Public Property Get LOCATIONS() As Workbook
    If m_WkbLocations Is Nothing Then
        Set m_WkbLocations= Workbooks.Open("wherever")
    End If
    Set LOCATIONS = m_WkbLocations
End Property

Public Property Get MERGEBOOK () As Workbook
    If m_WkbMergeBook Is Nothing Then
        Set m_WkbMergeBook = Workbooks.Open("wherever")
    End If
    Set MERGEBOOK = m_WkbMergeBook 
End Property

사용하려면 필요한 위치와 시간에 속성을 호출하기만 하면 됩니다. 추가 변수(또는 변수에 대한 집합)가 필요하지 않습니다.

TotalRowsMerged = MERGEBOOK.Worksheets("Sheet1").UsedRange.Rows.Count

이것이 지금까지 제가 생각해낼 수 있는 최선입니다.그 결과 이제 파일 이름을 변경할 수 있는 위치가 하나뿐이지만 모든 서브루틴 내에서 SET 기능을 복사해야 합니다.아직 완벽하게 이상적이지는 않지만 없는 것보다는 낫습니다.

Public Const DESTBOOK = "DURUM IT yields merged.xlsm"

Global Locations As Workbook
Global MergeBook As Workbook
Global TotalRowsMerged As String

Sub Fill_CZ_Array()
Set Locations = Application.Workbooks("locXws.xlsx")
Set MergeBook = Application.Workbooks(DESTBOOK)
TotalRowsMerged = MergeBook.Worksheets("Sheet1").UsedRange.Rows.Count

이 문제가 발생할 때마다 wb를 공용 상수 문자열로 선언합니다.

public wb as string = "c:\location"

그런 다음 프로젝트의 코드 전체에서 다음을 참조할 수 있습니다.

workbooks(wb).anything

글로벌 변수를 적절하게 초기화해야 할 때 주로 수행하는 작업입니다.

일반 코드 모듈에 다음 코드를 입력합니다.

Public Initialized As Boolean
Public Locations As Workbook

Sub Initialize()
    If Initialized Then Exit Sub
    Const fname As String = "M:\My Documents\MSC Thesis\Italy\Merged\locXws.xlsx"
    On Error Resume Next
        Set Locations = Workbooks(Dir(fname))
    On Error GoTo 0
    If Locations Is Nothing Then
        Set Locations = Workbooks.Open(fname)
    End If
    Initialized = True
End Sub

그런 다음 워크북의 코드 모듈에 다음을 입력합니다.

Private Sub Workbook_Open()
    Initialize
End Sub

할 수 또는 이벤트 핸들러,에 " " " 게웨이예수" " 또기에능또" " 는트러핸등하위서다" (" 이벤들트다", UDF 니합입")를 합니다.Initialize(또는 아마도:If Not Initialized Then Initialize를 첫 번째줄로 합니다.를 첫 번째 줄로 지정합니다.일반적으로 대부분의 서브스크립션은 직접 시작되지 않으며 사용할 수 있습니다.Locations호출자가 적절하게 설정하는 중입니다.되어 있지 않는 해야 할 에는 변가설지않은경제실우대행않로지되는다항입테니합력같하이경는다우음야과해수스트목을정되를 입력하면 .initialize즉시 창에 직접 표시됩니다.

클래스 모듈을 사용하여 이 작업을 수행하고 클래스 이니셜라이저를 사용하여 모듈에 사용할 때 작업을 수행할 수도 있습니다.

cLocations라는 클래스 모듈:

Public Workbook As Workbook

Private Sub Class_Initialize()
    Set Workbook = Workbooks.Open("C:\Temp\temp.xlsx")
End Sub

모듈에서 원하는 위치 또는 해당 사항에 대해 원하는 위치:

Dim Locations As New cLocations

Sub dosomething()
    Locations.Workbook.Sheets(1).Cells(1, 1).Value = "Hello World"
End Sub

그런 다음, 그냥 사용할 수 있습니다.Locations.Workbook워크북 및 워크북을 하십시오.ThisWorkbook 중인 합니다.ActiveWorkbook포커스가 있는 워크북을 참조합니다.코드를 할 수 .ThisWorkbook), 워크북()을 Locations.Workbook)을하여 다른 ActiveWorkbook를하여 자동화 수준을 할 수 있습니다.을 클릭하여 자동화 수준을 클릭합니다.

코드를 단계별로 살펴보면 워크북을 로드할 때가 아니라 해당 코드가 필요한 코드 라인을 누를 때만 클래스가 초기화된다는 것을 알 수 있습니다.

하지만 이 경우에 당신이 달성하고자 하는 것에 대해 조금 더 큰 그림을 제시해 주신다면 코딩 중에 부딪힌 문제보다 더 나은 해결책을 제시할 수 있을 것이라고 생각합니다.

또한 한 단계 더 나아가 응용프로그램 수준으로 추상화하고 위치 워크북을 숨겨두며 이름이 지정된 시트의 위치나 이름을 명시적으로 알고 있는 경우에도 해당 시트에 대한 인텔리전스를 제공할 수 있습니다.

클래스 모듈:

Private App As Application
Public Workbook As Workbook
Public NamedSheet As Worksheet

Private Sub Class_Initialize()
    Set App = New Application
    App.Visible = False
    App.DisplayAlerts = False
    Set Workbook = App.Workbooks.Open("C:\Temp\temp.xlsx") 'maybe open read only too?
    Set NamedSheet = Workbook.Sheets("SomethingIKnowTheNameOfExplicitly")
End Sub

Public Sub DoSomeWork()
    'ThisWorkbook refers to the one the code is running in, not the one we opened in the initialise
    ThisWorkbook.Sheets(1).Cells(1, 1).Value = Wb.Sheets(1).Cells(1, 1).Value
End Sub

Public Function GetSomeInfo() As String
    GetSomeInfo = NamedSheet.Range("RangeIKnowTheNameOfExplicitly")
End Function

그런 다음 모듈에서 변수를 처음 사용하면 코드 한 줄로 초기화됩니다.

Dim Locations As New cLocations
Dim SomeInfo

Sub DoSomething()
    SomeInfo = Locations.GetSomeInfo 'Initialised here, other subs wont re-initialise

    Locations.Workbook.Sheets(1).Cells(1, 1).Value = _ 
        ThisWorkbook.Sheets(1).Cells(1, 1).Value

    Locations.NamedSheet.Cells(1,1).Value = "Hello World!"

    Locations.Workbook.Save
End Sub

이 솔루션은 참조된 워크북에서 사용할 모든 워크시트의 번호와 이름을 알고 있는 경우에만 작동합니다.

모듈에서 모든 워크시트에 대해 워크시트 공용 변수를 다음과 같이 선언합니다.

Public sht1 As Worksheet
Public sht2 As Worksheet
Public sht3 As Worksheet
...

응용 프로그램 로드 이벤트에서 이러한 공개 변수를 인스턴스화합니다.

Sub Workbook_Open()

    Workbooks.Open ("your referenced workbook")

    'Instantiate the public variables
    Set sht1 = Workbooks("Test.xlsm").Sheets("Sheet1")
    Set sht2 = Workbooks("Test.xlsm").Sheets("Sheet2")
    Set sht3 = Workbooks("Test.xlsm").Sheets("Sheet3")

End Sub

이제 서브에서 이러한 글로벌 워크시트를 참조할 수 있습니다.

예:

Sub test()
    MsgBox sht1.Range("A1").Value
    MsgBox sht2.Range("A1").Value
    MsgBox sht3.Range("A1").Value
End Sub

모듈을 생성하면 ExcelMod라고 하며 해당 모듈 내에 공용 함수 또는 서브루틴 Initialize()가 있고 Terminate()라고 하는 또 다른 서브루틴이 있으면 이러한 루틴을 사용하여 모듈 수준 변수를 초기화하고 종료할 수 있습니다.예를 들어 이전에 사용한 적이 있습니다. (모듈 변수는 모듈의 맨 위에 선언된 첫 번째 항목입니다.)

Dim excelApp As Object, wb As Workbook, ws As Worksheet

Sub Initialize()
    Set excelApp = CreateObject("Excel.Application")
    Set wb = Workbooks.Open("C:\SomeOtherBook.xlsx")
End Sub

Sub Terminate()
    Set excelApp = Nothing
    Set wb = Nothing
End Sub

변수는 전체 모듈의 일부이며 이러한 서브루틴으로만 초기화 및 종료됩니다.변수를 원하는 대로 모듈 안팎으로 전달하여 다시 설정할 필요 없이 이 모듈의 모든 서브루틴에서 사용할 수 있습니다.다른 모듈에서 사용해야 하는 경우에는 일반적으로 사용하는 것처럼 해당 모듈로 전달해야 합니다.

또한 다른 사람들이 언급했듯이 workbook_Open 이벤트를 사용하여 초기화 서브를 호출하여 개체를 만들고 필요한 경우 한 번만 설정할 수 있습니다.

이게 당신이 노리는 건가요?

제가 질문을 올바르게 이해했다면 워크북 수준이 아닌 응용프로그램 수준에서 작동해야 하는 코드를 생성한 것입니다.이런 경우에는 추가 기능을 생성하는 것이 어떻습니까?

추가 기능 내의 모든 코드는 응용 프로그램 수준에서 열려 있는 모든 워크북에 액세스할 수 있습니다.

추가 기능을 만들거나 클래스 모듈을 사용하여 속성 작업을 수행할 수 있습니다.

하지만 일반 모듈에서 간단한 선언하고 워크북을 해당 절차를 호출하는 것보다 더 깔끔할 것이라고 확신하지 않습니다.

(저는 이 방법을 꽤 오랫동안 사용해 왔고 신경 쓰지 않았습니다.)

따라서 기능은 (전용이든 비전용이든) 일반 모듈에서 사용할 수 있습니다.

'Set the path to your files
Public Const DESTBOOK = "M:\My Documents\MSC Thesis\Italy\Merged\DURUM IT yields merged.xlsm"
Public Const LOCBOOK = "M:\My Documents\MSC Thesis\Italy\Merged\locXws.xlsx"

'Declare all global and public variables
Global Locations As Workbook
Global MergeBook As Workbook
Global TotalRowsMerged As String

'Set all variable (Procedure call from Workbook_Open)
Sub Set_All_Global_Variables()
    Set Locations = Set_Wbk(LOCBOOK)
    Set MergeBook = Set_Wbk(DESTBOOK)
    TotalRowsMerged = MergeBook.Worksheets("Sheet1").UsedRange.Rows.Count
    '...
End Sub

'Function to check if the workbook is already open or not
Function Set_Wbk(ByVal Wbk_Path As String) As Workbook
    On Error Resume Next
        Set Set_Wbk = Workbooks(Dir(Wbk_Path))
    On Error GoTo 0
    If Set_Wbk Is Nothing Then
        Set Set_Wbk = Workbooks.Open(Wbk_Path)
    End If
End Function

그리고 이 워크북 모듈의 모든 변수를 설정하는 절차를 호출합니다.

Private Sub Workbook_Open()
    Set_All_Global_Variables
End Sub

언급URL : https://stackoverflow.com/questions/31536519/declare-a-workbook-as-a-global-variable