保存然后操作表格时 Word 挂起

Word hangs when saving and then manipulating tables

我最近 运行 在 Word 中遇到了一个非常棘手的问题,我没想到能够解决。但我做到了,现在我想分享那个解决方案。

我看到的行为是 table 操作经常会弄乱图形并挂起文字,以至于需要重新启动它,除非您在它停止挂起后撤消更改。我发现的可重现测试用例是:

  1. 创建或打开带有 table 的任何文档。
  2. 保存两次。
  3. 使用弹出的控件插入新列。

我的解决方案在保存期间做了很多不同的事情,我的日志中没有出现任何异常或任何表明任何错误的东西。

这在普通 Word 中不会发生。

为了查明原因,我开始删除大量代码并重新测试以确定它是否有所不同。

我最终创建了这个 MCVE:

Note that this is a document-level template project.

using System;
using Microsoft.Office.Tools.Word;
using Microsoft.Office.Interop.Word;

namespace TableUndoBug
{
    public partial class ThisDocument
    {
        private void ThisDocument_Startup(object sender, System.EventArgs e)
        {
            BeforeSave += ThisDocument_BeforeSave;
        }

        private void ThisDocument_BeforeSave(object sender, SaveEventArgs e)
        {
            try
            {
                foreach (Table table in Tables)
                {
                    int numRows = table.Rows.Count;
                    var c = table.Cell(numRows, 0); // this line is the culprit
                    // this call should be using 1, not 0, but it completes successfully anyway.
                    // if you change it, this bug disappears
                }
            }
            catch (Exception)
            {
            }
        }

        private void ThisDocument_Shutdown(object sender, System.EventArgs e)
        {
        }

        #region VSTO Designer generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InternalStartup()
        {
            this.Startup += new System.EventHandler(ThisDocument_Startup);
            this.Shutdown += new System.EventHandler(ThisDocument_Shutdown);
        }

        #endregion
    }
}

下面是测试步骤(我在整理这些时还发现了更多测试用例):

This sample project illustrates a bug in Word 2013/VSTO.

To replicate:

  1. Run it from Visual Studio.

  2. Save the document anywhere.

  3. Insert a table.

测试用例 1:

  1. Save it again 2 more times.

  2. Try to insert a column using the controls that pop up on hover.

    Graphics will be messed up but it will not hang.

测试用例 2:

  1. Add a caption using the table's context menu (I think what matters here is the style application).
  2. Save it again 2 more times.
  3. Try to insert a column using the controls that pop up on hover.

    Graphics will be messed up and it will hang for a while.

测试用例 3:

  1. Save it again 2 more times.
  2. Use the undo button in the Quick Access Toolbar.
  3. Use the redo button in the Quick Access Toolbar.

    Graphics will be messed up and it will hang for a while.

解决方案就在代码中:检查应该基于 1 的基于 0 的索引。 API 应该会在这里失败,但由于某些原因它不会。