【问题标题】:Handle Alert PopUp Dialog of Macro enabled Excel File using C#使用 C# 处理启用宏的 Excel 文件的警报弹出对话框
【发布时间】:2016-07-26 11:43:38
【问题描述】:

我正在尝试使用 c# 编辑启用宏的 Excel 文件。

我已完成编辑,需要使用已定义的宏 [VBA - 按钮] 验证所有数据。我可以使用下面提到的代码运行宏:

workbook.Application.Run("Sheet1.validate_Click");

现在的问题是,无论何时调用宏都会验证我在 Excel 工作表中插入的数据并给出如下所示的输出:

现在我需要以编程方式单击“是”按钮。这将要求保存将由该验证按钮自动创建的文件。

我被卡住了,我怎么能以编程方式点击出现的警报对话框的“是”按钮。

请帮助我,我在这里没有任何线索,我用谷歌搜索了很多,但找不到任何符合我目的的东西。

【问题讨论】:

  • 设置Application.EnableEvents = False可能会绕过这个问题
  • @RGA 感谢您的回答,Application.EnableEvents = False 将禁用由 excel 生成的事件。此警报是由 VBA Excel 宏生成的,所以我需要单击是 |没有 Compolsory。任何其他想法!
  • “由 VBA Excel 宏生成”意味着它由您从代码中调用的宏生成?
  • @RGA:是的。该宏已经是该excel文件中的代码。我需要使用验证按钮验证该文件中的数据,您将在我的图像中看到该按钮。
  • 如果您在自己的宏中生成该消息框,为什么不能只禁用该消息框?

标签: c# vba excel


【解决方案1】:

正如@Tom 在 cmets 中提到的,真正的解决方案是更改 VBA 代码。但是由于这不是您可以使用的选项,因此您必须使用某种骇人听闻的解决方法。我没有做太多测试,但我假设您的 COM 互操作调用也因为模式对话框而阻塞。

关于我想出的处理 VBA 从托管代码生成的对话框的唯一方法是使用 win32 函数轮询目标窗口,然后在找到它时发送模拟鼠标单击。这是我使用的类:

public class DialogClicker
{
    private delegate bool EnumWindowsProc(int hWnd, int lParam);

    private const int BM_SETSTATE = 0x00F3;
    private const int WM_LBUTTONDOWN = 0x0201;
    private const int WM_LBUTTONUP = 0x0202;

    [DllImport("user32.dll")]
    private static extern int EnumWindows(EnumWindowsProc callbackFunc, int lParam);
    [DllImport("user32.dll")]
    private static extern int EnumChildWindows(int hWnd, EnumWindowsProc callbackFunc, int lParam);
    [DllImport("user32.dll")]
    private static extern int GetWindowText(int hWnd, StringBuilder buff, int maxCount);
    [DllImport("user32.dll")]
    private static extern int SendMessage(int hWnd, int Msg, int wParam, int lParam);

    private const int MsgBufferSize = 256;
    private bool _textFound;
    private int _btnhWnd;
    private readonly Timer _timer;

    public string TargetHeader { get; private set; }
    public string ButtonText { get; private set; }
    public string SearchText { get; private set; }
    public int TimerInterval { get; private set; }

    public DialogClicker(string header, string button, string search, int interval)
    {
        TargetHeader = header;
        ButtonText = button;
        SearchText = search;
        TimerInterval = interval;
        _timer = new Timer(interval);
        _timer.Elapsed += ElapsedHandler;            
    }

    public void Toggle(bool active)
    {
        _timer.Enabled = active;
    }

    private void ElapsedHandler(object sender, ElapsedEventArgs e)
    {
        _btnhWnd = 0;
        _textFound = string.IsNullOrEmpty(SearchText);
        EnumWindows(EnumProc, 0);
    }

    private bool EnumProc(int hWnd, int lParam)
    {
        var heading = new StringBuilder(MsgBufferSize);
        GetWindowText(hWnd, heading, MsgBufferSize);
        var title = heading.ToString();

        if (string.IsNullOrEmpty(title) || !title.Equals(TargetHeader)) return true;
        EnumChildWindows(hWnd, EnumChildProc, 0);
        return false;
    }

    private bool EnumChildProc(int hWnd, int lParam)
    {
        var title = new StringBuilder(MsgBufferSize);
        GetWindowText(hWnd, title, MsgBufferSize);
        var text = title.ToString();

        if (string.IsNullOrEmpty(text)) return true;
        if (!_textFound) _textFound = text.Contains(SearchText);
        if (text.Equals(ButtonText)) _btnhWnd = hWnd;
        if (_btnhWnd <= 0 || !_textFound) return true;

        SendMessage(_btnhWnd, BM_SETSTATE, 1, 0);
        SendMessage(_btnhWnd, WM_LBUTTONDOWN, 0, 0);
        SendMessage(_btnhWnd, WM_LBUTTONUP, 0, 0);
        SendMessage(_btnhWnd, BM_SETSTATE, 1, 0);
        return false;
    }
}

调用代码:

var clicker = new DialogClicker("Microsoft Excel", "&Yes", "No error found in sheet.", 100);
clicker.Toggle(true);  //Start polling.

//Do whatever triggers the dialog.

clicker.Toggle(false); //Stop polling.

【讨论】:

  • @Comintern :感谢您的代码,此代码可能对我有用。我不确定,但我需要在后台进程中调用这个 DialogClicker,因为当我使用 VBA 代码验证我的 Excel 时,它是一个连续的进程。请为此指导我。再次感谢
  • @Mr.Go - 它基于事件,VBA 代码在 STA 线程中运行。它应该可以正常工作。
  • @Comintern:嘿,我删除了该评论,它与我的代码完美配合。非常感谢朋友。在这里,我将您的回答视为已接受。再次感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-15
  • 2020-04-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多