13

我通过 Microsoft Office OpenXML SDK 2.0 更新了 Excel 电子表格的一些单元格。更改值会使包含依赖于已更改单元格的公式的所有单元格无效。但是,由于缓存值,即使用户单击“立即计算”,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();
}

除了这个片段不能为我编译之外,它还有两个限制:

  • 它只会使单个工作表无效,尽管其他工作表可能包含相关公式
  • 它不考虑任何依赖关系。

我正在寻找一种有效的方法(特别是,仅使依赖于某个单元格值的单元格无效),并考虑所有工作表。

更新:

与此同时,我设法使代码编译和运行,并删除了工作簿所有工作表上的缓存值。(请参阅答案。)我仍然对更好/替代解决方案感兴趣,特别是如何仅删除实际依赖于更新单元格的单元格的缓存值。

4

6 回答 6

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

为我工作!

于 2010-11-24T03:44:52.507 回答
2

由于它部分解决了我的问题并且到目前为止似乎没有更好的解决方案,因此将该代码块从问题移到答案......这就是新代码的样子:

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();
        }
    }
}
于 2010-04-21T15:24:15.720 回答
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())
            ;
    }

这会刷新缓存的值

打招呼

于 2010-07-09T10:37:29.420 回答
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();
}
于 2015-03-31T12:42:38.443 回答
0

或者,您可以更改公式以使用 INDIRECT 运算符。如果您使用 SAX + 模板文件方法,则特别有用。由于此解决方案不需要更改您的代码,只需模板 excel 文件。请在此处参考我的解决方案 -设置 xlsx 以在打开时重新计算公式

于 2020-08-10T10:54:23.343 回答
0

想指出我遇到的另一个问题,这似乎是重新计算的问题。我盲目地遵循一些代码来填充单元格,它显示了一个共享字符串。过了很久,我发现我需要CellValues.NumberDataType. 一旦我这样做了,细胞就会在打开时重新计算。

于 2021-10-28T21:13:30.797 回答