Office Scripts嵌套for循环仅重复输出数组末位值问题
问题背景
使用Power Automate搭配Office Scripts搭建Excel批量创建功能,核心逻辑为向Excel脚本传入值数组,由脚本将数组内全部值更新至Excel表中,Office Scripts基于JavaScript语言实现。
运行时出现异常:执行结果仅重复写入流程传入数组的最后一个值,表内批量写入的内容均为重复的数组末位值,异常表现如下:
经排查云流配置无问题,错误定位在内存表生成新行的代码段,故障代码如下:
//-1 to 0 index the RowNum RowNum = RowNum - 1; //Iterate through each object item in the array from the flow for (let i = 0; i < CreateData.length; i++) { //Create an empty row at the end of the 2D table array & increase RowNum by 1 for the next line updating that row TableData.push(EmptyRow); RowNum++; //Iterate through each item or line of the current object for (let j = 0; j < Object.keys(CreateData[i]).length; j++) { //Create each value for each item or column given TableData[RowNum][Number(Object.keys(CreateData[i])[j])] = CreateData[i][Object.keys(CreateData[i])[j]]; } }
对比验证情况
逻辑几乎完全一致的另外两段代码均可正常运行:
- 大表批量创建场景代码(无内存操作,直接操作表格对象):
//Iterate through each object item in the array from the flow for (let i = 0; i < CreateData.length; i++) { //Create an empty row at the end of the 2D table array & increase RowNum by 1 for the next line updating that row table.addRow() RowNum = RowNum + 1 //Iterate through each item or line of the current object for (let j = 0; j < Object.keys(CreateData[i]).length; j++) { //Create each value for each item or column given TableRange.getCell(RowNum, Number(Object.keys(CreateData[i])[j])).setValue(CreateData[i][Object.keys(CreateData[i])[j]]) } }
- 批量更新脚本同类逻辑代码:
//Iterate through each object item in the array from the flow for (let i = 0; i < UpdatedData.length; i++) { //If the record's Primary Key value is found continue, else post to error log if (ArrayPK.indexOf(UpdatedData[i].PK) > 0) { //Get the row number for the line to update by matching the foreign key from the other datasource to the primary key in Excel RowNum = ArrayPK.indexOf(UpdatedData[i].PK) //Iterate through each item or line of the current object for (let j = 0; j < Object.keys(UpdatedData[i]).length - 1; j++) { //Update each value for each item or column given TableData[RowNum][Number(Object.keys(UpdatedData[i])[j])] = UpdatedData[i][Object.keys(UpdatedData[i])[j]] } }
排查测试现象
- 反复校验未发现代码存在显性逻辑错误。实际测试发现:若将代码中
i的引用替换为静态数字,使其固定引用数组内同一项,则最终会重复写入该静态索引对应的值;故障场景下嵌套循环内的i引用仿佛始终指向Power Automate传入数组的最后一项(即循环中i可取到的最大值),不会随i++正常迭代取值。 - 补充测试显示:若手动将
EmptyRow替换为["", "", "", ""]这类手动构造的空值数组,故障会消失,新行可正常写入,但手动构造的空行与自动生成的EmptyRow结构、输出内容、长度完全一致,无法直接定位故障原因。
故障根因
该问题是JavaScript引用类型特性导致的典型坑点,和循环逻辑、Power Automate传参均无关系:EmptyRow是提前定义好的数组对象,属于引用类型。循环中每次执行TableData.push(EmptyRow)时,并没有创建新的独立空行数组,只是把同一个EmptyRow的内存引用重复存入TableData——也就是说TableData里所有被认为是“新行”的条目,本质上都指向内存里的同一个数组对象。
后续循环给不同行索引赋值时,实际都是在修改这同一个公共数组的内容,每一次循环都会覆盖上一次写入的值,等整个循环执行完,所有行指向的数组里存的自然就是最后一次循环写入的数组末位值,最终表现为全表重复最后一条数据。
手动写入字面量["", "", "", ""]时故障消失,是因为数组字面量每次执行都会生成一个全新的独立数组对象,每行指向独立的内存空间,修改操作互不干扰。而提前定义的EmptyRow被重复引用,才触发了该问题。
另外两段可正常运行的代码不受该问题影响的原因也很明确:直接操作表格对象新增行的代码,每次addRow()都会生成独立的新行,不存在引用复用;批量更新的代码是修改TableData中已存在的独立行对象,没有重复push同一个引用的操作,因此逻辑正常。
修复方案
只需要修改新增空行的逻辑,保证每次push到TableData的都是独立的新数组即可,两种常用实现:
- 每次push时对原有
EmptyRow做浅拷贝,生成独立副本:TableData.push([...EmptyRow]); - 每次push时直接生成和
EmptyRow长度一致的新空数组,效果和手动写字面量完全一致:TableData.push(new Array(EmptyRow.length).fill(""));
内容的提问来源于stack exchange,提问作者Tyler Kolota

