使用C#处理启用宏的Excel文件的警报弹出对话框

时间:2016-07-26 11:43:38

标签: c# excel vba excel-vba

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

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

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

现在问题是,每当调用宏时,它将验证我在Excel工作表中插入的数据,并给出如下所示的输出:

enter image description here

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

我遇到困难,我怎么能以编程方式点击出现的“警告对话框的按钮”。

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

1 个答案:

答案 0 :(得分:4)

正如@Tom在评论中提到的,真正的解决方案将是更改VBA代码。但是因为这不是你可以选择的选项,所以你必须使用某种hackish work-around。我没有做太多测试,但我认为你的COM Interop调用也因为模态对话框而被阻塞。

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

KeyPressFcn

致电代码:

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;
    }
}