如何将一些VBA代码embedded到使用ClosedXML创build的电子表格中?

我正在使用ClosedXML从C#(asp.net-mvc)生成电子表格,它工作的很好。 我还有一个额外的要求,所以我想获得一些关于如何实现这一目标的反馈。

我想保存为一个macros启用工作簿,当我只是给它一个“xlsm”扩展它似乎并没有打开(与xlsx)。 这是我的代码:

public ActionResult ExportExcel() { MemoryStream stream = nModel.GenerateSS(); return File(stream, @"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml", "MySS.xlsx"); } 

但如果我尝试这样做:

 public ActionResult ExportExcel() { MemoryStream stream = nModel.GenerateSS(); return File(stream, @"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml", "MySS.xlsm"); } 

Excel试图打开时抱怨。

然后,假设我可以做#1,我需要能够采取一些VBA(假设只是一个硬编码函数),并插入到模块或工作簿,所以当有人打开电子表格,并点击macros,他们可以运行macros。 从谷歌search,这似乎并不支持ClosedXML,所以我很好奇,如果有人有任何其他方式来实现这一目标?

我知道将代码插入到VBA项目的唯一方法是使用Office.Interop.Excel以及Microsoft.Vbe.Interop不确定关于ClosedXML和其他第三方…但仍然想分享

但是,既然你在寻求替代scheme,那么我将如何去做;

Creating a workbook and inserting a macro to it using C#


您需要允许在Excel中编程访问VBA项目 。

  • (Excel)文件 – >选项 – >信任中心 – >信任中心设置 – >macros设置 – >信任访问VBA项目对象模型

在这里输入图像说明

在您的C#解决scheme中添加COM引用

  • Microsoft Visual Basic for Applications扩展性5.3

  • Microsoft Excel 14.0对象库

将使用指令添加到文件后面的C#代码

 using Microsoft.Office.Interop.Excel; using System.Reflection; using Microsoft.Vbe.Interop; using System.Runtime.InteropServices; 

现在按照代码和评论

 Microsoft.Office.Interop.Excel.Application xlApp = new Microsoft.Office.Interop.Excel.Application(); xlApp.Visible = true; Workbook wb = xlApp.Workbooks.Add(XlWBATemplate.xlWBATWorksheet); VBProject vbProj = wb.VBProject; // access to VBAProject VBComponent vbComp = vbProj.VBComponents.Add(vbext_ComponentType.vbext_ct_StdModule); // adding a standard coding module vbComp.CodeModule.DeleteLines(1, vbComp.CodeModule.CountOfLines); //emptying it // this is VBA code to add to the coding module string code = "Public Sub HelloWorld() \n" + " MsgBox \"hello world!\" \n" + "End Sub"; // code should be added to the module now vbComp.CodeModule.AddFromString(code); // location to which you want to save the workbook - desktop in this case string fullPath = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory) + "\\macroWorkbook.xlsm"; // run the macro xlApp.Run("HelloWorld"); // save as macro enabled workbook wb.SaveAs(Filename: fullPath, FileFormat: XlFileFormat.xlOpenXMLWorkbookMacroEnabled); xlApp.Quit(); 

在上面的代码中;

您创build一个主机Excel应用程序,添加一个工作簿。 访问VBA项目对象模块,为VBA项目添加一个新的标准编码模块,将VBAmacros写入该模块。 Application.Run("HelloWorld")只是简单地调用macros – 注意如果你不想popup这个框,你可以注释掉这个部分。 然后最后将工作簿保存为已启用macros的工作簿fullPathvariables中指定的位置。

PS。 请注意我没有添加任何error handling。

有关C#和VBA的其他技巧,请参阅此博客希望这有助于:)

ClosedXML目前不支持直接编写VBA。

但是,您可以通过编程手动将包含预定义VBAmacros/函数的.bin文件添加到现有的.XLSX电子表格中。 事先写好所有的VBAmacros,并将该文件保存为.XLSM文件。 将内容提取到一个文件夹,你将有一个vbaProject.bin包含所有的代码。 要使VBA项目正确加载,workbook.xml需要添加以下内容:

 <Default Extension="bin" ContentType="application/vnd.ms-office.vbaProject"/> <Override PartName="/xl/workbook.xml" ContentType="application/vnd.ms-excel.sheet.macroEnabled.main+xml"/> 

vbaProject.bin需要放在“xl”文件夹下,工作簿需要一个codeName GUID和别名(默认情况下为“ThisWorkbook”)。 所有的工作表还需要一个codeName(匹配工作表名称),以便在引用命名工作表时macros中的调用实际上工作。

约翰·麦克纳马拉(John McNamara)在Perl中创build了一个工作validation概念,值得在这里查看: http : //blogs.perl.org/users/john_mcnamara/2012/12/adding-macros-to-excelwriterxlsx.html

在IlSpy上扫描程序集,在ClosedXML中实现这个应该相当简单,因此如果你在这里取得成功,将你的贡献推到主项目上是个好主意。

 return File(stream, @"application/vnd.ms-excel.sheet.macroEnabled.12", "MySS.xlsm"); 

根据此链接 ,Office Excel 2007macrosfunction工作簿(.xlms)的MIMEtypes为

application/vnd.ms-excel.sheet.macroEnabled.12

您是否在ClosedXml codeplex项目中看到过有关macros支持的文章。