如何在不使用 Interop 的情况下将 VBA 代码注入 Excel .xlsm?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8331711/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-11 14:35:38  来源:igfitidea点击:

How to inject VBA code into Excel .xlsm without using Interop?

c#excel-vbainteropvbaexcel

提问by Snorex

My goal is to add macros to an excel workbook without having to enable "Trust Access to the VBA Project Object Module" in the Excel Trust Center. (Enabling access seems a security risk).

我的目标是将宏添加到 Excel 工作簿,而无需在 Excel 信任中心启用“对 VBA 项目对象模块的信任访问”。(启用访问似乎存在安全风险)。

Found random pieces of puzzle on my initial fact finding search: -I see that VBA script is stored in the zipped .xlsm file as vbaProject.bin. -There are several free/commercial resources that can work with excel files: Create excel without interop and template with or without row and columnspan

在我最初的事实发现搜索中发现了随机的拼图: - 我看到 VBA 脚本作为 vbaProject.bin 存储在压缩的 .xlsm 文件中。- 有几个可以使用 excel 文件的免费/商业资源: 创建没有互操作的 excel 和带有或不带有行和列跨度的模板

It would be nice to simply have a file of VBA script in the C# project that the C# code pulls from and injects into the Excel document without VBA interop. Any quick/fast/simple/straightforward way to do this or should I play around with the free/commercial resources linked to above?

最好在 C# 项目中简单地拥有一个 VBA 脚本文件,C# 代码从该文件中提取并注入 Excel 文档,而无需 VBA 互操作。任何快速/快速/简单/直接的方法来做到这一点,或者我应该使用上面链接的免费/商业资源吗?

采纳答案by Snorex

Using OpenXML SDK 2.0:

使用OpenXML SDK 2.0

  1. Create your macro code and save it in .xlsm format, say snorehorse.xlsm.
  2. Open snorehorse.xlsm in the OpenXML Productivity Toolkit and do a Reflect Code on the tree root.
  3. Find the macro's binary code. It's in a string format and looks like random characters.
  4. In your IDE, add a reference to OpenXML SDK, and programmatically create or open the excel file you want to inject the macro code into.
  5. Copy the macro string found in step #3 into your code.
  6. Add a new vba part to the destination.
  7. Feed the string data into the new vba part.
  8. Save and run and be pleased you bypassed the Trust Center.
  1. 创建您的宏代码并将其保存为 .xlsm 格式,例如 snorehorse.xlsm。
  2. 在 OpenXML Productivity Toolkit 中打开 snorehorse.xlsm 并在树根上执行 Reflect Code。
  3. 找到宏的二进制代码。它采用字符串格式,看起来像随机字符。
  4. 在您的 IDE 中,添加对 OpenXML SDK 的引用,并以编程方式创建或打开要将宏代码注入其中的 excel 文件。
  5. 将第 3 步中找到的宏字符串复制到您的代码中。
  6. 向目标添加一个新的 vba 部件。
  7. 将字符串数据输入到新的 vba 部分。
  8. 保存并运行,很高兴您绕过了信任中心。

Example code:

示例代码:

using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;

private string partData = "...";

    public void vbaInjector{    
        [code to create / open spreadsheet using OpenXML omitted]
        VbaProjectPart vbaProjectPart1 = snoreSpreadsheetDoc.WorkbookPart.AddNewPart<VbaProjectPart>("rId8");
        System.IO.Stream data = GetBinaryDataStream(partData);
        vbaProjectPart1.FeedData(data);
        data.Close();
        [code to close spreadsheet and cleanup omitted]
    }


    private System.IO.Stream GetBinaryDataStream(string base64String)
    {
        return new System.IO.MemoryStream(System.Convert.FromBase64String(base64String));
    }

I chose to add the OpenXML SDK dll into the project's local build so the end users won't have to install the SDK themselves.

我选择将 OpenXML SDK dll 添加到项目的本地构建中,这样最终用户就不必自己安装 SDK。

I think this can be done on a lower level, working with the XML, without using the OpenXML SDK, but I haven't attempted to learn how to do this. If anyone can post the code, I'll accept that Answer over mine.

我认为这可以在较低级别上完成,使用 XML,而不使用 OpenXML SDK,但我没有尝试学习如何做到这一点。如果有人可以发布代码,我会接受我的答案。

Also, if one had a programmatic way to convert VBA script, in an embedded resource file, into a binary string of the format excel expects, one could bypass having to copy and paste in a new string of binary data every time you wanted to change the macro code. That would be a superior answer to mine.

此外,如果有一种编程方式将嵌入资源文件中的 VBA 脚本转换为 excel 期望格式的二进制字符串,则可以绕过每次想要更改时都必须复制和粘贴新的二进制数据字符串宏代码。那将是我的一个更好的答案。

Thanks.

谢谢。

回答by Doug WB

If you use EPPlus, you can now include VBA programmatically. See here:

如果您使用 EPPlus,您现在可以以编程方式包含 VBA。看这里:

Writing and Executing VBA Macros on Excel without using Excel.Interop

在不使用 Excel.Interop 的情况下在 Excel 上编写和执行 VBA 宏