Angular中如何用TypeScript结合VBA读写带宏的Excel文件?
解决XLSM模板写入数据后丢失VBA宏与格式的问题
问题根源
SheetJS(xlsx库)默认仅聚焦于单元格数据的读写,不会自动保留XLSM文件中的VBA宏资源(如xl/vbaProject.bin),且免费版本对复杂Excel格式(如自定义布局、条件格式)的支持有限,导致修改后文件丢失宏和原有布局。
解决方案
方案1:使用SheetJS保留VBA与基础格式
通过配置SheetJS的读写参数,强制保留VBA资源,并启用样式支持(需注意Pro版本才能完整保留样式):
// Angular组件中实现代码 async writeDataToXLSM() { // 1. 加载XLSM模板文件(示例从assets目录读取) const templateRes = await fetch('assets/your-template.xlsm'); const templateBuffer = await templateRes.arrayBuffer(); // 2. 读取工作簿,开启VBA保留选项 const workbook = XLSX.read(templateBuffer, { type: 'array', bookVBA: true // 保留VBA宏资源 }); // 3. 定位目标工作表并修改数据 const targetSheet = workbook.Sheets['目标工作表名']; // 单个单元格写入 targetSheet['A1'].v = 'Angular传入的数据'; // 批量数据写入(示例) const data = [{ 姓名: '张三', 年龄: 28 }, { 姓名: '李四', 年龄: 32 }]; XLSX.utils.sheet_add_json(targetSheet, data, { origin: 'A3' }); // 4. 写入文件,指定XLSM格式并保留VBA const outputBuffer = XLSX.write(workbook, { type: 'array', bookType: 'xlsm', bookVBA: true, cellStyles: true // 开启样式保留(SheetJS Pro版本支持) }); // 5. 触发浏览器下载 const blob = new Blob([outputBuffer], { type: 'application/vnd.ms-excel.sheet.macroEnabled.12' }); const downloadUrl = URL.createObjectURL(blob); const link = document.createElement('a'); link.href = downloadUrl; link.download = 'filled-template.xlsm'; link.click(); URL.revokeObjectURL(downloadUrl); }
方案2:直接操作XLSM的ZIP结构(完整保留宏与格式)
XLSM本质是ZIP压缩包,通过jszip库直接修改包内的工作表XML文件,不触动宏和格式相关的文件,可100%保留原始内容:
先安装依赖:
npm install jszip实现代码:
import JSZip from 'jszip'; async modifyXLSMRaw() { // 1. 加载模板并解析为ZIP const templateRes = await fetch('assets/your-template.xlsm'); const templateBuffer = await templateRes.arrayBuffer(); const zip = await JSZip.loadAsync(templateBuffer); // 2. 获取目标工作表的XML内容(替换为你的工作表路径,如sheet2.xml) const sheetXmlStr = await zip.file('xl/worksheets/sheet1.xml')?.async('string'); if (!sheetXmlStr) return; // 3. 解析XML并修改单元格 const parser = new DOMParser(); const xmlDoc = parser.parseFromString(sheetXmlStr, 'application/xml'); // 修改B2单元格的值(示例) const targetCell = xmlDoc.querySelector('c[r="B2"] v'); if (targetCell) { targetCell.textContent = '从Angular写入的新值'; } // 4. 将修改后的XML放回ZIP包 const modifiedXml = new XMLSerializer().serializeToString(xmlDoc); zip.file('xl/worksheets/sheet1.xml', modifiedXml); // 5. 生成新的XLSM文件并下载 const outputBuffer = await zip.generateAsync({ type: 'array', compression: 'DEFLATE' }); const blob = new Blob([outputBuffer], { type: 'application/vnd.ms-excel.sheet.macroEnabled.12' }); const downloadUrl = URL.createObjectURL(blob); const link = document.createElement('a'); link.href = downloadUrl; link.download = 'filled-template.xlsm'; link.click(); URL.revokeObjectURL(downloadUrl); }
注意事项
- 方案1中SheetJS免费版仅支持基础样式保留,复杂布局(如合并单元格、条件格式)可能仍会丢失,需使用Pro版本。
- 方案2需要熟悉Excel的OOXML结构,批量写入数据时需手动处理XML中的行和单元格节点,适合对格式完整性要求极高的场景。
内容的提问来源于stack exchange,提问作者Chabba Mohamed Nadir
相关产品推荐
相关产品推荐

