Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/vba/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ms access 如何在Access VBA中设置对运行对象的引用_Ms Access_Vba_Ms Access 2016 - Fatal编程技术网

Ms access 如何在Access VBA中设置对运行对象的引用

Ms access 如何在Access VBA中设置对运行对象的引用,ms-access,vba,ms-access-2016,Ms Access,Vba,Ms Access 2016,我尝试使用GetObject在另一个数据库中打开表单。不幸的是,我必须打开数据库的第二个实例,但我希望使用该数据库的活动实例(如果已加载)。为了实现这一点,我需要设置一个对象引用到该数据库的运行实例 我目前使用的是下面的函数。此函数首先尝试使用其屏幕名称激活数据库的运行实例,如果这产生错误,则加载数据库和表单。但是,如果数据库已经加载,我希望能够加载表单 另一个较小的问题是,如果加载db和表单的错误过程生成错误,则不遵循错误例程。我该如何处理 有人有主意吗 我正在使用Access 2016 Th

我尝试使用GetObject在另一个数据库中打开表单。不幸的是,我必须打开数据库的第二个实例,但我希望使用该数据库的活动实例(如果已加载)。为了实现这一点,我需要设置一个对象引用到该数据库的运行实例

我目前使用的是下面的函数。此函数首先尝试使用其屏幕名称激活数据库的运行实例,如果这产生错误,则加载数据库和表单。但是,如果数据库已经加载,我希望能够加载表单

另一个较小的问题是,如果加载db和表单的错误过程生成错误,则不遵循错误例程。我该如何处理

有人有主意吗

我正在使用Access 2016

Thx

彼得

作为布尔值的公共函数AppDbOpen(StrapExec作为字符串,StrapName作为字符串,StropeForm作为字符串)
关于错误转到错误进程
作为对象的Dim objDb
'如果打开,则激活数据库
激活名称
AppDbOpen=True
退出错误程序:
设置objDb=Nothing
退出功能
错误进程:
选择案例错误编号
案例5‘如果未打开,则打开Db
设置objDb=GetObject(StrapExec,“Access.Application”)
如果Nz(笔形,“”“”),则
objDb.DoCmd.OpenForm strOpenForm
如果结束
AppDbOpen=True
其他情况
MsgBox“错误:”&修剪(Str(错误编号))&vbCrLf&_
描述:&错误描述&vbCrLf&vbCrLf&_
“模块:模块通用功能”&vbCrLf&_
“函数:AppDbOpen”_
“错误!”
结束选择
恢复退出\u错误\u过程
端函数

这不是一项容易的任务,但可以通过使用一些WinAPI窗口函数来完成

本质上,您希望通过使用窗口标题来获取Access应用程序对象

我将假设窗口标题中没有任何unicode字符,否则,我们将需要更复杂的内容

首先,声明我们的WinAPI函数:

Declare PtrSafe Function FindWindowExA Lib "user32" (Optional ByVal hWndParent As LongPtr, Optional ByVal hwndChildAfter As LongPtr, Optional ByVal lpszClass As String, Optional ByVal lpszWindow As String) As LongPtr
Declare PtrSafe Function AccessibleObjectFromWindow Lib "oleacc" (ByVal hWnd As LongPtr, ByVal dwId As Long, riid As Any, ppvObject As Object) As Long
FindWindowExA
用于查找具有指定标题的窗口<代码>AccessibleObjectFromWindow用于获取该窗口的COM对象

然后,我们声明一些用于AccessibleObjectFromWindow的常量:

Const strIID_IDispatch As String = "{00020400-0000-0000-C000-000000000046}" 'To identify the IDISPATCH COM interface
Const OBJID_NATIVEOM As Long = &HFFFFFFF0 'To identify the object type
然后,我们可以编写函数

Public Function AppDbOpen(strAppExec As String, strAppName As String, strOpenForm As String) As Boolean
    On Error GoTo Err_Proc
    Dim objDb As Object

    'Activate DB if open
    AppActivate strAppName
    AppDbOpen = True
    Dim hwndAppDb As LongPtr
    hwndAppDb = FindWindowExA (,,,strAppName) 'Find the window handle (hWnd)
    If hwndAppDb <> 0 Then 'If it's 0, something went wrong, check the title
          Dim guid() As Byte
          guid = Application.GuidFromString(strIID_IDispatch)
          'Get the IDispatch object associated with that handle
          AccessibleObjectFromWindow hwndAppDb, OBJID_NATIVEOM, guid(0), objDb 
    End If
    If Nz(strOpenForm, "") <> "" Then
         objDb.DoCmd.OpenForm strOpenForm
    End If
