Excel.js自定义函数:调用单元格数字格式与列宽自适应问题
问题:Excel.js自定义函数设置数字格式后列宽自适应失效
我正尝试为Excel.js自定义函数的调用单元格设置数字格式,具体是将大数的科学计数法替换为数值格式,然后自动适配列宽。原本打算通过检查单元格文本中是否存在"E"来判断,但格式化代码似乎在结果写入单元格前就执行了,因此改为通过判断返回结果来设置格式。设置数字格式的功能正常(无需等待结果写入单元格),但列宽自适应功能失效。
自定义函数说明
getData通过API调用返回数字(或错误字符串)formatNumber需根据返回结果设置单元格数字格式并自动适配列宽
现有代码
Test 自定义函数
async function Test(symbol, metric, date, invocation) { const address = invocation.address; return await getData(symbol, metric, date) .then(async (result) => { if (!isNaN(result) && result > 99999999999) { await formatNumber(address); } return result; }) .catch((error) => { console.log("error: " + error); return error; }); }
formatNumber 格式化函数
此时range.text返回#BUSY,说明函数执行时API数据仍在获取中,导致autofitColumns会根据"#BUSY"字符串长度设置列宽。
async function formatNumber(address) { await Excel.run(async (context) => { const formats = [[",##0"]]; const range = context.workbook.worksheets.getActiveWorksheet().getRange(address); range.load("text"); await context.sync(); console.log("range.text: " + range.text); range.load("numberFormat"); await context.sync(); range.numberFormat = formats; range.format.autofitColumns(); await context.sync(); }); }
解决思路
1. 监听单元格内容变化后执行列宽适配
利用Excel.js的工作表变更事件,等待单元格内容从#BUSY更新为最终结果后,再触发列宽自适应:
// 全局存储需要处理的单元格地址 const pendingAddresses = new Set(); async function Test(symbol, metric, date, invocation) { const address = invocation.address; return await getData(symbol, metric, date) .then(async (result) => { if (!isNaN(result) && result > 99999999999) { pendingAddresses.add(address); await formatNumber(address); } return result; }) .catch((error) => { console.log("error: " + error); return error; }); } // 初始化时绑定工作表变更监听 Office.initialize = function() { Excel.run(async (context) => { const worksheet = context.workbook.worksheets.getActiveWorksheet(); worksheet.onChanged.add(handleWorksheetChange); await context.sync(); }); }; async function handleWorksheetChange(event) { const address = event.address; if (pendingAddresses.has(address)) { await Excel.run(async (context) => { const range = context.workbook.worksheets.getActiveWorksheet().getRange(address); range.format.autofitColumns(); await context.sync(); }); pendingAddresses.delete(address); } }
2. 基于结果手动计算列宽
既然已经拿到了API返回的最终结果,直接根据格式化后的字符串长度手动设置列宽,无需依赖autofitColumns:
async function formatNumber(address, result) { await Excel.run(async (context) => { const formats = [[",##0"]]; const range = context.workbook.worksheets.getActiveWorksheet().getRange(address); range.numberFormat = formats; // 按指定格式转换结果为字符串,计算显示长度后设置列宽(默认字体下1字符约对应1.2列宽) const formattedStr = new Intl.NumberFormat('en-US', { useGrouping: true, maximumFractionDigits: 0 }).format(result); range.format.columnWidth = formattedStr.length * 1.2; // 预留少量余量 await context.sync(); }); } // 修改Test函数,调用formatNumber时传入结果 async function Test(symbol, metric, date, invocation) { const address = invocation.address; return await getData(symbol, metric, date) .then(async (result) => { if (!isNaN(result) && result > 99999999999) { await formatNumber(address, result); } return result; }) .catch((error) => { console.log("error: " + error); return error; }); }
内容的提问来源于stack exchange,提问作者user2285985
相关产品推荐
相关产品推荐

