How can I embed some VBA code into a spreadsheet created using ClosedXML?

懵懂的女人 提交于 2019-12-05 03:59:29

The only way I know for inserting code to a VBA Project is to use Office.Interop.Excel along with Microsoft.Vbe.Interop (not sure about ClosedXML and other 3rd party...but still, wanted to share)

But since you are asking for an alternative this is how I would go about;

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


You need to allow programmatic access to VBA Project in Excel.

  • (Excel) File -> Options -> Trust Center -> Trust Center Settings -> Macro Settings -> Trust Access to the VBA Project Object Model

In your C# Solution add COM references to

  • Microsoft Visual Basic for Applications Extensibility 5.3

  • Microsoft Excel 14.0 Object Library

Add using directives to your C# code behind file

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

Now follow the code and comments

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();

In the above code;

you create an host Excel application, add a workbook. Access VBA Project Object module, add a new standard coding module to the VBA Project, write a VBA macro to that module. Application.Run("HelloWorld") simply calls the macro - note you can comment out this section if you don't want the box to pop-up. Then in the end you save the workbook as a Macro Enabled Workbook to a location specified in fullPath variable.

PS. Please note I haven't added any error handling.

For additional tips on C# and VBA see this blog Hope this helps :)

ClosedXML currently doesn't support writing VBA directly.

However you can manually add in a .bin file containing the predefined VBA macros/functions to an existing .XLSX spreadsheet programmatically. Write all of your VBA macros beforehand and save the file as a .XLSM file. Extract the contents to a folder and you'll have a vbaProject.bin containing all of your code. To get the VBA project to load properly, the workbook.xml requires the following additions:

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

The vbaProject.bin will need to be placed under the 'xl' folder, and the workbook will require a codeName GUID and alias ('ThisWorkbook' by default). All worksheets will also need a codeName (matching the sheet name) so that calls in the macros actually work when referencing named sheets.

John McNamara has created a working proof-of-concept in Perl that's worth checking out here.

Scanning over the assembly in IlSpy, this should be fairly straightforward to implement in ClosedXML, therefore if you have success here it would be a good idea to push your contribution over to the main project.

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

According to this link, the MIME type for Office Excel 2007 macro-enabled workbook (.xlms) is

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

Have you seen this post on the ClosedXml codeplex project regarding support for macros.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!