Exit_Err_Proc:
    Set objDb = Nothing
    Exit Function

Err_Proc:
    Select Case Err.Number
        Case 5 'Open Db if not open
            Set objDb = GetObject(strAppExec, "Access.Application")
            If Nz(strOpenForm, "") <> "" Then
                objDb.DoCmd.OpenForm strOpenForm
            End If
            AppDbOpen = True
        Case Else
            MsgBox "Error: " & Trim(Str(Err.Number)) & vbCrLf & _
            "Desc: " & Err.description & vbCrLf & vbCrLf & _
            "Module: Mod_GeneralFunctions" & vbCrLf & _
            "Function: AppDbOpen", _
            vbCritical, "Error!"
    End Select
    Resume Exit_Err_Proc
End Function
作为布尔值的公共函数AppDbOpen(StrapExec作为字符串,StrapName作为字符串,StropeForm作为字符串)
关于错误转到错误进程
作为对象的Dim objDb
'如果打开,则激活数据库
激活名称
AppDbOpen=True
Dim hwndAppDb作为长PTR
hwndAppDb=FindWindowExA(,,StrapName)'查找窗口句柄(hWnd)
如果hwndAppDb为0,则“如果为0,则出现问题,请检查标题
作为字节的Dim guid()
guid=Application.GuidFromString(strIID_IDispatch)
'获取与该句柄关联的IDispatch对象
可访问对象来自窗口hwndAppDb、OBJID_NATIVEOM、guid(0)、objDb
如果结束
如果Nz(笔形,“”“”),则
objDb.DoCmd.OpenForm strOpenForm
如果结束
退出错误程序:
设置objDb=Nothing
退出功能
错误进程:
选择案例错误编号
案例5‘如果未打开,则打开Db
设置objDb=GetObject(StrapExec,“Access.Application”)
如果Nz(笔形,“”“”),则
objDb.DoCmd.OpenForm strOpenForm
如果结束
AppDbOpen=True
其他情况
MsgBox“错误:”&修剪(Str(错误编号))&vbCrLf&_
描述:&错误描述&vbCrLf&vbCrLf&_
“模块:模块通用功能”&vbCrLf&_
“函数:AppDbOpen”_
“错误!”
结束选择
恢复退出\u错误\u过程
端函数

我不打算讨论链式错误处理程序的要点,但您可以回顾一下。请注意,重置错误处理程序也会重置
Err
对象,因此如果您想使用它,可能首先需要存储错误号和描述。

这就像一个符咒,非常感谢!我自己从来没有想到这一点

在代码调整之后,似乎也没有与嵌套错误相关的问题。我需要添加一个maximize调用,因为mu表单显示与屏幕相关,当另一个数据库最小化时,这会导致一个不可见的表单。最后的代码是现在

Option Compare Database
Option Explicit
Declare PtrSafe Function FindWindowExA Lib "user32" (Optional ByVal hWndParent As LongPtr, _
        Optional ByVal hwndChildAfter As LongPtr, Optional ByVal lpszClass As String, _
        Optional ByVal lpszWindow As String) As LongPtr
Declare PtrSafe Function AccessibleObjectFromWindow Lib "oleacc" (ByVal hWnd As LongPtr, _
        ByVal dwId As Long, riid As Any, ppvObject As Object) As Long
Const strIID_IDispatch As String = "{00020400-0000-0000-C000-000000000046}" 'To identify the IDISPATCH COM interface
Const OBJID_NATIVEOM = &HFFFFFFF0 'To identify the object type

Public Function AppDbOpen(strAppExec As String, strAppName As String, strOpenForm As String) As Boolean
    On Error GoTo Err_Proc
    Dim objDb As Object
    Dim hwndAppDb As LongPtr

    'Find the Db handle
    hwndAppDb = FindWindowExA(, , , strAppName) 'Find the window handle (hWnd)
    If hwndAppDb <> 0 Then 'If it's 0, something went wrong, check the title
        'Activate DB if open
        Dim guid() As Byte
        guid = Application.GUIDFromString(strIID_IDispatch)
        'Get the IDispatch object associated with that handle
        AccessibleObjectFromWindow hwndAppDb, OBJID_NATIVEOM, guid(0), objDb
    Else
        'Open Db if not open
        Set objDb = GetObject(strAppExec, "Access.Application")
    End If

    If Nz(strOpenForm, "") <> "" Then
        objDb.RunCommand acCmdAppMaximize
        objDb.DoCmd.OpenForm strOpenForm
        objDb.Run "CenterForm", strOpenForm, False, False, False, 0
    End If
    AppDbOpen = True

