OpenXML SDK将VBA注入excel工作簿

Ian*_*ert 6 c# excel vba excel-vba openxml-sdk

我可以成功地将一段VBA代码注入到生成的excel工作簿中,但我想要做的是使用Workbook_Open()事件,以便在文件打开时执行VBA代码.我将sub添加到我的xlsm模板文件中的"ThisWorkbook"对象.然后我使用openxml生产力工具来反映代码并获取编码的VBA数据.

当生成文件并查看VBA时,我看到"ThisWorkbook"和"ThisWorkbook1"对象.我的VBA在"ThisWorkbook"对象中,但代码永远不会在打开时执行.如果我将我的VBA代码移动到"ThisWorkbook1"并重新打开该文件,它可以正常工作.为什么要创建一个额外的"ThisWorkbook"?是否无法使用Workbook_Open()子系统注入excel电子表格?这是我正在使用的C#代码的片段:

private string partData = "...";  //base 64 encoded data from reflection code
//open workbook, myWorkbook
VbaProjectPart newPart = myWorkbook.WorkbookPart.AddNewPart<VbaProjectPart>("rId1");
System.IO.Stream data = GetBinaryDataStream(partData);
newPart.FeedData(data);
data.Close();
//save and close workbook
Run Code Online (Sandbox Code Playgroud)

有人有想法吗?

小智 6

根据我的研究,没有办法以可以在 C# 中操作的格式插入项目部件数据。在 OpenXML 格式中,VBA 项目仍然以二进制格式存储。但是,将VbaProjectPart一个 Excel 文档中的复制到另一个应该可以。因此,您必须提前确定您希望项目部分说什么。

如果您对此没有意见,那么您可以将以下代码添加到“ThisWorkbook”Microsoft Excel 对象中的模板 Excel 文件中,以及相应的宏代码:

Private Sub Workbook_Open()
    Run "Module1.SomeMacroName()"
End Sub
Run Code Online (Sandbox Code Playgroud)

要将VbaProjectPart对象从一个文件复制到另一个文件,您可以使用如下代码:

public static void InsertVbaPart()
{
    using(SpreadsheetDocument ssDoc = SpreadsheetDocument.Open("file1.xlsm", false))
    {
        WorkbookPart wbPart = ssDoc.WorkbookPart;
        MemoryStream ms;
        CopyStream(ssDoc.WorkbookPart.VbaProjectPart.GetStream(), ms);

        using(SpreadsheetDocument ssDoc2 = SpreadsheetDocument.Open("file2.xlsm", true))
        {
            Stream stream = ssDoc2.WorkbookPart.VbaProjectPart.GetStream();
            ms.WriteTo(stream);
        }
    }
}

public static void CopyStream(Stream input, Stream output)
{
    byte[] buffer = new byte[short.MaxValue + 1];
    while (true)
    {
        int read = input.Read(buffer, 0, buffer.Length);
        if (read <= 0)
            return;
        output.Write(buffer, 0, read);
    }
}
Run Code Online (Sandbox Code Playgroud)

希望有帮助。