[英]Run Excel VBA in Access
I have been researching this a great deal and I am not finding any leads to how this would work.我一直在研究这个问题,但我没有找到任何关于它如何工作的线索。
I have written code in Excel that I want to run in MS Access.我已经在 Excel 中编写了我想在 MS Access 中运行的代码。 I have pasted the code I wish to run in Access.
我已经粘贴了我希望在 Access 中运行的代码。
All the examples or information I have found is from 2003 Access.我找到的所有示例或信息均来自 2003 Access。 I am using 2016 Access.
我正在使用 2016 Access。
The Excel code 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
Code I found and tried to use in Access.我在 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
There are few concepts you need to deal with first.您需要先处理几个概念。
Your original code was written in Excel.您的原始代码是用 Excel 编写的。 Therefore, in that VBA project, it has Excel object referenced.
因此,在该 VBA 项目中,它引用了 Excel 对象。 In your Access VBA project, that is not referenced.
在您的 Access VBA 项目中,没有引用它。 You can compare this by looking at
Tools
-> References
.您可以通过查看
Tools
-> References
来进行比较。
That brings us to the concept of "early-binding" and "late-binding".这给我们带来了“早期绑定”和“后期绑定”的概念。 When you type in things like
Range.
当您输入
Range.
, you get VBA's intellisense to tell you what you can do with a Range
or whatever. ,你会得到 VBA 的智能感知来告诉你你可以用一个
Range
或其他什么来做什么。 But in Access, you don't have Excel object library referenced by default.但是在 Access 中,默认情况下您没有引用 Excel 对象库。 Therefore,
Range.
因此,
Range.
will not yield intellisense and you can't run the code because Access does not have Range
in its object model and your VBA project mostly likely don't have a reference that has it.不会产生智能感知并且您无法运行代码,因为 Access 在其对象模型中没有
Range
,并且您的 VBA 项目很可能没有包含它的引用。
Therefore, your code need to be adjusted to run late-bound if you do not want to add reference to Excel object model, and you most likely do want that anyway.因此,如果您不想添加对 Excel 对象模型的引用,则需要调整您的代码以运行后期绑定,而且您很可能确实想要这样做。
Your original Excel code contains unqualified references to various global objects that are available in Excel's object model.您的原始 Excel 代码包含对 Excel 对象模型中可用的各种全局对象的非限定引用。
Application.DisplayAlerts = False
...
Sheets("DATA").Delete
...
Set wb = Workbooks.Open(Ret)
...
Those won't necessarily work consistently in VBA projects hosted by other hosts other than Excel and most certainly won't work in late-bound code.这些不一定能在 Excel 以外的其他主机托管的 VBA 项目中始终如一地工作,而且大多数肯定不会在后期绑定代码中工作。 Furthermore, if you elect to add a reference to Excel's object model, you still end up leaking Excel instance which can cause ghost instances because unqualified references to the global objects will implicitly create an Excel instance that you can't interact and that can also cause other runtime error down the path.
此外,如果您选择添加对 Excel 对象模型的引用,您最终仍会泄漏 Excel 实例,这可能会导致幻影实例,因为对全局对象的不合格引用将隐式创建一个您无法交互的 Excel 实例,这也可能导致路径上的其他运行时错误。 To make your code more late-bindable, you need something like:
为了让你的代码更晚绑定,你需要这样的东西:
Set ExcelApp = CreateObject("Excel.Application")
ExcelApp.DisplayAlerts = False
...
Set MyBook = ExcelApp.Workbooks("Whatever")
MyBook.Sheets("DATA").Delete
...
Set wb = ExcelApp.Workbooks.Open(Ret)
...
Note how all global objects that you could have accessed in a Excel-hosted context now have to be a variable on its own.请注意,您可以在 Excel 托管的上下文中访问的所有全局对象现在必须是一个独立的变量。 Furthermore, you won't have access to
ThisWorkbook
or even Sheet1
in other VBA projects because Excel is no longer the host.此外,您将无权访问其他 VBA 项目中的
ThisWorkbook
甚至Sheet1
,因为 Excel 不再是宿主。 You must adjust accordingly.您必须相应地进行调整。
Early-bound code makes it much easier for you to develop since you get full intelisense and object browser helping you write the code.早期绑定代码使您更容易开发,因为您可以获得完整的智能感知和对象浏览器来帮助您编写代码。 However, when referencing other object models, you might want to distribute your VBA code using late-binding to avoid versioning problems and broken references.
但是,在引用其他对象模型时,您可能希望使用后期绑定来分发 VBA 代码以避免版本控制问题和引用损坏。 But you can have best from both worlds:
但是您可以同时拥有两个世界中最好的:
#Const EarlyBind = 1
#If EarlyBind Then
Dim ExcelApp As Excel.Application
#Else
Dim ExcelApp As Object
#End If
Set ExcelApp = CreateObject("Excel.Application")
This illustrates the use of conditional compilation argument to allow you to have ExcelApp
variable that can be either Excel.Application
(aka early-bound) vs. Object
(aka late-bound).这说明了使用条件编译参数来允许您拥有
ExcelApp
变量,该变量可以是Excel.Application
(又名早期绑定)与Object
(又名后期绑定)。 To change, you simply change the Const LateBind
line between 0
or 1
.要更改,只需将
Const LateBind
行更改为0
或1
之间。
First, to clear up terminology:首先,清理术语:
VBA is a separate language and not tied to any MS Office application. VBA 是一种独立的语言,不依赖于任何MS Office 应用程序。 Under Tools\References, you will see Visual Basic for Applications is usually the first checked object.
在 Tools\References 下,您会看到Visual Basic for Applications通常是第一个选中的对象。 What differs between running VBA inside Excel, Access, Word, Outlook, etc. is the default access to their object library.
在 Excel、Access、Word、Outlook 等中运行 VBA 的不同之处在于默认访问它们的对象库。 Specifically:
具体来说:
When running a foreign object library inside an application, such as MS Access accessing Excel objects, you must define and initialize the foreign objects via reference either with early or late binding:当在应用程序中运行外部对象库时,例如 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)
With that said, simply keep original code nearly intact but change definitions and initializations.话虽如此,只需保持原始代码几乎完好无损,但更改定义和初始化即可。 Notably, all
Application
calls now point to Excel.Application
object and not to be confused with Access' application.值得注意的是,所有
Application
调用现在都指向Excel.Application
对象,不要与 Access 的应用程序混淆。 Plus, best practices of avoiding .Select/.Activate/ Selection/ ActiveCell/ ActiveSheet/ ActiveWorkbook
.另外,避免
.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
By the way, above can be run in any MS Office application as no object of the parent application (here being MS Access) is used!顺便说一句,上面可以在任何MS Office 应用程序中运行,因为没有使用父应用程序(这里是 MS Access)的对象!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.