簡體   English   中英

使用 VBA OpenRecordset 從 Access Query 到 Excel 的用戶定義函數 (UDF) 失敗 - 未定義函數

[英]User Defined Functions (UDF) from Access Query to Excel using VBA OpenRecordset failed - Undefined Function

如果有 UDF,如何將查詢結果從 Access 獲取到 Excel?

我收到以下錯誤:“運行時錯誤‘3085’:表達式中未定義函數‘XXXX’ ”。 從 Excel VBA 打開(訪問查詢)記錄集時發生錯誤。 正在打開的查詢具有觸發錯誤的用戶定義函數 (UDF)。

代碼在 Excel Office 365 中。查詢在 Access Office 365 中。

我已經成功地使用了被調用的查詢(以及其他使用 UDF 的查詢)大約 12 個月,並且“突然”它不再起作用了。 我用谷歌搜索並測試了許多選項,但沒有成功。

大多數線程說它不能完成,或者不使用 udf 而是嘗試一個有效的內置函數。 我對這些回應提出質疑,因為它以前奏效過。 我使用的主要 udf 是一種稱為“iMax”的 udf,它在其他帖子中有所提及。 它的功能類似於 Excel 中的 max()。 Access 中沒有 max(x,y) 函數

我還看到建議分兩步執行此操作的線程: 1 - 將查詢更改為生成表查詢。 2 - 將表格結果拉入 Excel。 雖然我可能可以擺脫這個(經過大量返工),但它會導致我制作許多包含成千上萬行的臨時表,並且看起來不太光滑。

我已經編譯了 vba 並壓縮了數據庫,對我的問題沒有影響。

作為一個長鏡頭,我創建了一個虛擬數據庫,其中包含一個返回數字 1 的簡單 udf 公共函數、一個返回三個記錄的簡單查詢和一個函數結果字段。 拉入 Excel 時會出現相同的錯誤。

Sub RunQuery()
Dim MyDatabase As dao.Database
Dim qdf As dao.QueryDef
Dim rs As dao.Recordset
Dim qryname As object
Dim SheetName As String

Set MyDatabase = DBEngine.OpenDatabase _
("SomePath\SomeFilename.accdb")

For Each qryname In Range("SomeRange")
    Set rs = MyDatabase.OpenRecordset(qryname)      '<<<ERROR IS HERE
    SheetName = "SomeSheetName"
        With Sheets(SheetName)
            .ListObjects(SomeTableName).DataBodyRange.Rows.ClearContents
            .Range("A2").CopyFromRecordset rs
        End With
    Set rs = Nothing
    Set qdf = Nothing
Next qryname

End Sub

對於 For 循環中沒有 udf 的所有查詢,結果將被拉取並轉儲到 Excel 中的一系列表中。 在“Set rs = Mydatabase.OpenRecordset(qryname)”中出現 udf 錯誤的任何查詢

大多數線程說它不能完成,

他們是對的。

您唯一的選擇是使用自動化打開 Access 實例,並在其中運行查詢。

如果您在 Access 應用程序會話中運行查詢,如 Gustav 建議的那樣,表達式服務可以處理查詢中的 UDF。

這是一個快速測試的 Excel VBA 代碼段,它從包含 UDF 的查詢中提取數據:

Const cstrDbFile As String = "C:\share\Access\Database2.accdb"
Dim objAccess As Object
Dim rs As Object
Dim ws As Worksheet
Dim strSelect As String

Set objAccess = CreateObject("Access.Application")
objAccess.Visible = True ' useful during testing '
objAccess.OpenCurrentDatabase "C:\share\Access\Database2.accdb"
strSelect = "SELECT ID, DummyFunction('a', '', 'c') FROM Dual;"
Set rs = objAccess.CurrentDb.OpenRecordset(strSelect)
If Not rs.EOF Then
    Set ws = ThisWorkbook.Sheets("Sheet1")
    ws.Range("A1").CopyFromRecordset rs
End If
rs.Close
objAccess.Quit

好吧,如前所述,大多數人都說這不應該起作用。

但是,如果您 100% 確定它曾經並且曾經有效嗎?

您需要設置 JET(現在是 ACE)數據庫引擎的“沙箱”模式。

表達式服務通常不允許將 VBA 函數求值作為防止 SQL 注入的安全設置,也不允許在 Access 之外運行代碼以允許 SQL 運行 + 調用 VBA 函數。 曾經,此功能確實默認為“開啟”,但現在默認設置為僅訪問。

您必須將 Access 應用程序所在的文件夾設置為受信任。 這應該允許 VBA 函數現在工作。 因此,請確保將文件夾設置為受信任。

如果您的訪問應用程序所在的位置(文件夾)不受信任,則 Access 將使用沙箱模式,並且 SQL 中的 VBA 將不會運行。

如果該位置受信任,則 THEN 訪問將使用您計算機上的注冊表設置。

我的賭注是該位置不受信任 - 因此您總是在 Access 中獲得 SQL 的沙箱模式。

如果您 100% 確定文件夾位置在 Access 中設置為受信任,並且您仍然收到錯誤消息,那么您必須更改 Access“沙箱”模式的注冊表設置。

此處概述了注冊表中的設置: https : //support.office.com/en-us/article/Turn-sandbox-mode-on-or-off-to-disable-macros-8CC7BAD8-38C2-4A7A-A604 -43E9A7BBC4FB

注冊表設置是:

對於 x32 位訪問:

Software\Microsoft\Office\ClickToRun\Registry\Machine\Software\
Wow6432Node\Microsoft\Office\16.0\Access Connectivity Engine\Engines

以上適用於Office 2016

14 = 2010

15 = 2013

16 = 2016

沙盒模式的關鍵值是:0 到 3

0 沙盒模式始終處於禁用狀態。

1 Sandbox 模式用於 Access,但不適用於非 Access 程序。

2 沙盒模式用於非 Access 程序,但不適用於 Access。

3 沙盒模式一直被使用。 這是默認值,在安裝 Access 時設置

因此,從上面開始,您需要設置為 0。

暫無
暫無

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

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