2010-04-19 200 views
10

我通過Microsoft Office OpenXML SDK 2.0更新Excel電子表格的某些單元格。更改值會使包含取決於已更改單元格的公式的所有單元無效。但是,由於緩存的值,Excel不會重新計算公式,即使用戶單擊「立即計算」。OpenXML SDK:使Excel重新計算公式

什麼是通過SDK使整個工作簿的所有相關單元無效的最佳方法?到目前爲止,我發現下面的代碼片段在http://cdonner.com/introduction-to-microsofts-open-xml-format-sdk-20-with-a-focus-on-excel-documents.htm

public static void ClearAllValuesInSheet 
     (SpreadsheetDocument spreadSheet, string sheetName) 
{ 
    WorksheetPart worksheetPart = 
     GetWorksheetPartByName(spreadSheet, sheetName); 

    foreach (Row row in 
     worksheetPart.Worksheet. 
      GetFirstChild().Elements()) 
    { 
     foreach (Cell cell in row.Elements()) 
     { 
      if (cell.CellFormula != null && 
        cell.CellValue != null) 
      { 
       cell.CellValue.Remove(); 
      } 
     } 

    } 

    worksheetPart.Worksheet.Save(); 
} 

除了這個事實,這個片段不編譯對我來說,它有兩個限制:

  • 它只是一個無效單張,儘管其他表可能包含獨立公式
  • 它不考慮任何依賴關係。

我正在尋找一種方式,是有效的(特別是,僅無效依賴於某個單元格的值單元格),並採取所有工作表考慮在內。

更新:

在我已成功地使代碼編譯&運行,並取消對工作簿中的所有工作表的緩存值其間。 (請參閱答案。)我仍然對更好/替代解決方案感興趣,特別是如何僅刪除實際依賴更新單元格的單元格的緩存值。

+0

刪除緩存值後,如何讀取單元格的值?是否有必要關閉對象?在我的情況下,我得到的價值並沒有返回任何東西 – mggSoft 2013-10-21 16:46:46

回答

39
spreadSheet.WorkbookPart.Workbook.CalculationProperties.ForceFullCalculation = true; 
spreadSheet.WorkbookPart.Workbook.CalculationProperties.FullCalculationOnLoad = true; 

適合我!

+0

酷,看起來更簡單!爲了使其更具可讀性,您可以編輯您的答案並刪除源代碼前面的空格嗎? (爲了將文本格式化爲源代碼,最多需要4個空格) – chiccodoro 2010-11-24 07:56:03

+0

Bang!也爲我工作了,謝謝! – Brian 2013-04-15 16:14:42

+0

它不適用於我在這種形式和以前的消息。我可以嘗試什麼? – mggSoft 2013-10-21 16:21:14

1

由於這部分解決我的問題,有似乎沒有更好的解決方案,到目前爲止,感動,代碼塊從問題的答案了...這是新代碼的樣子:

foreach (WorksheetPart worksheetPart in spreadSheet.WorkbookPart.WorksheetParts) 
{ 
    foreach (Row row in 
      worksheetPart.Worksheet.GetFirstChild<SheetData>().Elements()) 
    { 
     foreach (Cell cell in row.Elements()) 
     { 
      if (cell.CellFormula != null && cell.CellValue != null) 
       cell.CellValue.Remove(); 
     } 
    } 
} 
2

我用這個

static void FlushCachedValues(SpreadsheetDocument doc) 
    { 
     doc.WorkbookPart.WorksheetParts 
      .SelectMany(part => part.Worksheet.Elements<SheetData>()) 
      .SelectMany(data => data.Elements<Row>()) 
      .SelectMany(row => row.Elements<Cell>()) 
      .Where(cell => cell.CellFormula != null) 
      .Where(cell => cell.CellValue != null) 
      .ToList() 
      .ForEach(cell => cell.CellValue.Remove()) 
      ; 
    } 

這刷新緩存值

迎接

+0

我已經嘗試過這一點,並刪除緩存的值後,我得到的價值並沒有返回任何東西 – mggSoft 2013-10-21 16:49:08

+0

相同在這裏這種方法不適用於我。我在SO上發佈了類似的問題。 – 2014-01-24 01:59:02

1

您需要將工作表保存在最後,這對我有用。

foreach (WorksheetPart worksheetPart in spreadSheet.WorkbookPart.WorksheetParts) { 
    foreach (Row row in 
      worksheetPart.Worksheet.GetFirstChild<SheetData>().Elements()) { 
     foreach (Cell cell in row.Elements()) { 
      if (cell.CellFormula != null && cell.CellValue != null) 
       cell.CellValue.Remove(); 
     } 
    } 
    worksheetPart.Worksheet.Save(); 
}