【问题标题】:How to identify the changed cell in office js api BindingDataChanged event?如何识别 office js api BindingDataChanged 事件中更改的单元格?
【发布时间】:2016-09-28 16:46:40
【问题描述】:

当在 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 上使用表格绑定完成的,而不是在 Office 365 上进行的。接下来会尝试)

【问题讨论】:

    标签: office-js


    【解决方案1】:

    我认为上述跟踪 selectionchanged 的​​解决方案很聪明,但我相信它会让您在事件触发之间处于竞争状态。我测试了上述解决方案,似乎 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 中包含此内容。祈祷它即将到来!:)

    注意 - 它似乎适用于复制和粘贴,但需要增强此解决方案以处理以下情况:

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

    更新 1 - 另一种情况

    • 更新绑定的边缘单元格并按 Enter 时,将导致选择超出绑定范围。 on selection change 事件不会启动,上述解决方案将失败

    【讨论】:

    • 正如您在更新 1 和其他情况中提到的那样,处理所有边缘情况将是一件痛苦的事情。希望 excel 团队早日在EventArgs 中添加信息。为 API 1.4 提供此功能或团队提供更好的解决方法而祈祷。
    • @OfficeDev 团队应该在工作表已更改事件 (VSTO) 中实现该功能,您可以在其中轻松识别哪些单元格已更改,而无需费劲。
    【解决方案2】:

    没有直接的方法来获取绑定中发生更改的行。

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

    代码如下:

    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,Office 插件的 PM

    【讨论】:

    • 1.当用户拖放时,这是如何工作的?这些事件总是一个接一个地发生吗?此外,看起来当多个用户在工作表上时,所有用户都会收到BindingSelectionChanged 事件。在这种情况下如何区分选择更改。
    • 你有两个选择:要么等到用户在拖放后更改他们的选择(这适用于我上面的解决方案),要么修改解决方案以检查 当前-选定的范围。
    • 你能详细解释一下选项2吗?我们如何跟踪大型 Excel 工作表中的变化?这里有什么推荐的方法吗?第一个选项对用户有两个很大的依赖关系,除非 office api 触发拖动结束事件。
    • 另外,当多个用户在工作表上时,所有用户都会收到BindingDataChange事件。在这种情况下如何区分更改的选择以识别是否发生在其他用户身上?
    【解决方案3】:

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

    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. 
            });
        });
    }
    

    【讨论】:

      【解决方案4】:

      据我了解您的问题,您需要相应点击单元格的标题名称

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

      对象可以是表格或工作表。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-07-21
        • 1970-01-01
        • 1970-01-01
        • 2012-10-12
        • 1970-01-01
        • 2019-01-13
        相关资源
        最近更新 更多