打开xml sdk excel公式,在细胞去除后重新计算

时间:2014-01-24 02:53:05

标签: c# excel asp.net-mvc-4 openxml openxml-sdk

我在另一个单元格C2中输入值后需要重新计算公式单元格C4。但C4不断缓存并继续返回旧的缓存值。

我在SO上多次提出这个问题,但我没有得到任何帮助。我正在尽我所能。这是我在msdn网站上发现的。

  

使用上一代码列表中的方法,生成   该报告现在是获取投资组合数据的过程   反复调用UpdateValue来创建报告。的确,如果你   添加必要的代码来做到这一点,事情似乎工作正常,除了   一个问题 - 任何包含引用单元格的公式的单元格   其值通过Open XML操作更改未显示   正确的结果。这是因为Excel缓存公式的结果   在细胞内。因为Excel认为它具有正确的缓存值,   它不会重新计算细胞。即使你有自动计算   打开或如果您按F9强制手动重新计算,Excel   不会重新计算细胞。对此的解决方案是删除   缓存来自这些单元格的值,以便Excel重新计算值   文件在Excel中打开后立即生效。添加RemoveCellValue方法   在以下示例中显示了要提供的PortfolioReport类   这个功能。

基于以上MSDN解释。在更新单元格之前,我已尝试删除代码。我更新单元格后。在我读取公式单元格之前,在读取公式单元格之后,我在读取公式单元格后仍然遇到以下错误。

  

System.NullReferenceException:未将对象引用设置为实例   一个对象。

这是我的代码......

    string filename = Server.MapPath("/") + "MyExcelData.xlsx";



    using (SpreadsheetDocument document = SpreadsheetDocument.Open(filename, true))
    {


        Sheet sheet = document.WorkbookPart.Workbook.Descendants<Sheet>().SingleOrDefault(s => s.Name == "myRange1");
        if (sheet == null)
        {
            throw new ArgumentException(
                String.Format("No sheet named {0} found in spreadsheet {1}", "myRange1", filename), "sheetName");
        }
        WorksheetPart worksheetPart = (WorksheetPart)document.WorkbookPart.GetPartById(sheet.Id);
        Worksheet ws = worksheetPart.Worksheet; // ((WorksheetPart)(worksheetPart.GetPartById(sheet.Id))).Worksheet;
        Cell cell = InsertCellInWorksheet(ws, "C4");

        // If there is a cell value, remove it to force a recalculation
        // on this cell.
        if (cell.CellValue != null)
        {
            cell.CellValue.Remove();
        }

        // Save the worksheet.
        ws.Save();
        document.Close();
    }



    // getting 2 numbers in excel sheet, saving, and closing it.

    using (SpreadsheetDocument document = SpreadsheetDocument.Open(filename, true))
    {


        Sheet sheet = document.WorkbookPart.Workbook.Descendants<Sheet>().SingleOrDefault(s => s.Name == "myRange1");
        if (sheet == null)
        {
            throw new ArgumentException(
                String.Format("No sheet named {0} found in spreadsheet {1}", "myRange1", filename), "sheetName");
        }
        WorksheetPart worksheetPart = (WorksheetPart)document.WorkbookPart.GetPartById(sheet.Id);


        int rowIndex = int.Parse("C3".Substring(1));

        Row row = worksheetPart.Worksheet.GetFirstChild<SheetData>().
                Elements<Row>().FirstOrDefault(r => r.RowIndex == rowIndex);

        Cell cell3 = row.Elements<Cell>().FirstOrDefault(c => "C3".Equals(c.CellReference.Value));
        if (cell3 != null) 
        {
            cell3.CellValue = new CellValue("16");
            cell3.DataType = new DocumentFormat.OpenXml.EnumValue<CellValues>(CellValues.Number); 
        }

        worksheetPart.Worksheet.Save();
        document.Close();

    }

    // getting the result out of excel.
    using (SpreadsheetDocument document = SpreadsheetDocument.Open(filename, false))
    {
        document.WorkbookPart.Workbook.CalculationProperties.ForceFullCalculation = true;
        document.WorkbookPart.Workbook.CalculationProperties.FullCalculationOnLoad = true;

        Sheet sheet = document.WorkbookPart.Workbook.Descendants<Sheet>().SingleOrDefault(s => s.Name == "myRange1");
        if (sheet == null)
        {
            throw new ArgumentException(
                String.Format("No sheet named {0} found in spreadsheet {1}", "myRange1", filename), "sheetName");
        }



        WorksheetPart worksheetPart = (WorksheetPart)document.WorkbookPart.GetPartById(sheet.Id);

        int rowIndex = int.Parse("C4".Substring(1));

        Row row = worksheetPart.Worksheet.GetFirstChild<SheetData>().
                Elements<Row>().FirstOrDefault(r => r.RowIndex == rowIndex);

        Cell cell = row.Elements<Cell>().FirstOrDefault(c => "C4".Equals(c.CellReference.Value));

        d.Average = Convert.ToDouble(cell.CellValue.InnerText);

    }

2 个答案:

答案 0 :(得分:0)

问题似乎是您在不打开Excel的情况下直接修改Excel数据文件。由于Excel只能在打开时跟踪公式依赖项,因此在不知道您已经这样做的情况下更改数据时,它不知道它需要重新计算。

3种可能的解决方案是:
1)从文件中删除计算链部分(未测试)
2)对文件进行更改后,使用interop / automation打开Excel并请求完整计算(如果您也在改变/创建公式,则使用依赖关系重建进行完整计算)
3)将fullcalculationonload属性设置为true:这会导致Excel在打开文件时执行完整计算

答案 1 :(得分:-1)

我想你已经删除了C4的cellValue,首先你必须创建cellValue然后你可以对它执行任何操作。