Exit_Err_Proc:
    Set objDb = Nothing
    Exit Function

Err_Proc:
    Select Case Err.Number
        Case Else
            MsgBox "Error: " & Trim(Str(Err.Number)) & vbCrLf & _
            "Desc: " & Err.description & vbCrLf & vbCrLf & _
            "Module: Mod_OpenExtDb" & vbCrLf & _
            "Function: AppDbOpen", _
            vbCritical, "Error!"
    End Select
    Resume Exit_Err_Proc
End Function
选项比较数据库
选项显式
声明PtrSafe函数FindWindowExA Lib“user32”(可选ByVal hWndParent作为LongPtr_
可选ByVal hwndChildAfter作为LongPtr,可选ByVal lpszClass作为字符串_
可选的ByVal lpsz窗口(作为字符串)作为LongPtr
声明PtrSafe函数AccessibleObjectFromWindow Lib“oleacc”(ByVal hWnd为LongPtr_
ByVal dwId尽可能长,riid尽可能长,ppvObject尽可能长
常量strIID_IDispatch As String=“{00020400-0000-0000-C000-0000000000 46}”,以标识IDispatch COM接口
Const OBJID_NATIVEOM=&HFFFFFFF0'来标识对象类型
作为布尔值的公共函数AppDbOpen(StrapExec作为字符串,StrapName作为字符串,StropeForm作为字符串)
关于错误转到错误进程
作为对象的Dim objDb
Dim hwndAppDb作为长PTR
'查找数据库句柄
hwndAppDb=FindWindowExA(,,StrapName)'查找窗口句柄(hWnd)
如果hwndAppDb为0,则“如果为0,则出现问题,请检查标题
'如果打开,则激活数据库
作为字节的Dim guid()
guid=Application.GUIDFromString(strIID_IDispatch)
'获取与该句柄关联的IDispatch对象
可访问对象来自窗口hwndAppDb、OBJID_NATIVEOM、guid(0)、objDb
其他的
'如果未打开,则打开数据库
设置objDb=GetObject(StrapExec,“Access.Application”)
如果结束
如果Nz(笔形,“”“”),则
objDb.RunCommand acCmdAppMaximize
objDb.DoCmd.OpenForm
Option Compare Database
Option Explicit
Declare PtrSafe Function FindWindowExA Lib "user32" (Optional ByVal hWndParent As LongPtr, _
        Optional ByVal hwndChildAfter As LongPtr, Optional ByVal lpszClass As String, _
        Optional ByVal lpszWindow As String) As LongPtr
Declare PtrSafe Function AccessibleObjectFromWindow Lib "oleacc" (ByVal hWnd As LongPtr, _
        ByVal dwId As Long, riid As Any, ppvObject As Object) As Long
Const strIID_IDispatch As String = "{00020400-0000-0000-C000-000000000046}" 'To identify the IDISPATCH COM interface
Const OBJID_NATIVEOM = &HFFFFFFF0 'To identify the object type

Public Function AppDbOpen(strAppExec As String, strAppName As String, strOpenForm As String) As Boolean
    On Error GoTo Err_Proc
    Dim objDb As Object
    Dim hwndAppDb As LongPtr

    'Find the Db handle
    hwndAppDb = FindWindowExA(, , , strAppName) 'Find the window handle (hWnd)
    If hwndAppDb <> 0 Then 'If it's 0, something went wrong, check the title
        'Activate DB if open
        Dim guid() As Byte
        guid = Application.GUIDFromString(strIID_IDispatch)
        'Get the IDispatch object associated with that handle
        AccessibleObjectFromWindow hwndAppDb, OBJID_NATIVEOM, guid(0), objDb
    Else
        'Open Db if not open
        Set objDb = GetObject(strAppExec, "Access.Application")
    End If

    If Nz(strOpenForm, "") <> "" Then
        objDb.RunCommand acCmdAppMaximize
        objDb.DoCmd.OpenForm strOpenForm
        objDb.Run "CenterForm", strOpenForm, False, False, False, 0
    End If
    AppDbOpen = True

Exit_Err_Proc:
    Set objDb = Nothing
    Exit Function

Err_Proc:
    Select Case Err.Number
        Case Else
            MsgBox "Error: " & Trim(Str(Err.Number)) & vbCrLf & _
            "Desc: " & Err.description & vbCrLf & vbCrLf & _
            "Module: Mod_OpenExtDb" & vbCrLf & _
            "Function: AppDbOpen", _
            vbCritical, "Error!"
    End Select
    Resume Exit_Err_Proc
End Function