簡體   English   中英

在 Access 中運行 Excel VBA

[英]Run Excel VBA in Access

我一直在研究這個問題,但我沒有找到任何關於它如何工作的線索。

我已經在 Excel 中編寫了我想在 MS Access 中運行的代碼。 我已經粘貼了我希望在 Access 中運行的代碼。

我找到的所有示例或信息均來自 2003 Access。 我正在使用 2016 Access。

Excel代碼

Public Function getworkbook()
    ' Get workbook...
    Dim ws As Worksheet
    Dim Filter As String
    Dim targetWorkbook As Workbook, wb As Workbook
    Dim Ret As Variant

    Application.DisplayAlerts = False

    Sheets("DATA").Delete
    '   Sheets("DATA").Cells.Clear

    Set targetWorkbook = Application.ActiveWorkbook

    ' get the customer workbook
    Filter = "Text files (*.xlsx;*.xlsb),*.xlsx;*.xlsb"
    Caption = "Please Select an input file "
    Ret = Application.GetOpenFilename(Filter, , Caption)

    If Ret = False Then Exit Function

    Set wb = Workbooks.Open(Ret)

    wb.Sheets(1).Move After:=targetWorkbook.Sheets(targetWorkbook.Sheets.Count)

    ' ActiveSheet.Paste = "DATA"

    ActiveSheet.Name = "DATA"

    ThisWorkbook.RefreshAll

    ' Application.Quit
    Application.DisplayAlerts = True

End Function

我在 Access 中找到並嘗試使用的代碼。

Public Function runExcelMacro(wkbookPath)
    Dim XL As Object
    Set XL = CreateObject("Excel.Application")
    With XL
        .Visible = False
        .displayalerts = False
        .Workbooks.Open wkbookPath
        'Write your Excel formatting, the line below is an example
        .Range("C2").value = "=1+2"
        .ActiveWorkbook.Close (True)
        .Quit
    End With
    Set XL = Nothing
End Function

您需要先處理幾個概念。

庫參考和范圍

您的原始代碼是用 Excel 編寫的。 因此,在該 VBA 項目中,它引用了 Excel 對象。 在您的 Access VBA 項目中,沒有引用它。 您可以通過查看Tools -> References來進行比較。

這給我們帶來了“早期綁定”和“后期綁定”的概念。 當您輸入Range. ,你會得到 VBA 的智能感知來告訴你你可以用一個Range或其他什么來做什么。 但是在 Access 中,默認情況下您沒有引用 Excel 對象庫。 因此, Range. 不會產生智能感知並且您無法運行代碼,因為 Access 在其對象模型中沒有Range ,並且您的 VBA 項目很可能沒有包含它的引用。

因此,如果您不想添加對 Excel 對象模型的引用,則需要調整您的代碼以運行后期綁定,而且您很可能確實想要這樣做。

不合格參考

您的原始 Excel 代碼包含對 Excel 對象模型中可用的各種全局對象的非限定引用。

Application.DisplayAlerts = False
...
Sheets("DATA").Delete
...
Set wb = Workbooks.Open(Ret)
...

這些不一定能在 Excel 以外的其他主機托管的 VBA 項目中始終如一地工作,而且大多數肯定不會在后期綁定代碼中工作。 此外,如果您選擇添加對 Excel 對象模型的引用,您最終仍會泄漏 Excel 實例,這可能會導致幻影實例,因為對全局對象的不合格引用將隱式創建一個您無法交互的 Excel 實例,這也可能導致路徑上的其他運行時錯誤。 為了讓你的代碼更晚綁定,你需要這樣的東西:

Set ExcelApp = CreateObject("Excel.Application")

ExcelApp.DisplayAlerts = False
...
Set MyBook = ExcelApp.Workbooks("Whatever")
MyBook.Sheets("DATA").Delete
...
Set wb = ExcelApp.Workbooks.Open(Ret)
...

請注意,您可以在 Excel 托管的上下文中訪問的所有全局對象現在必須是一個獨立的變量。 此外,您將無權訪問其他 VBA 項目中的ThisWorkbook甚至Sheet1 ,因為 Excel 不再是宿主。 您必須相應地進行調整。

