2010-04-19 198 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(); 
}