programing

OpenXML SDK: Excel 재계산 공식 만들기

sourcejob 2023. 8. 12. 10:14
반응형

OpenXML SDK: Excel 재계산 공식 만들기

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

이 스니펫이 컴파일되지 않는다는 사실 외에도 두 가지 제한 사항이 있습니다.

  • 다른 시트에 종속 공식이 포함될 수 있지만 단일 시트만 무효화됩니다.
  • 종속성은 고려하지 않습니다.

저는 효율적이고(특히 특정 셀의 값에 의존하는 셀만 무효화) 모든 시트를 고려한 방법을 찾고 있습니다.

업데이트:

그동안 코드를 컴파일하고 실행할 수 있었고 워크북의 모든 시트에서 캐시된 값을 제거할 수 있었습니다. (답변 참조)여전히 저는 더 나은/대체 솔루션, 특히 업데이트된 셀에 실제로 의존하는 셀의 캐시된 값만 삭제하는 방법에 관심이 있습니다.

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

나한테 효과가 있어요!

내 문제를 부분적으로 해결해주고 아직까지는 더 나은 해결책이 없는 것 같으니, 그 코드 블록을 질문에서 답변으로 옮겼습니다.새 코드는 다음과 같습니다.

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

사용합니다.

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

캐시된 값을 플러시합니다.

인사말

마지막에 워크시트를 저장해야 합니다. 이것은 저에게 효과가 있었습니다.

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

또는 공식을 변경하여 간접 연산자를 사용할 수 있습니다.SAX + 템플릿 파일 접근 방식을 사용하는 경우 특히 유용합니다.이 솔루션은 코드를 변경할 필요가 없으므로 템플릿 엑셀 파일만 사용합니다.여기에서 내 솔루션을 참조하십시오 - 열려 있는 공식을 다시 계산하도록 xlsx 설정

재계산에 문제가 있는 것으로 보이는 또 다른 문제에 주목하고 싶습니다.저는 맹목적으로 세포를 채우기 위해 코드를 따랐고 그것은 공유된 문자열을 보여주었습니다.오랜 시간이 지난 후, 저는 제가 사용할 필요가 있다는 것을 발견했습니다.CellValues.Number에 대한 가치DataType일단 제가 그렇게 하면, 세포들은 열었을 때 다시 계산됩니다.

언급URL : https://stackoverflow.com/questions/2668643/openxml-sdk-make-excel-recalculate-formula

반응형