diff --git a/ClosedXML/ClosedXML.csproj b/ClosedXML/ClosedXML.csproj index eb62794..c7da769 100644 --- a/ClosedXML/ClosedXML.csproj +++ b/ClosedXML/ClosedXML.csproj @@ -22,7 +22,7 @@ false bin\Debug\ DEBUG;TRACE - NET4 + NET4;TRACE;DEBUG prompt 4 1591 @@ -32,7 +32,7 @@ true bin\Release\ TRACE - NET4 + NET4;TRACE prompt 4 bin\Release\ClosedXML.xml diff --git a/ClosedXML/Excel/XLWorkbook.cs b/ClosedXML/Excel/XLWorkbook.cs index ac31b4e..3cfe9ef 100644 --- a/ClosedXML/Excel/XLWorkbook.cs +++ b/ClosedXML/Excel/XLWorkbook.cs @@ -175,7 +175,7 @@ private readonly Dictionary _stylesByStyle = new Dictionary(); public XLEventTracking EventTracking { get; set; } - + internal Int32 GetStyleId(IXLStyle style) { Int32 cached; @@ -411,16 +411,28 @@ /// public void Save() { +#if DEBUG + Save(true); +#else + Save(false); +#endif + } + + /// + /// Saves the current workbook and optionally performs validation + /// + public void Save(bool validate) + { checkForWorksheetsPresent(); if (_loadSource == XLLoadSource.New) throw new Exception("This is a new file, please use one of the SaveAs methods."); if (_loadSource == XLLoadSource.Stream) { - CreatePackage(_originalStream, false, _spreadsheetDocumentType); + CreatePackage(_originalStream, false, _spreadsheetDocumentType, validate); } else - CreatePackage(_originalFile, _spreadsheetDocumentType); + CreatePackage(_originalFile, _spreadsheetDocumentType, validate); } /// @@ -428,6 +440,18 @@ /// public void SaveAs(String file) { +#if DEBUG + SaveAs(file, true); +#else + SaveAs(file, false); +#endif + } + + /// + /// Saves the current workbook to a file and optionally validates it. + /// + public void SaveAs(String file, Boolean validate) + { checkForWorksheetsPresent(); PathHelper.CreateDirectory(Path.GetDirectoryName(file)); if (_loadSource == XLLoadSource.New) @@ -435,14 +459,14 @@ if (File.Exists(file)) File.Delete(file); - CreatePackage(file, GetSpreadsheetDocumentType(file)); + CreatePackage(file, GetSpreadsheetDocumentType(file), validate); } else if (_loadSource == XLLoadSource.File) { if (String.Compare(_originalFile.Trim(), file.Trim(), true) != 0) File.Copy(_originalFile, file, true); - CreatePackage(file, GetSpreadsheetDocumentType(file)); + CreatePackage(file, GetSpreadsheetDocumentType(file), validate); } else if (_loadSource == XLLoadSource.Stream) { @@ -452,7 +476,7 @@ { CopyStream(_originalStream, fileStream); //fileStream.Position = 0; - CreatePackage(fileStream, false, _spreadsheetDocumentType); + CreatePackage(fileStream, false, _spreadsheetDocumentType, validate); fileStream.Close(); } } @@ -481,6 +505,18 @@ /// public void SaveAs(Stream stream) { +#if DEBUG + SaveAs(stream, true); +#else + SaveAs(stream, false); +#endif + } + + /// + /// Saves the current workbook to a stream and optionally validates it. + /// + public void SaveAs(Stream stream, Boolean validate) + { checkForWorksheetsPresent(); if (_loadSource == XLLoadSource.New) { @@ -491,13 +527,13 @@ if (stream.CanRead && stream.CanSeek && stream.CanWrite) { // all is fine the package can be created in a direct way - CreatePackage(stream, true, _spreadsheetDocumentType); + CreatePackage(stream, true, _spreadsheetDocumentType, validate); } else { // the harder way MemoryStream ms = new MemoryStream(); - CreatePackage(ms, true, _spreadsheetDocumentType); + CreatePackage(ms, true, _spreadsheetDocumentType, validate); // not really nessesary, because I changed CopyStream too. // but for better understanding and if somebody in the future // provide an changed version of CopyStream @@ -512,7 +548,7 @@ CopyStream(fileStream, stream); fileStream.Close(); } - CreatePackage(stream, false, _spreadsheetDocumentType); + CreatePackage(stream, false, _spreadsheetDocumentType, validate); } else if (_loadSource == XLLoadSource.Stream) { @@ -520,7 +556,7 @@ if (_originalStream != stream) CopyStream(_originalStream, stream); - CreatePackage(stream, false, _spreadsheetDocumentType); + CreatePackage(stream, false, _spreadsheetDocumentType, validate); } } @@ -589,24 +625,24 @@ return columns; } - #region Fields +#region Fields private readonly XLLoadSource _loadSource = XLLoadSource.New; private readonly String _originalFile; private readonly Stream _originalStream; - #endregion +#endregion - #region Constructor +#region Constructor - + /// /// Creates a new Excel workbook. /// public XLWorkbook() :this(XLEventTracking.Enabled) { - + } public XLWorkbook(XLEventTracking eventTracking) @@ -665,7 +701,7 @@ /// The stream to open. public XLWorkbook(Stream stream):this(stream, XLEventTracking.Enabled) { - + } public XLWorkbook(Stream stream, XLEventTracking eventTracking) @@ -676,9 +712,9 @@ Load(stream); } - #endregion +#endregion - #region Nested type: UnsupportedSheet +#region Nested type: UnsupportedSheet internal sealed class UnsupportedSheet { @@ -687,7 +723,7 @@ public Int32 Position; } - #endregion +#endregion public IXLCell Cell(String namedCell) { @@ -814,4 +850,4 @@ LockWindows = LockWindows; } } -} \ No newline at end of file +} diff --git a/ClosedXML/Excel/XLWorkbook_Save.cs b/ClosedXML/Excel/XLWorkbook_Save.cs index 19fdd69..9b5c432 100644 --- a/ClosedXML/Excel/XLWorkbook_Save.cs +++ b/ClosedXML/Excel/XLWorkbook_Save.cs @@ -10,6 +10,7 @@ using DocumentFormat.OpenXml.Packaging; using DocumentFormat.OpenXml.Spreadsheet; using DocumentFormat.OpenXml.VariantTypes; +using DocumentFormat.OpenXml.Validation; using DocumentFormat.OpenXml.Vml.Office; using DocumentFormat.OpenXml.Vml.Spreadsheet; using Vml = DocumentFormat.OpenXml.Vml; @@ -43,7 +44,6 @@ using RunProperties = DocumentFormat.OpenXml.Spreadsheet.RunProperties; using VerticalTextAlignment = DocumentFormat.OpenXml.Spreadsheet.VerticalTextAlignment; - namespace ClosedXML.Excel { public partial class XLWorkbook @@ -80,7 +80,19 @@ } } - private void CreatePackage(String filePath, SpreadsheetDocumentType spreadsheetDocumentType) + private bool Validate(SpreadsheetDocument package) + { + var validator = new OpenXmlValidator(); + var errors = validator.Validate(package); + if (errors.Any()) + { + var message = string.Join("\r\n", errors.Select(e => string.Format("{0} in {1}", e.Description, e.Path.XPath)).ToArray()); + throw new ApplicationException(message); + } + return true; + } + + private void CreatePackage(String filePath, SpreadsheetDocumentType spreadsheetDocumentType, bool validate) { PathHelper.CreateDirectory(Path.GetDirectoryName(filePath)); var package = File.Exists(filePath) @@ -90,11 +102,11 @@ using (package) { CreateParts(package); - //package.Close(); + if (validate) Validate(package); } } - private void CreatePackage(Stream stream, bool newStream, SpreadsheetDocumentType spreadsheetDocumentType) + private void CreatePackage(Stream stream, bool newStream, SpreadsheetDocumentType spreadsheetDocumentType, bool validate) { var package = newStream ? SpreadsheetDocument.Create(stream, spreadsheetDocumentType) @@ -103,7 +115,7 @@ using (package) { CreateParts(package); - //package.Close(); + if (validate) Validate(package); } } diff --git a/ClosedXML_Tests/Excel/Columns/ColumnTests.cs b/ClosedXML_Tests/Excel/Columns/ColumnTests.cs index 0a98c4f..aa28593 100644 --- a/ClosedXML_Tests/Excel/Columns/ColumnTests.cs +++ b/ClosedXML_Tests/Excel/Columns/ColumnTests.cs @@ -108,7 +108,7 @@ IXLColumn columnIns = ws.Column(2).InsertColumnsBefore(1).First(); string outputPath = Path.Combine(TestHelper.TestsOutputDirectory, @"ForTesting\Sandbox.xlsx"); - wb.SaveAs(outputPath); + wb.SaveAs(outputPath, true); Assert.AreEqual(XLColor.Red, ws.Column(1).Cell(1).Style.Fill.BackgroundColor); Assert.AreEqual(XLColor.Red, ws.Column(1).Cell(2).Style.Fill.BackgroundColor); @@ -237,4 +237,4 @@ Assert.AreEqual(2, lastCoUsed); } } -} \ No newline at end of file +} diff --git a/ClosedXML_Tests/Excel/PageSetup/HeaderFooterTests.cs b/ClosedXML_Tests/Excel/PageSetup/HeaderFooterTests.cs index d1748a9..18fe221 100644 --- a/ClosedXML_Tests/Excel/PageSetup/HeaderFooterTests.cs +++ b/ClosedXML_Tests/Excel/PageSetup/HeaderFooterTests.cs @@ -17,7 +17,7 @@ ws.PageSetup.Header.Center.AddText("Initial page header", XLHFOccurrence.EvenPages); var ms = new MemoryStream(); - wb.SaveAs(ms); + wb.SaveAs(ms, true); wb = new XLWorkbook(ms); ws = wb.Worksheets.First(); @@ -25,7 +25,7 @@ ws.PageSetup.Header.Center.Clear(); ws.PageSetup.Header.Center.AddText("Changed header", XLHFOccurrence.EvenPages); - wb.SaveAs(ms); + wb.SaveAs(ms, true); wb = new XLWorkbook(ms); ws = wb.Worksheets.First(); @@ -34,4 +34,4 @@ Assert.AreEqual("Changed header", newHeader); } } -} \ No newline at end of file +} diff --git a/ClosedXML_Tests/Excel/Ranges/XLRangeBaseTests.cs b/ClosedXML_Tests/Excel/Ranges/XLRangeBaseTests.cs index c90f624..22bd7c6 100644 --- a/ClosedXML_Tests/Excel/Ranges/XLRangeBaseTests.cs +++ b/ClosedXML_Tests/Excel/Ranges/XLRangeBaseTests.cs @@ -178,7 +178,7 @@ // ws.NamedRanges.Add("TestRange", "\"Hello\""); // using (MemoryStream memoryStream = new MemoryStream()) // { - // wb.SaveAs(memoryStream); + // wb.SaveAs(memoryStream, true); // var wb2 = new XLWorkbook(memoryStream); // var text = wb2.Worksheet("Sheet1").NamedRanges.First() // memoryStream.Close(); @@ -187,4 +187,4 @@ //} } -} \ No newline at end of file +} diff --git a/ClosedXML_Tests/Excel/Tables/TablesTests.cs b/ClosedXML_Tests/Excel/Tables/TablesTests.cs index d7a8bac..ea27d0d 100644 --- a/ClosedXML_Tests/Excel/Tables/TablesTests.cs +++ b/ClosedXML_Tests/Excel/Tables/TablesTests.cs @@ -40,14 +40,14 @@ public void CanSaveTableCreatedFromEmptyDataTable() { var dt = new DataTable("sheet1"); - dt.Columns.Add("col1", typeof(string)); - dt.Columns.Add("col2", typeof(double)); + dt.Columns.Add("col1", typeof (string)); + dt.Columns.Add("col2", typeof (double)); var wb = new XLWorkbook(); wb.AddWorksheet(dt); using (var ms = new MemoryStream()) - wb.SaveAs(ms); + wb.SaveAs(ms, true); } [Test] @@ -59,7 +59,7 @@ ws.Range("A1").CreateTable(); using (var ms = new MemoryStream()) - wb.SaveAs(ms); + wb.SaveAs(ms, true); } [Test] @@ -101,7 +101,7 @@ ws.RangeUsed().CreateTable(); using (var ms = new MemoryStream()) { - wb.SaveAs(ms); + wb.SaveAs(ms, true); var wb2 = new XLWorkbook(ms); IXLWorksheet ws2 = wb2.Worksheet(1); IXLTable table2 = ws2.Table(0); @@ -131,7 +131,7 @@ using (var ms = new MemoryStream()) { - wb.SaveAs(ms); + wb.SaveAs(ms, true); var wb2 = new XLWorkbook(ms); IXLWorksheet ws2 = wb2.Worksheet(1); IXLTable table2 = ws2.Table(0); @@ -144,8 +144,8 @@ public void TableCreatedFromEmptyDataTable() { var dt = new DataTable("sheet1"); - dt.Columns.Add("col1", typeof(string)); - dt.Columns.Add("col2", typeof(double)); + dt.Columns.Add("col1", typeof (string)); + dt.Columns.Add("col2", typeof (double)); var wb = new XLWorkbook(); IXLWorksheet ws = wb.AddWorksheet("Sheet1"); diff --git a/ClosedXML_Tests/TestHelper.cs b/ClosedXML_Tests/TestHelper.cs index be509a2..07576df 100644 --- a/ClosedXML_Tests/TestHelper.cs +++ b/ClosedXML_Tests/TestHelper.cs @@ -19,22 +19,22 @@ //Note: Run example tests parameters public static string TestsOutputDirectory { - get { - return Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location); + get { + return Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location); } } public const string ActualTestResultPostFix = ""; public static readonly string TestsExampleOutputDirectory = Path.Combine(TestsOutputDirectory, "Examples"); - + private const bool CompareWithResources = true; private static readonly ResourceFileExtractor _extractor = new ResourceFileExtractor(null, ".Resource.Examples."); public static void SaveWorkbook(XLWorkbook workbook, string fileName) { - workbook.SaveAs(Path.Combine(TestsOutputDirectory, fileName)); + workbook.SaveAs(Path.Combine(TestsOutputDirectory, fileName), true); } public static void RunTestExample(string filePartName) @@ -57,7 +57,7 @@ var filePath2 = Path.Combine(directory, fileName); //Run test example.Create(filePath1); - new XLWorkbook(filePath1).SaveAs(filePath2); + new XLWorkbook(filePath1).SaveAs(filePath2, true); bool success = true; #pragma warning disable 162 try @@ -102,4 +102,4 @@ } } } -} \ No newline at end of file +}