OpenXML SDK: сделать Excel пересчитать формулу - PullRequest
12 голосов
/ 19 апреля 2010

Я обновляю некоторые ячейки электронной таблицы Excel через Microsoft Office OpenXML SDK 2.0. Изменение значений делает все ячейки, содержащие формулу, которые зависят от измененных ячеек, недействительными. Однако из-за кэшированных значений 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();
}

Помимо того, что этот фрагмент не компилируется для меня, у него есть два ограничения:

  • Это делает недействительным только один лист, хотя другие листы могут содержать зависимую формулу
  • Не учитывает никаких зависимостей.

Я ищу способ, который эффективен (в частности, делает недействительными только ячейки, которые зависят от значения определенной ячейки) и учитывает все листы.

Обновление:

Тем временем мне удалось заставить код компилироваться и запускаться, а также удалять кэшированные значения на всех листах рабочей книги. (См. Ответы.) Тем не менее меня интересуют лучшие / альтернативные решения, в частности, как удалять только кэшированные значения ячеек, которые на самом деле зависят от обновленной ячейки.

Ответы [ 5 ]

44 голосов
/ 24 ноября 2010
spreadSheet.WorkbookPart.Workbook.CalculationProperties.ForceFullCalculation = true;
spreadSheet.WorkbookPart.Workbook.CalculationProperties.FullCalculationOnLoad = true;

У меня работает!

2 голосов
/ 09 июля 2010

Я использую это

    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())
            ;
    }

Это сбрасывает кэшированные значения

приветствует

1 голос
/ 31 марта 2015

Вам нужно сохранить лист в конце, это сработало для меня.

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();
}
1 голос
/ 21 апреля 2010

Поскольку это частично решает мою проблему, и, похоже, лучшего решения пока нет, я переместил этот кодовый блок из вопроса в ответ ... Вот так выглядит новый код:

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();
        }
    }
}
0 голосов
/ 13 мая 2019

Алгоритмы:

  • Угол в радианах: (Math.PI / 180) * Угол
  • Расстояние: Math.Pow (скорость, 2) / GRAVITY * Math.Sin (2 * angleInRadians)
  • Гравитация равна 9,8

Пример: при 45 градусах и 56 м / с мяч должен пройти 320 метров.

...