[英]Using MS Access to run code in excel vba
我使用訪問前端從 SQL Server 中提取查詢。 然后我將記錄集導出到一個新的 Excel 工作簿。 然后我想使用 excel 來運行我在 Access 中的代碼。 它只是遍歷單元格並添加格式並檢查某個值。 我可以從訪問中運行它,它將讓工作簿打開循環。 然而,它是痛苦的緩慢。
如果我進入excel並粘貼訪問正在運行的代碼以進行格式化並檢查。 它在幾秒鍾內運行。 但是從 access 運行它需要 10 多分鍾。
如果可以做到這一點,有人有任何想法嗎?
我已將此代碼放在 Excel 的“ThisWorkbook”對象中:
Public Sub TestScript()
Debug.Print "Hello"
End Sub
然后使用表單上的按鈕從 Access 成功調用它:
Private Sub cmdRunExcel_Click()
Dim xl As Excel.Application
Set xl = CreateObject("Excel.Application")
xl.Visible = True
xl.Workbooks.Open "C:/Your/FolderPath/And/FileName.xlsx", True, False
xl.Run "ThisWorkbook.TestScript"
Set xl = Nothing
End Sub
不可否認,我沒有給它很多代碼來運行,但這里的代碼至少在 Excel 上運行,從 Excel ......這肯定比嘗試從 Access 在 Excel 上運行代碼要好。
更新:看看您是否可以通過測試從 Access 到 Excel 創建模塊(我無法正確測試它,因為我使用的是工作計算機,而且由於安全設置,它似乎不允許我運行此類代碼)
Private Sub cmdRunExcel_Click()
Dim xl As Excel.Application
Dim myWrkBk As Excel.Workbook
Dim myModule As VBComponent
Dim strVb As String
Set xl = CreateObject("Excel.Application")
xl.Visible = True
xl.Workbooks.Open "C:/Your/FolderPath/And/FileName.xlsx", True, False
Set myWrkBk = xl.Workbooks.Add
Set myModule = myWrkBk.VBProject.VBComponents.Add(vbext_ct_StdModule)
strVb = "Public Sub TestScript()" & vbCrLf _
& "Debug.Print 'Hello'" _
& "End Sub"
myModule.CodeModule.AddFromString strVb
' xl.Run "ThisWorkbook.TestScript"
Set myModule = Nothing
Set myWrkBk = Nothing
Set xl = Nothing
End Sub
如果您希望在 Excel 中運行的代碼始終相同,請打開一個 Excel 模板,其中包含一個宏工作簿,其中包含您的代碼。 然后,從 Access 中,您可以運行一系列宏,當然,如果只將一個宏傳遞給參數數組,則只運行一個宏:
Function RunExcelMacros( _
ByVal strFileName As String, _
ParamArray avarMacros()) As Boolean
Debug.Print "xl ini", Time
On Error GoTo Err_RunExcelMacros
Static xlApp As Excel.Application
Dim xlWkb As Excel.Workbook
Dim varMacro As Variant
Dim booSuccess As Boolean
Dim booTerminate As Boolean
If Len(strFileName) = 0 Then
' Excel shall be closed.
booTerminate = True
End If
If xlApp Is Nothing Then
If booTerminate = False Then
Set xlApp = New Excel.Application
End If
ElseIf booTerminate = True Then
xlApp.Quit
Set xlApp = Nothing
End If
If booTerminate = False Then
Set xlWkb = xlApp.Workbooks.Open(FileName:=strFileName, UpdateLinks:=0, ReadOnly:=True)
' Make Excel visible (for troubleshooting only) or not.
xlApp.Visible = False 'True
For Each varMacro In avarMacros()
If Not Len(varMacro) = 0 Then
Debug.Print "xl run", Time, varMacro
booSuccess = xlApp.Run(varMacro)
End If
Next varMacro
Else
booSuccess = True
End If
RunExcelMacros = booSuccess
Exit_RunExcelMacros:
On Error Resume Next
If booTerminate = False Then
xlWkb.Close SaveChanges:=False
Set xlWkb = Nothing
End If
Debug.Print "xl end", Time
Exit Function
Err_RunExcelMacros:
Select Case Err
Case 0 'insert Errors you wish to ignore here
Resume Next
Case Else 'All other errors will trap
Beep
MsgBox "Error: " & Err & ". " & Err.Description, vbCritical +
vbOKOnly, "Error, macro " & varMacro
Resume Exit_RunExcelMacros
End Select
End Function
另外,請注意您 - 如上所示 - 必須非常嚴格地以正確的順序打開、使用和關閉 Excel 對象。 沒有 ActiveWorkbook 等。
基於 Matt Hall 的回答,但進行了更改以展示如何從 Access 中:
ThisWorkbook
之外的 Excel 模塊; 在 Excel 中名為basTextModule
的自定義模塊中:
Public Sub ShowCoolMessage()
MsgBox "cool"
End Sub
' Add02 is explictly ByRef (the default in VBA) to show that
' the parameter will be altered and have its value changed even for
' prodedures higher up the call stack.
Public Function GetCoolAmount(Add01 As Variant, _
Optional ByRef Add02 As Integer) As Integer
Add02 = Add02 + 1
GetCoolAmount = 10 + Add01 + Add02
End Function
在訪問中:
對於通過引用傳遞的參數工作:
請注意Microsoft Docs 中的 Application.Run 方法 (Excel) ,當您將參數傳遞給 Excel Sub 或函數時,“您不能在此方法中使用命名參數。參數必須按位置傳遞”。
聲明excelApp 時使用Object
而不是Excel.Application
以確保可以檢索通過引用傳遞給 excelApp.Run 的任何參數的值。 資料來源:Jaafar Tribak“Application.Run ..(Argument Passed ByRef)”在https://www.mrexcel.com/board/threads/application-run-argument-passed-byref.998132/post-4790961
在被調用的 sub 或 Function 中,參數(除了第一個ModuleAndSubOrFunctionName
)必須具有與調用模塊或函數的參數的數據類型匹配的數據類型。 它們可以是變體或特定的數據類型。 例如,出於說明目的, Arg02
是一個整數,因此在使用RunExcelCode(WorkbookPathAndFileName, "basTestModule.GetCoolAmount" ...)
時必須是GetCoolAmount
的第二個參數。
但是,為了使您的RunExcelCode
更通用,最好確保Arg01
、 Arg02
、 ... Arg30
參數都是變體; 因此,您最終調用的 sub 或 function 的參數也是變體,例如 ...
Public Function GetCoolAmount(Add01 As Variant, _ Optional ByRef Add02 As Variant) As Integer ...
Public Function RunExcelCode(WorkbookPathAndFileName As String, _
ModuleAndSubOrFunctionName As String, _
Optional ByRef Arg01 As Variant, _
Optional ByRef Arg02 As Integer) As Variant
' Must be Object, not Excel.Application, to allow for parameters pass by reference
Dim excelApp As Object
Dim workbook As Excel.workbook
Dim Result As Variant
On Error GoTo HandleErr
' Can be Excel.Application if excelApp previously declared as Object
Set excelApp = New Excel.Application
' excelApp.Visible = True ' For debugging
Set workbook = excelApp.Workbooks.Open(WorkbookPathAndFileName)
' Get a value from a function or,
' if it is a sub a zero length string "" will be returned
Result = excelApp.Run(ModuleAndSubOrFunctionName, Arg01, Arg02)
RunExcelCode = Result
ExitHere:
workbook.Close
excelApp.Quit
Set workbook = Nothing
Set excelApp = Nothing
Exit Function
HandleErr:
Select Case Err.number
Case Else
MsgBox "Error " & Err.number & ": " & Err.Description, _
vbCritical, "RunExcelCode"
End Select
Resume ExitHere
End Function
測試(來自 Access),調用一個 Sub 和一個函數:
Private Sub TestRunExcelCode()
Dim WorkbookPathAndFileName As String
Dim Result As Variant
WorkbookPathAndFileName = "C:\Users\YourName\Documents\MyWorkbook.xlsm"
' Run a sub
Result = RunExcelCode(WorkbookPathAndFileName, "basTestModule.ShowCoolMessage")
If IsNull(Result) Then
Debug.Print "{Null}"
ElseIf Result = "" Then
Debug.Print "{Zero length string}"
Else
Debug.Print Result
End If
' Will output "{Zero length string}"
' Get a value from a function
Dim Arg02 As Integer
Arg02 = 1
Debug.Print "Arg02 Before: " & Arg02
Result = RunExcelCode(WorkbookPathAndFileName, _
"basTestModule.GetCoolAmount", 1, Arg02)
Debug.Print "Arg02 After : " & Arg02 ' Value will have changed, as desired.
Debug.Print "Result : " & Result
End Sub
編輯 01:主要更改以使代碼更通用。
編輯 02:處理通過引用傳遞的參數的重大更改。
編輯 03:在“使您的 RunExcelCode 更通用”的情況下添加了詳細信息。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.