OpenKML SDK: сделайте Excel пересчитанной формулой

Я обновляю некоторые ячейки электронной таблицы 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();
}

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

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

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

Update:

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

Ответ 1

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

Работает для меня!

Ответ 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())
            ;
    }

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

здоровается

Ответ 3

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

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

Ответ 4

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

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

Ответ 5

Алгоритмы:

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

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