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

Automating MS Access VBA procedure - assign string variable to InputBox

我正在尝试通过 C# 自动执行乍一看非常简单的任务 - 将字符串值传递给通过 VBA 函数调用的 inputBox。

为此,我使用 Visual C# .NET Automation Client 创建了一个 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句话综合它:

如何获取该输入框的引用、设置输入值并“单击”其中一个按钮?

更多信息:

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

我可以不能修改VBAfunctions/subs。

更新 1:

在下方查看我的回答。

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

[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 window 和 inputBox window 句柄:

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, IntPtr.Zero, "Edit", 
    string.Empty);
    if (TextBox != IntPtr.Zero)
    {
      SendMessage(TextBox, WM_SETTEXT, new IntPtr(0), "Your out string to the input here");
    }
  }
}

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

oAccess.Run("TheNameOfTheMacro");

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