在早期綁定和后期綁定之間切換

早期綁定代碼使您更容易開發,因為您可以獲得完整的智能感知和對象瀏覽器來幫助您編寫代碼。 但是,在引用其他對象模型時,您可能希望使用后期綁定來分發 VBA 代碼以避免版本控制問題和引用損壞。 但是您可以同時擁有兩個世界中最好的:

#Const EarlyBind = 1

#If EarlyBind Then
Dim ExcelApp As Excel.Application
#Else
Dim ExcelApp As Object
#End If

Set ExcelApp = CreateObject("Excel.Application")

這說明了使用條件編譯參數來允許您擁有ExcelApp變量,該變量可以是Excel.Application (又名早期綁定)與Object (又名后期綁定)。 要更改,只需將Const LateBind行更改為01之間。

首先,清理術語:

  • VBA 是一種獨立的語言,不依賴於任何MS Office 應用程序。 在 Tools\References 下,您會看到Visual Basic for Applications通常是第一個選中的對象。 在 Excel、Access、Word、Outlook 等中運行 VBA 的不同之處在於默認訪問它們的對象庫。 具體來說:

    • 只有Excel可以看到WorkbookWorksheet等而無需定義其來源
    • 只有Access可以看到FormsReports等而無需定義其來源
    • 只有Word可以看到DocumentsParagraphs等而不定義其來源
  • 當在應用程序中運行外部對象庫時,例如 MS Access 訪問 Excel 對象,您必須使用早期綁定或后期綁定通過引用定義和初始化外部對象:

     ' EARLY BINDING, REQUIRES EXCEL OFFICE LIBRARY UNDER REFERENCES Dim xlApp As Excel.Application Dim wb As Excel.Workbook Dim ws As Excel.Worksheet Set xlApp = New Excel.Application Set wb = xlApp.Workbooks.Open(...) Set ws = wb.Worksheets(1) ' LATE BINDING, DOES NOT REQUIRE EXCEL OFFICE LIBRARY UNDER REFERENCES Dim xlApp As Object, wb As Object, ws As Object Set xlApp = CreateObject("Excel.Application") Set wb = xlApp.Workbooks.Open(...) Set ws = wb.Worksheets(1)

話雖如此,只需保持原始代碼幾乎完好無損,但更改定義和初始化即可。 值得注意的是,所有Application調用現在都指向Excel.Application對象,不要與 Access 的應用程序混淆。 另外,避免.Select/.Activate/ Selection/ ActiveCell/ ActiveSheet/ ActiveWorkbook的最佳實踐。

Public Function getworkbook()
    ' Get workbook...
    Dim xlApp As Object, targetWorkbook As Object, wb As Object, ws As Object         
    Dim Filter As String, Caption As String
    Dim Ret As Variant

    Set xlApp = CreateObject("Excel.Application")
    Set targetWorkbook = xlApp.Workbooks.Open("C:\Path\To\Workbook.xlsx")

    xlApp.DisplayAlerts = False

    targetWorkbook.Sheets("DATA").Delete

    ' get the customer workbook
    Filter = "Text files (*.xlsx;*.xlsb),*.xlsx;*.xlsb"
    Caption = "Please Select an input file "
    Ret = xlApp.GetOpenFilename(Filter, , Caption)

    If Ret = False Then Exit Function    
    Set wb = xlApp.Workbooks.Open(Ret)

    wb.Sheets(1).Move After:=targetWorkbook.Sheets(targetWorkbook.Sheets.Count)    
    Set ws = targetWorkbook.Worksheets(targetWorkbook.Sheets.Count)
    ws.Name = "DATA"

    targetWorkbook.RefreshAll

    xlApp.DisplayAlerts = True
    xlApp.Visible = True                        ' LAUNCH EXCEL APP TO SCREEN
    ' xlApp.Quit

    ' RELEASE RESOURCEES
    Set ws = Nothing: Set wb = Nothing: Set targetWorkbook = Nothing: Set xlApp = Nothing
End Function

順便說一句,上面可以在任何MS Office 應用程序中運行,因為沒有使用父應用程序(這里是 MS Access)的對象!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM