自动化 MS Access VBA 过程 - 将字符串变量分配给 InputBox

问题描述

乍一看,我试图通过 C# 自动一个非常简单的任务 - 将字符串值传递给通过 VBA 函数调用的 inputBox

为了做到这一点,我使用了 Visual C# .NET 自动化客户端来创建一个 MS Access 实例并打开所需的数据库

using System.Management.Automation;
using Access = Microsoft.Office.Interop.Access;

Access.Application oAccess = new Access.Application();
        oAccess.Visible = true;
        oAccess.OpenCurrentDatabase("D:\\path\\to\\database",false,"");
      

在上述数据库中,我们有一个宏,它通过“runcode”操作调用 VBA 函数。这个 public Function 然后调用一个 private Sub:

Public Function ImportMappingDatabases()
  ImportMappings InputBox("Specify Path","Path",mstrcDefaultPath),_
    InputBox("Choose Package","Package","")
End Function

Private Sub ImportMappings(Optional Path As String = mstrcDefaultPath,Optional Package As String = "")

这就是我卡住的地方。标题为“Path”的输入框希望用户输入某条路径,后面的代码使用,原因无需解释。这同样适用于标题为“Package”的输入框。我假设有一种方法可以将字符串值从 C# 代码“传递”到输入框输入字段,但我不知道如何引用输入框并设置该值。完成后需要用户点击“确定”按钮或“取消”,同样的问题适用,我将尝试用1句话综合:

如何获取那个输入框的引用,设置输入值,然后“点击”其中一个按钮?

更多信息:

我通过以下方式调用公共函数oAccess.Run("ImportMappingDatabases");

我可以不能修改 VBA 函数/子。

更新 1:

在下面检查我的答案。

解决方法

我找到了一种获取 inputBox 句柄的方法以及一种将字符串值传递给它的方法。您需要以下导入:

[DllImport("User32.dll",CharSet = CharSet.Auto)] static extern IntPtr FindWindow(string lpClassName,string lpWindowName);
[DllImport("User32.dll",CharSet = CharSet.Auto)] static extern IntPtr FindWindowEx(IntPtr parentHandle,IntPtr childAfter,string lpcClassName,string lpcWindowTitle);
[DllImport("User32.dll",CharSet = CharSet.Auto)] static extern UInt32 SendMessage(IntPtr handle,UInt32 message,IntPtr wParam,string lParam);

然后您可以使用 Win API 调用来查找您的 MS Access 窗口和 inputBox 窗口句柄:

IntPtr parent = FindWindow(null,"The access Window title here");
IntPtr childInputBox = IntPtr.Zero;
IntPtr TextBox = IntPtr.Zero;
if (parent != IntPtr.Zero)
{
   childInputBox = FindWindowEx(parent,IntPtr.Zero,string.Empty,"InputBox name here");
  if (childInputBox != IntPtr.Zero)
  {
    TextBox = FindWindowEx(childInputBox,"Edit",string.Empty);
    if (TextBox != IntPtr.Zero)
    {
      SendMessage(TextBox,WM_SETTEXT,new IntPtr(0),"Your out string to the input here");
    }
  }
}

这里我碰壁了,因为我实际上必须在尝试捕获句柄之前调用我的宏。所以调用宏:

oAccess.Run("TheNameOfTheMacro");

将在同一线程上运行它,因此在宏完成之前使我们的窗口窗体应用程序无法使用。 这种复杂性使我获得了使用接受字符串作为参数的公共函数扩展 VBA 代码的许可(如评论中所述)并从那里继续。 如果您决定必须使用输入框,则必须在不同的线程上运行宏,并以某种方式检查输入框是否被“召唤” - 发送消息。