我在这里玩游戏迟到了 - 我有时会在原始问题发布数月或数年后发布答案,因为当快速搜索“堆栈”找到与我当天的问题相关的问题时,我会发布自己的解决方案,但没有我可以实际使用的答案。
[更新,2016 年 6 月 6 日]
从 Access 2010 开始,“NameMap”属性在文档对象中不可用。但是,'Stacker Thunderframe 指出,现在可以在 'MsysNameMap' 表中找到它。
我已经修改了代码,这适用于 Access 2010 和 2013。
[/更新]
大多数表单属性仅在表单打开时可用,但有些在 DAO 文档集合中的表单条目中可用。
DAO '文档' 是一个可怕的对象:它不会在内存中持久存在,并且每次使用它时都必须明确引用它:
FormName = "我的表单"
For i = 0 至 Application.CodeDb.Containers("Forms").Documents(FormName).Properties.Count - 1
Debug.Print i & vbTab & Application.CodeDb.Containers("Forms").Documents(FormName).Properties(i).Name & vbTab & vbTab & Application.CodeDb.Containers("Forms").Documents(FormName)。属性(i).值
下一个
为您的表单运行该 sn-p,您将看到一个“NameMap”属性,其中包含表单控件列表和 一些表单属性。
...在一个真正可怕的格式,需要一个二进制解析器。您可能想立即停止阅读并服用阿司匹林,然后再继续。
健康警告:
NameMap 属性未记录。因此,它不受支持,并且无法保证此解决方案将在 Microsoft Access 的未来版本中运行。
如果记录源的 NameMap 的两字节二进制标签发生变化,或者它是特定于语言环境的,我下面代码中的解决方案将停止工作。
这是一个可怕的黑客行为:我对对您的理智造成的任何影响不承担任何责任。
好的,代码如下:
从关闭的 MS-Access 表单返回记录源的 VBA 函数:
私有函数 FormRecordSource_FromNameMap(FormName As String) As String
' 从表单的 Document 对象的 NameMap 属性中读取记录源。
' 警告:这里有一个潜在的错误:如果表单的 RecordSource 属性为空
' 并且它有一个或多个列表控件,其中填充了 .RecordSource 属性
' 列表,此函数将返回第一个列表控件的记录源。
' 如果您在表单名称中使用非 ASCII 字符 (Char > 255),这将不起作用。
将 i 调暗为整数
将 j 调暗为整数
将 k 调暗为整数
将 arrByte() 调暗为字节
将 strOut 调暗为字符串
If Application.Version < 12 然后
arrByte = Application.CodeDb.Containers("Forms").Documents(FormName).Properties("NameMap").Value
For i = 1 To UBound(arrByte) - 2 Step 2
' NameMap 中 querydef 的 2 字节标记:
如果 (arrByte(i) = 228 并且 arrByte(i + 1) = 64) 那么
j = 我 + 2
Do While arrByte(j) = 0 And arrByte(j + 1) = 0 And j < UBound(arrByte)
' 遍历标记和字符串开头之间的空字符
j = j + 2
循环
strOut = ""
直到 (arrByte(j) = 0 和 arrByte(j + 1) = 0) 或 j >= UBound(arrByte) - 2
如果 arrByte(j) = 0 那么 j = j + 1
' 循环直到我们到达终止这个字符串的空字符
' 附加表或查询的 Bchars(不是 unicode Wchars!)
strOut = strOut & Chr(arrByte(j))
j = j + 2
循环
Exit For ' 我们只想要第一个数据源
结束如果
接下来我
其他
arrByte = Nz(DLookup("[NameMap]", "[MSYSNameMap]", "[Name] = '" & FormName & "'"), vbNullChar)
If UBound(arrByte) < 4 然后退出函数
strOut = ""
对于 j = 60 到 UBound(arrByte) - 2 步骤 2
如果 arrByte(j) = 0 并且 arrByte(j + 1) = 0 则退出 For
strOut = strOut & Chr(arrByte(j))
下一个 j
结束如果
frmRecordSource_FromNameMap = strOut
擦除 arrByte
结束函数
如果您在(比如说)OpenRecordset 或 DCOUNT 函数中使用 RecordSource,我建议您将其封装在方括号中:您可能会从 RecordSource 中的“SELECT”语句中获取隐藏查询对象的名称,并且该名称将包含需要特殊处理的 '~' 波浪字符。
现在,您没有要求的额外内容,但如果其他人在此处搜索“MS Access RecordSource for a closed form”,他们将会寻找:
获取 MS-Access 表单的 RecordSource,无论它是否打开
大多数情况下,您的表单将处于打开状态。问题是,你不知道......如果它是一个子表单,它可能在 Forms() 集合中不可见。更糟糕的是,作为子表单托管的表单可能作为多个实例存在于多个打开的表单中。
祝你好运,如果你想提取动态属性...比如过滤器,或者记录源,如果它是由 VBA 'on the fly' 设置的。
公共函数 GetForm(FormName As String, Optional ParentName As String = "") As Form
' 返回一个表单对象,如果一个名称类似 FormName 的表单是打开的
' FormName 可以包含通配符。
' 如果没有打开匹配的表单,则不返回任何内容。
' 枚举打开表单中的子表单,并返回子表单 .form 对象,如果
' 它有一个匹配的名称。请注意,一个表单可能会作为多个实例打开
' 如果有多个子表单托管它;该函数返回第一个匹配项
' 实例。指定命名的父窗体(或子窗体控件的名称),如果
'您需要避免由表单的多个实例引起的错误。
将 objForm 调暗为 Access.Form
如果 ,
对于表单中的每个 objForm
If objForm.Name Like FormName 那么
设置 GetForm = objForm
退出功能
万一
下一个
结束如果
如果 GetForm 什么都不是,那么
对于表单中的每个 objForm
设置 GetForm = SearchSubForms(objForm, FormName, ParentName)
如果不是 GetForm 什么都不是,那么
退出
万一
下一个
结束如果
结束函数
私有函数 SearchSubForms(objForm As Access.Form, SubFormName As String, Optional ParentName As String = "") As Form
' 如果命名对象 SubFormName 是 subform,则返回一个 Form 对象,其名称类似于 SubFormName
' 的开放形式,或者可以递归地枚举为开放子形式的子形式。
' 此函数返回第一个匹配的表单:请注意,一个表单可以被多个实例化
' 实例,如果它被多个子表单控件使用。
将 objCtrl 调暗为控件
对于每个 objCtrl 在 objForm 中
如果 TypeName(objCtrl) = “SubForm” 那么
If objCtrl.Form.Name Like SubFormName 那么
If ParentName = “” 或 objForm.Name Like ParentName 或 objCtrl.Name Like ParentName 然后
设置 SearchSubForms = objCtrl.Form
退出
万一
别的
设置 SearchSubForms = SearchSubForms(objCtrl.Form, SubFormName, ParentName)
如果不是 SearchSubForms 什么都不是,那么
退出
万一
万一
结束如果
下一个 objCtrl
结束函数
公共函数 FormRecordSource(FormName As String, Optional ParentName As String = "") As String
'返回表单的记录源,即使它没有在 Forms() 集合中打开
' 这将首先查找打开的表单。如果您正在寻找子表单,您可能需要一个
' 托管子表单的表单的父名称:您的命名表单可能会以
' 多个父表单中的子表单实例。
' 警告:这里有一个潜在的错误:如果表单没有打开,并且它有一个空白
' RecordSource 属性,并且它具有一个或多个带有 .RecordSource 的控件
' 填充列表的属性,可以返回列表控件的 RecordSource
将 objForm 作为表单调暗
如果 FormName = "" 那么
退出功能
结束如果
设置 objForm = GetForm(FormName, ParentName)
如果 objForm 什么都不是,那么
FormRecordSource = FormRecordSource_FromNameMap(FormName)
别的
FormRecordSource = objForm.RecordSource
设置 objForm = 无
结束如果
结束函数
分享和享受:对于代码示例中任何不需要的换行符,请接受我的歉意。