我正在从.Net注入一个VBA代码到Microsoft Access数据库中。
它只是一行代码,它运行一个宏。所有宏都在模块内运行一块VBA代码。
我遇到的问题是,这一切都发生在新的MSAccess会话中,我甚至看不到,而不是用户当前打开的会话。
是否有可能与用户当前的MSAccess会话进行交互?这一点的重点是在每次出现.Net事件时在MSAccess会话中打开一个特定的表单。我的C#代码如下:
using Microsoft.Office.Interop.Access;
var msAccess = new Application();
msAccess.OpenCurrentDatabase(@"x:\foo\bar.accdb", false);
msAccess.DoCmd.RunMacro("macCTI");
msAccess.CloseCurrentDatabase();
由于
答案 0 :(得分:2)
如果您运行的是单个Access实例,则可以使用 Marshal.GetActiveObject
:
using Microsoft.Office.Interop.Access;
using System.Runtime.InteropServices
...
try
{
var msAccess = (Application)Marshal.GetActiveObject("Access.Application");
msAccess.DoCmd.RunMacro("macCTI");
}
catch (COMException ex)
{
// handle error
}
或者,如果正在运行多个实例,并且没有两个实例打开相同的数据库,则可以使用 Marshal.BindToMoniker
:
var msAccess = (Application) Marshal.BindToMoniker(@"x:\foo\bar.accdb");
注意:此Microsoft knowledge base article可以这样说:
COM服务器是单用户(多实例)还是 多用途(单一实例)可能会影响您的使用决策 GetActiveObject以获取对该服务器的引用。因为可能 可以使用Word,Excel或Microsoft Access的多个实例 运行,特定服务器上的GetActiveObject可能会返回一个实例 你没想到的。首先在。中注册的实例 ROT通常是GetActiveObject返回的实例。如果 您希望获得特定运行实例的自动化参考 的Word,Excel或Microsoft Access,使用名称的BindToMoniker 在该实例中打开的文件。对于多用途(单一用途) 实例)像PowerPoint这样的服务器,没关系,因为 自动化参考指向同一个运行实例。
答案 1 :(得分:0)
要获取新的Access实例,您必须查看实例是否已存在。使用Marshal.GetActiveObject
作为Matt建议:
Application GetAccessApplication() {
var application = (Application) Marshal.GetActiveObject("Access.Application");
return application ?? new Application();
}
请注意,这里存在轻微的断开,因为您必须使用ProgID来获取现有的Access实例,但是要创建一个使用互操作程序集的新实例。
然后,您可以使Access应用程序可见:
var msAccess = GetAccessApplication();
msAccess.Visible = true;