如何在office js api BindingDataChanged事件中识别已更改的单元格?

时间:2016-09-28 16:46:41

标签: office-js

当在excel中的绑定中更改数据时,如果触发了BindingDataChanged事件。

function addHandler() {
    Office.select("bindings#MyBinding").addHandlerAsync(
    Office.EventType.BindingDataChanged, dataChanged);
}
function dataChanged(eventArgs) {
    write('Bound data changed in binding: ' + eventArgs.binding.id);
}

eventArgs没有关于数据的哪个部分发生变化的信息。有什么办法,我们可以跟踪这些信息吗?我们有大量细胞的绑定,如5000行* 15列或90行* 350列。我们正在使用office js api 1.2。

更新1 使用下面Michael Saunders提供的代码。看到一些奇怪的行为。我选择了G9:H9并按下删除。但是标题总是以Column1和Column2的形式返回(查看右上角的toastr通知)。我期待Column7和Column8。这是预期的行为吗? (测试是在带有表格绑定的Excel 2016上完成的,而不是在办公室365上进行。接下来会尝试)data changed behavior

4 个答案:

答案 0 :(得分:1)

我认为跟踪选择的上述解决方案是聪明的,但我相信它可以让您在事件发生之间处于竞争状态。我测试了上面的解决方案,看起来SelectionChange在DataChanged事件之前触发,这意味着你将抓住当前选定的单元而不是之前的单元。我不认为你可以避免这种竞争条件,因为事件是异步的,但你可以跟踪以前和当前的选择:

myBinding.addHandlerAsync(Office.EventType.BindingSelectionChanged, onSelectionChange);

var startRow, rowCount, startColumn, columnCount;
var previousStartRow, previousRowCount, previousStartColumn, previousColumnCount;



function onSelectionChange(eventArgs){
    // save "previous" selected cell into previous variables 
    previousStartRow = startRow;
    previousRowCount = rowCount;
    previousStartColumn = startColumn;
    previousColumnCount = columnCount;

    // re-assign the current selected to the eventArgs
    startRow = eventArgs.startRow;
    rowCount = eventArgs.rowCount;
    startColumn = eventArgs.startColumn;
    columnCount = eventArgs.columnCount;
}

function onBindingDataChange(eventArgs){
    eventArgs.binding.getDataAsync({
        startRow: previousStartRow,
        rowCount: previousRowCount,
        startCol: previousStartColumn,
        columnCount: previousColumnCount  
    }, function(result){
        // Do whatever you need with result.value.
        // You might want to compare and update your in-memory representation of the data. 
    });
}

我测试了它并且它有效......不太好并且可能有更好的方法来跟踪多个级别,但它似乎工作。理想情况下,DataChanged事件会在像VSTO这样的EventArgs中使用它。手指越过它即将到来!:)

注意 - 它似乎与copy&粘贴,但需要增强此解决方案以处理以下情况:

  • 使用“+”符号拖动单元格。
  • 选择多个单元格,然后使用键盘更新单个单元格并输入

更新1 - 另一种情况

  • 更新绑定的边缘单元格并按下输入时,将导致选择超出绑定范围。 on选择更改事件没有启动,上述解决方案将失败

答案 1 :(得分:0)

没有一种直接的方法可以让绑定中的行发生变化。

避免检查整个表格的最佳解决方法是跟踪用户的选择。每次用户在Binding中选择某些内容时,BindingSelectionChanged event都会触发,这在输入表格中的数据时总会发生。解决方案是始终在内存中保存绑定中最新的先前选择位置。然后,当数据发生变化时,请检查存储的位置。

以下是代码:

myBinding.addHandlerAsync(Office.EventType.BindingSelectionChanged, onSelectionChange);

var previousStartRow, previousRowCount, previousStartColumn, previousColumnCount;

function onSelectionChange(eventArgs){
    previousStartRow = eventArgs.startRow;
    previousRowCount = eventArgs.rowCount;
    previousStartColumn = eventArgs.startColumn;
    previousColumnCount = eventArgs.columnCount;
}

function onBindingDataChange(eventArgs){
    eventArgs.binding.getDataAsync({
        startRow: previousStartRow,
        rowCount: previousRowCount,
        startCol: previousStartColumn,
        columnCount: previousColumnCount  
    }, function(result){
        // Do whatever you need with result.value.
        // You might want to compare and update your in-memory representation of the data. 
    });
}

-Michael,PM for Office加载项

答案 2 :(得分:0)

Micheal的答案唯一的问题是,在onBindingDataChanged函数中,getDataAsync方法的参数对象的startColumn被错误地传递为startCol,这就是返回起始列的原因。 / p>

function onSelectionChange(eventArgs) {
    startRow = eventArgs.startRow;
    rowCount = eventArgs.rowCount;
    startColumn = eventArgs.startColumn;
    columnCount = eventArgs.columnCount;
}

// When data in the table is changed, this event is triggered.
function onBindingDataChanged(eventArgs) {
    Excel.run(function (ctx) {
        // Highlight the table in orange to indicate data changed.
        eventArgs.binding.getDataAsync({
            startRow: startRow,
            rowCount: rowCount,
            ***startColumn***: startColumn,
            columnCount: columnCount
        }, function (result) {
            // Do whatever you need with result.value.
            console.log(result.value);
            // You might want to compare and update your in-memory representation of the data. 
        });
    });
}

答案 3 :(得分:0)

据我所知,您需要相应点击单元格的标题名称

object.onSelectionChanged.add(selectionChangedCallback) 从EventArgs可以获取单元格地址(在上述情况下为G9:h9)。因此,只需从这些值中获取引用即可(例如G1或H1,此值取决于您的逻辑,如果它是表,则可以从表头范围位置获得帮助)并从中获得价值。

对象可以是表或工作表。