为什么这个Context.Sync不起作用?

时间:2016-12-29 14:53:23

标签: excel office-js

为什么此代码段不会将值写回Excel,除非我取消注释range.values = range.values行?

$('#run').click(function() {
    invokeRun()
        .catch(OfficeHelpers.logError);
});
function invokeRun() {
    return Excel.run(function(context) {
        var range = context.workbook.worksheets.getItem("Sheet1").getRange("A1:B3");
        range.load('values');
        return context.sync()
            .then(function() {
               range.values[1][1]=99;
               console.log(JSON.stringify(range.values));
                //range.values=range.values
                return context.sync();
        });
    });
}

1 个答案:

答案 0 :(得分:2)

数组属性很特殊。我在我的网站上添加了一个页面来描述主题: Reading and writing array properties

总结一下,代理对象模型的工作方式,无论何时在对象上设置属性,Office.js运行时都有一个挂钩到setter和getter,用于拦截调用并添加命令到队列。

让我们先举一个常规财产的例子。按照上面的说法,无论何时设置range.format.fill.color = "red"之类的东西,color属性的setter都会拦截请求,并在内部向队列添加一个命令,将范围填充颜色设置为红色(用下一个{{1分派) }})

另一方面,如果你只有context.sync (当然,在var color = range.format.fill.colorload之后),getter将触发而不是setter,颜色变量将获得范围的当前填充颜色。

现在,这是常规属性。无论何时设置数组的元素,都可以有效地将数组值作为getter访问。从运行时的角度来看,这一行与稍微冗长的版本没有区别:

sync

因为var array = range.values; array[r][c] = '-'; 的getter返回一个非常简单的JS数组对象,访问它然后设置它的值不会将它传播回原始的Range对象。

如果希望将值反射回来,最好的方法是在同步后立即获取对数组的引用(即var array = range.values,如上所述),然后在数组上设置值根据需要,然后最终将其设置回对象:range.values

这意味着您还可以在适当的位置修改values数组,然后在循环完成时将values属性赋值回自身(range.values = array)。然而,这看起来很尴尬,好像它是一个无操作,而实际上它不是。所以个人而言,我更喜欢在开始时检索数组并将其分配给自己的变量,然后进行任何必要的修改,最后设置完整的数组。

更新以澄清上述内容:

非常清楚,通过访问range.values = range.values.values等, ARE 纯粹的vanilla JS数组返回了数组。这实际上是问题的症结所在:为了让Office.js返回纯粹的对象,这意味着那些纯粹的对象不能被sp" spiked"能够反映变化。

对于它的价值,我们实际上有一个即将推出的功能,应在一两个月内推出,我们将在其中引入.formulas语法,如:

object.set

这样可以更方便地在同一个对象上设置多个属性,但它也可以使数组属性更容易处理。