diff --git a/ClosedXML/Excel/XLWorkbook.cs b/ClosedXML/Excel/XLWorkbook.cs index 645d536..e82a5a0 100644 --- a/ClosedXML/Excel/XLWorkbook.cs +++ b/ClosedXML/Excel/XLWorkbook.cs @@ -429,16 +429,16 @@ public void Save() { #if DEBUG - Save(true); + Save(true, false); #else - Save(false); + Save(false, false); #endif } /// /// Saves the current workbook and optionally performs validation /// - public void Save(bool validate) + public void Save(Boolean validate, Boolean evaluateFormulae = false) { checkForWorksheetsPresent(); if (_loadSource == XLLoadSource.New) @@ -446,10 +446,10 @@ if (_loadSource == XLLoadSource.Stream) { - CreatePackage(_originalStream, false, _spreadsheetDocumentType, validate); + CreatePackage(_originalStream, false, _spreadsheetDocumentType, validate, evaluateFormulae); } else - CreatePackage(_originalFile, _spreadsheetDocumentType, validate); + CreatePackage(_originalFile, _spreadsheetDocumentType, validate, evaluateFormulae); } /// @@ -458,16 +458,16 @@ public void SaveAs(String file) { #if DEBUG - SaveAs(file, true); + SaveAs(file, true, false); #else - SaveAs(file, false); + SaveAs(file, false, false); #endif } /// /// Saves the current workbook to a file and optionally validates it. /// - public void SaveAs(String file, Boolean validate) + public void SaveAs(String file, Boolean validate, Boolean evaluateFormulae = false) { checkForWorksheetsPresent(); PathHelper.CreateDirectory(Path.GetDirectoryName(file)); @@ -476,14 +476,14 @@ if (File.Exists(file)) File.Delete(file); - CreatePackage(file, GetSpreadsheetDocumentType(file), validate); + CreatePackage(file, GetSpreadsheetDocumentType(file), validate, evaluateFormulae); } else if (_loadSource == XLLoadSource.File) { if (String.Compare(_originalFile.Trim(), file.Trim(), true) != 0) File.Copy(_originalFile, file, true); - CreatePackage(file, GetSpreadsheetDocumentType(file), validate); + CreatePackage(file, GetSpreadsheetDocumentType(file), validate, evaluateFormulae); } else if (_loadSource == XLLoadSource.Stream) { @@ -493,7 +493,7 @@ { CopyStream(_originalStream, fileStream); //fileStream.Position = 0; - CreatePackage(fileStream, false, _spreadsheetDocumentType, validate); + CreatePackage(fileStream, false, _spreadsheetDocumentType, validate, evaluateFormulae); fileStream.Close(); } } @@ -531,16 +531,16 @@ public void SaveAs(Stream stream) { #if DEBUG - SaveAs(stream, true); + SaveAs(stream, true, false); #else - SaveAs(stream, false); + SaveAs(stream, false, false); #endif } /// /// Saves the current workbook to a stream and optionally validates it. /// - public void SaveAs(Stream stream, Boolean validate) + public void SaveAs(Stream stream, Boolean validate, Boolean evaluateFormulae = false) { checkForWorksheetsPresent(); if (_loadSource == XLLoadSource.New) @@ -552,13 +552,13 @@ if (stream.CanRead && stream.CanSeek && stream.CanWrite) { // all is fine the package can be created in a direct way - CreatePackage(stream, true, _spreadsheetDocumentType, validate); + CreatePackage(stream, true, _spreadsheetDocumentType, validate, evaluateFormulae); } else { // the harder way MemoryStream ms = new MemoryStream(); - CreatePackage(ms, true, _spreadsheetDocumentType, validate); + CreatePackage(ms, true, _spreadsheetDocumentType, validate, evaluateFormulae); // not really nessesary, because I changed CopyStream too. // but for better understanding and if somebody in the future // provide an changed version of CopyStream @@ -573,7 +573,7 @@ CopyStream(fileStream, stream); fileStream.Close(); } - CreatePackage(stream, false, _spreadsheetDocumentType, validate); + CreatePackage(stream, false, _spreadsheetDocumentType, validate, evaluateFormulae); } else if (_loadSource == XLLoadSource.Stream) { @@ -581,7 +581,7 @@ if (_originalStream != stream) CopyStream(_originalStream, stream); - CreatePackage(stream, false, _spreadsheetDocumentType, validate); + CreatePackage(stream, false, _spreadsheetDocumentType, validate, evaluateFormulae); } } diff --git a/ClosedXML/Excel/XLWorkbook_Save.cs b/ClosedXML/Excel/XLWorkbook_Save.cs index 08994f1..9d68063 100644 --- a/ClosedXML/Excel/XLWorkbook_Save.cs +++ b/ClosedXML/Excel/XLWorkbook_Save.cs @@ -60,7 +60,7 @@ private static readonly EnumValue CvDate = new EnumValue(CellValues.Date); private static readonly EnumValue CvBoolean = new EnumValue(CellValues.Boolean); - private static EnumValue GetCellValue(XLCell xlCell) + private static EnumValue GetCellValueType(XLCell xlCell) { switch (xlCell.DataType) { @@ -105,7 +105,7 @@ return true; } - private void CreatePackage(String filePath, SpreadsheetDocumentType spreadsheetDocumentType, bool validate) + private void CreatePackage(String filePath, SpreadsheetDocumentType spreadsheetDocumentType, bool validate, bool evaluateFormulae) { PathHelper.CreateDirectory(Path.GetDirectoryName(filePath)); var package = File.Exists(filePath) @@ -114,12 +114,12 @@ using (package) { - CreateParts(package); + CreateParts(package, evaluateFormulae); if (validate) Validate(package); } } - private void CreatePackage(Stream stream, bool newStream, SpreadsheetDocumentType spreadsheetDocumentType, bool validate) + private void CreatePackage(Stream stream, bool newStream, SpreadsheetDocumentType spreadsheetDocumentType, bool validate, bool evaluateFormulae) { var package = newStream ? SpreadsheetDocument.Create(stream, spreadsheetDocumentType) @@ -127,7 +127,7 @@ using (package) { - CreateParts(package); + CreateParts(package, evaluateFormulae); if (validate) Validate(package); } } @@ -213,7 +213,7 @@ } // Adds child parts and generates content of the specified part. - private void CreateParts(SpreadsheetDocument document) + private void CreateParts(SpreadsheetDocument document, bool evaluateFormulae) { var context = new SaveContext(); @@ -311,7 +311,7 @@ GenerateVmlDrawingPartContent(vmlDrawingPart, worksheet, context); } - GenerateWorksheetPartContent(worksheetPart, worksheet, context); + GenerateWorksheetPartContent(worksheetPart, worksheet, evaluateFormulae, context); if (worksheet.PivotTables.Any()) { @@ -3497,8 +3497,8 @@ #region GenerateWorksheetPartContent - private static void GenerateWorksheetPartContent(WorksheetPart worksheetPart, XLWorksheet xlWorksheet, - SaveContext context) + private static void GenerateWorksheetPartContent( + WorksheetPart worksheetPart, XLWorksheet xlWorksheet, bool evaluateFormulae, SaveContext context) { #region Worksheet @@ -4066,10 +4066,10 @@ else { cell.CellFormula = null; - cell.DataType = xlCell.DataType == XLCellValues.DateTime ? null : GetCellValue(xlCell); + cell.DataType = xlCell.DataType == XLCellValues.DateTime ? null : GetCellValueType(xlCell); } - if (!xlCell.HasFormula) + if (!xlCell.HasFormula || evaluateFormulae) SetCellValue(xlCell, cell); } @@ -4584,6 +4584,23 @@ private static void SetCellValue(XLCell xlCell, Cell openXmlCell) { + if (xlCell.HasFormula) + { + var cellValue = new CellValue(); + try + { + cellValue.Text = xlCell.Value.ToString(); + openXmlCell.DataType = new EnumValue(CellValues.String); + } + catch + { + cellValue = null; + } + + openXmlCell.CellValue = cellValue; + return; + } + var dataType = xlCell.DataType; if (dataType == XLCellValues.Text) { diff --git a/ClosedXML_Examples/ClosedXML_Examples.csproj b/ClosedXML_Examples/ClosedXML_Examples.csproj index 155d094..c1074f7 100644 --- a/ClosedXML_Examples/ClosedXML_Examples.csproj +++ b/ClosedXML_Examples/ClosedXML_Examples.csproj @@ -109,6 +109,7 @@ + diff --git a/ClosedXML_Examples/Misc/FormulasWithEvaluation.cs b/ClosedXML_Examples/Misc/FormulasWithEvaluation.cs new file mode 100644 index 0000000..dca890e --- /dev/null +++ b/ClosedXML_Examples/Misc/FormulasWithEvaluation.cs @@ -0,0 +1,16 @@ +using ClosedXML.Excel; + +namespace ClosedXML_Examples.Misc +{ + public class FormulasWithEvaluation : Formulas + { + public override void Create(string filePath) + { + base.Create(filePath); + using (var wb = new XLWorkbook(filePath)) + { + wb.Save(true, true); + } + } + } +} diff --git a/ClosedXML_Tests/ClosedXML_Tests.csproj b/ClosedXML_Tests/ClosedXML_Tests.csproj index 9eac192..d4c8a9a 100644 --- a/ClosedXML_Tests/ClosedXML_Tests.csproj +++ b/ClosedXML_Tests/ClosedXML_Tests.csproj @@ -153,6 +153,7 @@ + diff --git a/ClosedXML_Tests/Examples/MiscTests.cs b/ClosedXML_Tests/Examples/MiscTests.cs index 47865bc..928e9ab 100644 --- a/ClosedXML_Tests/Examples/MiscTests.cs +++ b/ClosedXML_Tests/Examples/MiscTests.cs @@ -98,6 +98,12 @@ } [Test] + public void FormulasWithEvaluation() + { + TestHelper.RunTestExample(@"Misc\FormulasWithEvaluation.xlsx", true); + } + + [Test] public void FreezePanes() { TestHelper.RunTestExample(@"Misc\FreezePanes.xlsx"); diff --git a/ClosedXML_Tests/Resource/Examples/Misc/FormulasWithEvaluation.xlsx b/ClosedXML_Tests/Resource/Examples/Misc/FormulasWithEvaluation.xlsx new file mode 100644 index 0000000..c4a24f7 --- /dev/null +++ b/ClosedXML_Tests/Resource/Examples/Misc/FormulasWithEvaluation.xlsx Binary files differ diff --git a/ClosedXML_Tests/TestHelper.cs b/ClosedXML_Tests/TestHelper.cs index 477facf..98929bc 100644 --- a/ClosedXML_Tests/TestHelper.cs +++ b/ClosedXML_Tests/TestHelper.cs @@ -53,7 +53,7 @@ } } - public static void RunTestExample(string filePartName) + public static void RunTestExample(string filePartName, bool evaluateFormulae = false) where T : IXLExample, new() { // Make sure tests run on a deterministic culture @@ -74,7 +74,7 @@ var filePath2 = Path.Combine(directory, fileName); //Run test example.Create(filePath1); - new XLWorkbook(filePath1).SaveAs(filePath2, true); + new XLWorkbook(filePath1).SaveAs(filePath2, true, evaluateFormulae); bool success = true; #pragma warning disable 162 try