在不同的工作簿上运行Excel宏

时间:2016-02-19 17:55:05

标签: c# excel excel-vba excel-interop vba

我正在尝试从另一个工作簿上的一个工作簿运行VBA宏 我正在使用Microsoft.Office.Interop.Excel(或等效)对象(如果要使用它,请将引用(COM)添加到Microsoft Excel 12.0对象库)来编辑和使用C#可执行文件中的Excel文档。

例如,文档1中包含一些数据。文档2包含格式化文档一的宏。文档一是每天都是新的,所以我不能在那里存储宏。我尝试使用Excel.Application.Run()在文档一中运行文档二中的宏。

我使用的示例宏很简单(存储在Microsoft Excel对象:ThisWorkbook中):

Sub Test()
  Sheets("Sheet1").Select
  Range("A1").Value = 32
End Sub

我需要在不同的工作簿上运行它。我可以使用以下代码在同一工作簿上运行它:

Application xlApp = new Application(); //Excel app
Workbook xlWbk = null;
try
{
  xlWbk = xlApp.Workbooks.Open(DocumentTwoLocation);
  xlApp.Run("'" + DocumentTwoLocation + "'!" + MacroName); //MacroName example: ThisWorkbook.Test
}
finally
{
  if (xlWbk != null)
    try
    {
      xlWbk.Close(true); //Saves changes
    }
    catch
    {
      xlWbk.Close(false);
    }
  xlApp.Quit();
}

当我将xlApp.Workbooks.Open中的DocumentTwoLocation更改为DocumentOneLocation时,宏将不会运行。抛出一个COMException(HRESULT:0x800A03EC),这是NameNotFound(仅在使用xlApp.Run()时抛出)。文件地址是正确的。即使我事先打开这两份文件:

Application xlApp = new Application(); //Excel app
Workbook xlWbk = null;
Workbook xlMacroBook = null;
try
{
  xlWbk = xlApp.Workbooks.Open(DocumentOneLocation);
  xlMacroBook = xlApp.Workbooks.Open(DocumentTwoLocation);
  xlApp.Run("'" + DocumentTwoLocation + "'!" + MacroName); //MacroName example: ThisWorkbook.Test
}
finally
{
  if (xlWbk != null)
    try
    {
      xlWbk.Close(true); //Saves changes
    }
    catch
    {
      xlWbk.Close(false);
    }
  if (xlMacroBook != null)
    xlMacroBook.Close(false) //Don't save changes
  xlApp.Quit();
}

仍然出现错误(相同的0x800A03EC异常)。

MSDN几乎没有关于我遗漏的内容或如何处理此问题的文档(https://msdn.microsoft.com/en-us/library/microsoft.office.interop.excel.applicationclass.run.aspx

这里有类似的问题: Error when calling Excel macro from C# 并且我已尽我所能来匹配他们所写的内容(包括添加ReleaseComObject,并在之后设置为null)但无济于事。

1 个答案:

答案 0 :(得分:1)

我已经解决了这个问题。

问题出现的原因是试图运行" xlsm"格式宏在不同的文档上。只能使用Microsoft Office Excel二进制工作表(xlsb格式)在另一个工作簿上运行宏。如果您遇到同样的问题 - 请使用xlsb保存宏,而不是xlsm。

对于您感兴趣的人,最终代码如下:

/// <summary>
/// Run a macro from an xlsb file on another excel file
/// </summary>
/// <param name="ExcelFile">The excel file to run the macro on</param>
/// <param name="MacroFileLocation">The xlsb file the macro is saved in</m>
/// <param name="Macro">The macro name to run (e.g. Module1.Example)</param>
static void Test(string ExcelFile, string MacroFileLocation, string Macro)
{
    Application xlApp = new Application(); //Excel app
    Workbook xlWbk = null;
    try
    {
        xlWbk = xlApp.Workbooks.Open(ExcelFile);

        string MacroCommand = "'" + MacroFileLocation + "'!" + Macro;
        xlApp.Run(MacroCommand);
    }
    finally
    {
        //Clean up
        if (xlWbk != null)
            try
            {
                xlWbk.Close(true);
            }
            catch
            {
                //Couldn't save - consider alerting user
                xlWbk.Close(false);
            }
        xlApp.Quit();

        System.Runtime.InteropServices.Marshal.ReleaseComObject(xlWbk);
        System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApp);

        xlWbk = null;
        xlApp = null;
    }
}