使用NPOI编辑带宏按钮的Excel文件后按钮失效求助
问题:使用NPOI填充带宏的Excel模板后,宏按钮失效
我有一个带宏按钮的Excel模板文件(Excel_template.xlsm),最初尝试新建Excel并迁移内容,但宏未被保留。改为复制原模板文件后,使用NPOI填充单元格值(仅为普通文本或数字),单元格值可正常写入,但带宏的按钮却失效了。
实现代码
// Paramerters string filename_org = "Excel_template.xlsm"; // Template file string server_folder = HttpContext.Current.Server.MapPath("~"); string file_path_org = server_folder + "\\temp\\" + filename_org; // New File **************************************************************** string filename_new = "Report_for_" + root.getProperty( "name", "" ) + "_" + pval.Replace("-", "_").Replace(":", "_") + ".xlsm"; string file_path_new = server_folder + "\\temp\\" + filename_new; // Copy file here ********************************************************** System.IO.File.Copy(file_path_org, file_path_new, true); FileStream fs; try { fs = new FileStream(file_path_new, FileMode.Open, FileAccess.Read); } catch( Exception e) { return inn.newError("Opening the Excel Template File FAILED: " + e.Message); } CCO.Utilities.WriteDebug("Excel_Report", "file_Open"); if (fs != null) { // WORKBOOK ************************************************************** IWorkbook xssWorkbook = new XSSFWorkbook(fs); fs.Close(); // WORKSHEET ISheet sheet = xssWorkbook.GetSheetAt(0); // UPDATE CELL VALUES **************************************************** //LOTS OF THESE HERE sheet.GetRow(9).GetCell(1).SetCellValue( root.getProperty( "name", "" ) ); // Save new result file **************************************************** using (var fs2 = new FileStream(file_path_new, FileMode.Create, FileAccess.Write)) { xssWorkbook.Write(fs2,false); fs2.Close(); } } CCO.Utilities.WriteDebug("Excel_REPORT", "Properties added"); //Add file to vault ******************************************************** Item file = inn.newItem("File","add"); file.setProperty("filename", filename_new); file.attachPhysicalFile(file_path_new); Item returnItem = file.apply(); returnItem.setProperty("errors",errorMessage); // Delete copied File File.Delete(file_path_new); return returnItem;
解决办法
核心原因
NPOI默认处理.xlsm文件时,不会保留VBA项目和宏按钮的关联信息,尤其是使用XSSFWorkbook的无参构造和Write(fs, false)重载时,会重新生成文件结构,破坏宏控件的关联数据。
具体修复步骤
初始化Workbook时保留VBA
打开文件时,给XSSFWorkbook构造函数传入第二个参数true,明确要求保留VBA内容:// 替换原有的Workbook初始化代码 IWorkbook xssWorkbook = new XSSFWorkbook(fs, true); // KeepVba=true修改文件写入逻辑
不要用FileMode.Create覆盖整个文件,而是打开已复制的模板文件,调用不带第二个参数的Write方法,让NPOI在原文件基础上更新内容,保留原有VBA和控件关联:// 替换原有的保存代码 using (var fs2 = new FileStream(file_path_new, FileMode.Open, FileAccess.Write)) { xssWorkbook.Write(fs2); // 不传入false,默认保留VBA fs2.Close(); }额外优化建议
- 优先使用Excel的表单控件按钮(而非ActiveX控件)关联宏,NPOI对表单控件的兼容性更好
- 确保模板文件中的宏名称和路径未被修改,填充数据时不要改动控件的位置或名称
- 生成文件后,打开时需手动启用Excel的宏功能(默认禁用),再测试按钮是否有效
内容的提问来源于stack exchange,提问作者Fchicken
相关产品推荐
相关产品推荐

