在開發 Microsoft Office 應用程式時,如果會輸出大量資料到 Office 文件中(例如:建立許多文字方塊),執行速度會比較慢。因為每次輸出資料到 Office 文件時,需要花一點時間更新畫面的顯示。因此,如果在餵資料給 Office 文件之前,先把 Application.ScreenUpdating 屬性設定為 false,等到處理完畢之後再恢復 Application.ScreenUpdating 為 true,速度就會快很多。

我寫了兩個測試程式,分別用 OLE Automation 的方式和 VSTO 的方式,在一個空白的 WORD 文件中連續建立 200 個文字方塊,以觀察執行效能的差異。

測試環境

  • Visual Studio .NET 2003
  • Windows Server 2003
  • 記憶體:1.5GB

測試結果

使用 OLE Automation:

  • ScreenUpdating = true :0 分 36.98 秒
  • ScreenUpdating = false:0 分 21.64 秒

使用 VSTO:

  • ScreenUpdating = true :1 分 19.87 秒
  • ScreenUpdating = false:0 分 13.48 秒

從結果可以看出,不管是用 OLE Automation 還是用 VSTO 的方式,在輸出資料的過程中暫時關閉螢幕更新都能有效提升執行效能。比較詭異的現象是使用 VSTO 測試結果,ScreenUpdating = false 時是所有測試結果中最快的,可是 ScreenUpdating = true 時卻是最慢的,而且時間多達一分鐘以上,比其他測試結果多了兩到三倍以上的時間,而且測試幾次的結果都一樣。

以下是測試的程式碼:

using Office = Microsoft.Office.Core;
using Word = Microsoft.Office.Interop.Word;
...

  protected void ThisDocument_Open()
  {
    object missing = System.Type.Missing;
    object fname = @"C:\Temp\測試文件-複製.doc";
  
    thisDocument.SaveAs(ref fname, ref missing, ref missing, ref missing, 
      ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, 
      ref missing, ref missing, ref missing, ref missing, ref missing, ref missing); 
  
    Test(true);
  
  }

  // 測試連續建立 200 個文字方塊要花多少時間
  private void Test(bool disableRefresh) 
  {
    object missing = System.Type.Missing;
    int x = 10;
    int y = 10;
  
    thisApplication.ScreenUpdating = !disableRefresh;
  
    DateTime beginTime = DateTime.Now;
  
    for (int i = 0; i < 200; i++) 
    {
      Word.Shape txtBox = thisDocument.Shapes.AddTextbox(
        Office.MsoTextOrientation.msoTextOrientationHorizontal, x, y, 40, 30, ref missing);
      txtBox.TextFrame.TextRange.Font.Size = 80.0f;   
      txtBox.TextFrame.TextRange.Text = "文字 " + i.ToString();
  
      x += 50;
      if (x > 500) 
      {
        x = 10;
        y += 40;
      }
    }
  
    // 恢復螢幕更新.
    thisApplication.ScreenUpdating = true;
  
    // 將花費的時間輸出到文件中.
    TimeSpan diffTime = new TimeSpan(DateTime.Now.Ticks - beginTime.Ticks);
    thisApplication.Selection.TypeText("共花費時間: " + diffTime.ToString());
  }

OLE Automation 的程式寫法跟 VSTO 的寫法類似,就不列出了。