使用VBA OpenRecordset从Access Query到Excel的用户定义函数(UDF)失败 - 未定义函数

问题描述 投票:1回答:3

如果具有UDF,如何将Access的查询结果从Excel中获取?

我收到以下错误:“运行时错误'3085':表达式中未定义的函数'XXXX'”。从Excel VBA打开(访问查询)记录集时发生此错误。正在打开的查询具有触发错误的用户定义函数(UDF)。

该代码位于Excel Office 365中。该查询位于Access Office 365中。

我已经成功地使用了被调用的查询(以及其他使用UDF的查询)大约12个月,并且“突然”它不再工作了。我用谷歌搜索并测试了许多选项但没有成功。

大多数线程说它无法完成,或者不使用udf但尝试使用内置工具。我正在挑战那些回应,因为它以前有效。我使用的主要udf是一个名为“iMax”的文章,在其他帖子中写了。它的功能类似于Excel中的max()。 (No max(x,y) function in Access

我也看到线程建议分两步执行:1 - 将查询更改为生成表查询。 2 - 将表格结果拉入Excel。虽然我可以逃脱这个(经过多次返工),但这会导致我制作许多具有成千上万行的临时表并且看起来不太光滑。

我编译了vba并压缩了db而对我的问题没有影响。

作为一个远景,我创建了一个虚拟数据库,其中包含一个返回数字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

对于没有udf的For循环中的所有查询,结果将被拉出并转储到Excel中的一系列表中。在“Set rs = Mydatabase.OpenRecordset(qryname)”中出现udf错误的任何查询

excel vba ms-access access-vba user-defined-functions
3个回答
0
投票

如果您在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

1
投票

大多数线程说它无法完成,

他们是对的。

您唯一的选择是使用自动化来打开Access实例,并在其中运行查询。


0
投票

好吧,如上所述,大多数人都说这不起作用。

但是,如果你100%确定它曾经并且曾经一次工作过吗?

您需要设置JET(现在为ACE)数据库引擎的“沙盒”模式。

表达式服务通常不允许将VBA函数评估为防止SQL注入的安全设置,或者在Access之外运行的代码以允许SQL运行+调用VBA函数。有一次,此功能默认为“on”,但现在默认设置为仅访问。

您必须将Access应用程序设置为受信任的文件夹。这应该允许VBA功能现在工作。因此,请确保将文件夹设置为受信任。

如果您的访问应用程序不受信任的位置(文件夹),则Access将使用沙箱模式,并且SQL中的VBA将不会运行。

如果该位置是受信任的,则THEN访问权限使用您计算机上的注册表设置。

我的意思是该位置不受信任 - 所以你总是在Access中获得SQL的沙箱模式。

如果您100%确定在Access中将文件夹位置设置为受信任,并且仍然收到错误,则必须更改Access“sandbox”模式的注册表设置。

注册表中的设置如下: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沙盒模式用于Access,但不用于非Access程序。

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

3沙盒模式始终使用。这是安装Access时设置的默认值

因此,从上面看,您需要设置为0。

© www.soinside.com 2019 - 2024. All rights reserved.