OpenXML SDK: preparar la fórmula volver a calcular Excel
-
28-09-2019 - |
Pregunta
actualizar algunas celdas de una hoja de cálculo de Excel a través del Microsoft Office OpenXML SDK 2.0. Cambio de los valores hace que todas las células que contienen fórmula que dependen de las células modificados no válidos. Sin embargo, debido a los valores almacenados en caché de Excel no vuelve a calcular el formular, incluso si el usuario hace clic en "Calcular ahora".
¿Cuál es la mejor manera de invalidar todas las células dependientes de todo el libro a través del SDK? Hasta el momento, he encontrado el siguiente fragmento de código en el 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();
}
Además del hecho de que este fragmento no se compila para mí, tiene dos limitaciones:
- Sólo invalida una sola hoja, aunque otras hojas pueden contener fórmula dependiente
- No tiene en cuenta las dependencias.
Estoy buscando una manera que sea eficiente (en particular, sólo se invalida las células que dependen del valor de una determinada célula), y toma todas las hojas en cuenta.
Actualización:
Mientras tanto he logrado hacer que el código de compilación y de ejecución, y de quitar los valores almacenados en caché en todas las hojas del libro de trabajo. (Ver las respuestas.) Aún estoy interesado en mejores soluciones / alternativos, en particular, cómo sólo para borrar los valores almacenados en caché de las células que en realidad dependen de la celda actualizada.
Solución
spreadSheet.WorkbookPart.Workbook.CalculationProperties.ForceFullCalculation = true;
spreadSheet.WorkbookPart.Workbook.CalculationProperties.FullCalculationOnLoad = true;
funciona para mí!
Otros consejos
Yo uso este
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())
;
}
Esto limpia los valores almacenados en caché
saluda
Desde que resuelve parcialmente mi problema y no parece haber mejor solución hasta el momento, avanzó que el bloque de código a partir de la pregunta a una respuesta ... Es así como las nuevas miradas de código como:
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();
}
}
}
Es necesario guardar la hoja al final, Esto funcionó para mí.
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();
}
Algoritmos:
- ángulo en radianes: (Math.PI / 180) * ángulo
- Distancia: Math.pow (velocidad, 2) / GRAVEDAD * Math.sin (2 * angleInRadians)
- La gravedad es igual a 9,8
Ejemplo:. A 45 grados y 56 m / s, la pelota debe viajar 320 metros