From 43328a3f22c05c143d5ef63f944054f03daa593b Mon Sep 17 00:00:00 2001 From: Antony Liu Date: Fri, 15 Mar 2024 15:03:41 +0800 Subject: [PATCH 1/4] poi: bug 60031: DataFormatter parses months incorrectly when put at the end of date segment. Thanks to Andrzej Witecki --- main/SS/UserModel/DataFormatter.cs | 4 ++++ testcases/main/SS/UserModel/TestDataFormatter.cs | 13 +++++++++++++ 2 files changed, 17 insertions(+) diff --git a/main/SS/UserModel/DataFormatter.cs b/main/SS/UserModel/DataFormatter.cs index 8a2b9102d..515ac91ff 100644 --- a/main/SS/UserModel/DataFormatter.cs +++ b/main/SS/UserModel/DataFormatter.cs @@ -649,6 +649,10 @@ Excel displays the month instead of minutes." } else { + if (Char.IsWhiteSpace(c)) + { + ms.Clear(); + } sb.Append(c); } } diff --git a/testcases/main/SS/UserModel/TestDataFormatter.cs b/testcases/main/SS/UserModel/TestDataFormatter.cs index 4c9a832b1..ec45cf8a4 100644 --- a/testcases/main/SS/UserModel/TestDataFormatter.cs +++ b/testcases/main/SS/UserModel/TestDataFormatter.cs @@ -821,6 +821,19 @@ public void TestFormulaEvaluation() Assert.AreEqual("5.6789", formatter.FormatCellValue(cell, evaluator)); wb.Close(); } + + /** + * bug 60031: DataFormatter parses months incorrectly when put at the end of date segment + */ + [Test] + public void TestBug60031() + { + // 23-08-2016 08:51:01 which is 42605.368761574071 as double will be parsed + // with format "yyyy-dd-MM HH:mm:ss" into "2016-23-51 08:51:01". + DataFormatter dfUS = new DataFormatter(CultureInfo.GetCultureInfo("en-US")); + Assert.AreEqual("2016-23-08 08:51:01", dfUS.FormatRawCellContents(42605.368761574071, -1, "yyyy-dd-MM HH:mm:ss")); + Assert.AreEqual("2017-12-01 January 09:54:33", dfUS.FormatRawCellContents(42747.412892397523, -1, "yyyy-dd-MM MMMM HH:mm:ss")); + } } } \ No newline at end of file From 8b4efcd367601fb16515875a251ee888b5229c73 Mon Sep 17 00:00:00 2001 From: Antony Liu Date: Fri, 15 Mar 2024 15:08:26 +0800 Subject: [PATCH 2/4] poi: fix copy-paste typo in unit test found by Andrzej Witecki --- .../main/HSSF/UserModel/TestHSSFSheet.cs | 45 +++++++------------ testcases/main/POITestCase.cs | 12 +++++ 2 files changed, 29 insertions(+), 28 deletions(-) diff --git a/testcases/main/HSSF/UserModel/TestHSSFSheet.cs b/testcases/main/HSSF/UserModel/TestHSSFSheet.cs index 0a0555abd..a53538337 100644 --- a/testcases/main/HSSF/UserModel/TestHSSFSheet.cs +++ b/testcases/main/HSSF/UserModel/TestHSSFSheet.cs @@ -17,29 +17,20 @@ limitations under the License. namespace TestCases.HSSF.UserModel { - using System.IO; - using System; - using System.Configuration; - using System.Runtime.InteropServices; - using NPOI.HSSF.UserModel; + using NPOI.DDF; using NPOI.HSSF.Model; using NPOI.HSSF.Record; - using NPOI.SS.Util; - using NPOI.DDF; - - using TestCases.HSSF; - using NPOI.HSSF.Record.Aggregates; - using TestCases.SS; - using TestCases.SS.UserModel; - using NPOI.SS.UserModel; - using NPOI.Util; using NPOI.HSSF.Record.AutoFilter; - using System.Collections.Generic; - using System.Collections; - using NPOI.SS.Formula; + using NPOI.HSSF.UserModel; using NPOI.SS.Formula.PTG; + using NPOI.SS.UserModel; + using NPOI.SS.Util; + using NPOI.Util; using NUnit.Framework; - using NPOI.SS; + using System; + using System.Collections; + using TestCases.HSSF; + using TestCases.SS.UserModel; /** * Tests NPOI.SS.UserModel.Sheet. This Test case is very incomplete at the moment. @@ -764,12 +755,10 @@ public void TestAutoSizeDate() s.AutoSizeColumn((short)1); // Size ranges due to different fonts on different machines - Assert.IsTrue(s.GetColumnWidth(0) > 350, "Single number column too small: " + s.GetColumnWidth(0)); - //Assert.IsTrue(s.GetColumnWidth(0) < 550, "Single number column too big: " + s.GetColumnWidth(0)); - //Todo: find a algorithm of function SheetUtil.GetColumnWidth to make the test statement above succeed. - Assert.IsTrue(s.GetColumnWidth(0) < 650, "Single number column too big: " + s.GetColumnWidth(0)); - Assert.IsTrue(s.GetColumnWidth(1) > 1500, "6 digit number column too small: " + s.GetColumnWidth(1)); - Assert.IsTrue(s.GetColumnWidth(1) < 2000, "6 digit number column too big: " + s.GetColumnWidth(1)); + //Assert.That(s.GetColumnWidth(0), Is.InRange(350, 550), "Single number column width"); + //Assert.That(s.GetColumnWidth(1), Is.InRange(1500, 2000), "6 digit number column width"); + POITestCase.AssertBetween("Single number column width", (int) s.GetColumnWidth(0), 350, 550); + POITestCase.AssertBetween("6 digit number column width", (int) s.GetColumnWidth(1), 1500, 2000); // Set a date format ICellStyle cs = wb.CreateCellStyle(); @@ -785,10 +774,10 @@ public void TestAutoSizeDate() s.AutoSizeColumn((short)0); s.AutoSizeColumn((short)1); - Assert.IsTrue(s.GetColumnWidth(0) > 4750, "Date column too small: " + s.GetColumnWidth(0)); - Assert.IsTrue(s.GetColumnWidth(1) > 4750, "Date column too small: " + s.GetColumnWidth(1)); - Assert.IsTrue(s.GetColumnWidth(0) < 6500, "Date column too big: " + s.GetColumnWidth(0)); - Assert.IsTrue(s.GetColumnWidth(0) < 6500, "Date column too big: " + s.GetColumnWidth(0)); + //Assert.That(s.GetColumnWidth(0), Is.InRange(4750, 7000), "Date column width"); + //Assert.That(s.GetColumnWidth(1), Is.InRange(4750, 7000), "Date column width"); + POITestCase.AssertBetween("Date column width", (int) s.GetColumnWidth(0), 4750, 7000); + POITestCase.AssertBetween("Date column width", (int) s.GetColumnWidth(1), 4750, 7000); wb.Close(); } diff --git a/testcases/main/POITestCase.cs b/testcases/main/POITestCase.cs index 797e23c6b..a68aefc78 100644 --- a/testcases/main/POITestCase.cs +++ b/testcases/main/POITestCase.cs @@ -143,5 +143,17 @@ public static void TestPassesNow(int bug) { Assert.Fail("This test passes now. Please update the unit test and bug " + bug + "."); } + + public static void AssertBetween(String message, int value, int min, int max) + { + Assert.IsTrue(min <= value, message + ": " + value + " is less than the minimum value of " + min); + Assert.IsTrue(value <= max, message + ": " + value + " is greater than the maximum value of " + max); + } + + public static void AssertStrictlyBetween(String message, int value, int min, int max) + { + Assert.IsTrue(min < value, message + ": " + value + " is less than or equal to the minimum value of " + min); + Assert.IsTrue(value < max, message + ": " + value + " is greater than or equal to the maximum value of " + max); + } } } \ No newline at end of file From d5e49d2931315db8937c0d6a392acf956f484d82 Mon Sep 17 00:00:00 2001 From: Antony Liu Date: Fri, 15 Mar 2024 15:18:57 +0800 Subject: [PATCH 3/4] poi: Bug 60031: Enhance test some more --- testcases/main/SS/UserModel/TestDataFormatter.cs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/testcases/main/SS/UserModel/TestDataFormatter.cs b/testcases/main/SS/UserModel/TestDataFormatter.cs index ec45cf8a4..ffc84aaa0 100644 --- a/testcases/main/SS/UserModel/TestDataFormatter.cs +++ b/testcases/main/SS/UserModel/TestDataFormatter.cs @@ -832,8 +832,21 @@ public void TestBug60031() // with format "yyyy-dd-MM HH:mm:ss" into "2016-23-51 08:51:01". DataFormatter dfUS = new DataFormatter(CultureInfo.GetCultureInfo("en-US")); Assert.AreEqual("2016-23-08 08:51:01", dfUS.FormatRawCellContents(42605.368761574071, -1, "yyyy-dd-MM HH:mm:ss")); + Assert.AreEqual("2016-23 08:51:01 08", dfUS.FormatRawCellContents(42605.368761574071, -1, "yyyy-dd HH:mm:ss MM")); Assert.AreEqual("2017-12-01 January 09:54:33", dfUS.FormatRawCellContents(42747.412892397523, -1, "yyyy-dd-MM MMMM HH:mm:ss")); + + Assert.AreEqual("08", dfUS.FormatRawCellContents(42605.368761574071, -1, "MM")); + Assert.AreEqual("01", dfUS.FormatRawCellContents(42605.368761574071, -1, "ss")); + + // From Excel help: + /* + The "m" or "mm" code must appear immediately after the "h" or"hh" + code or immediately before the "ss" code; otherwise, Microsoft + Excel displays the month instead of minutes." + */ + Assert.AreEqual("08", dfUS.FormatRawCellContents(42605.368761574071, -1, "mm")); + Assert.AreEqual("08:51", dfUS.FormatRawCellContents(42605.368761574071, -1, "hh:mm")); + Assert.AreEqual("51:01", dfUS.FormatRawCellContents(42605.368761574071, -1, "mm:ss")); } } - } \ No newline at end of file From f01f3a17c5217bed80d12a8f7ab712d009b784eb Mon Sep 17 00:00:00 2001 From: Antony Liu Date: Sat, 16 Mar 2024 08:30:09 +0800 Subject: [PATCH 4/4] Move test to base-test-class to run it for (S)XSSF as well --- .../main/HSSF/UserModel/TestHSSFSheet.cs | 41 ------------------- testcases/main/SS/UserModel/BaseTestSheet.cs | 39 ++++++++++++++++++ 2 files changed, 39 insertions(+), 41 deletions(-) diff --git a/testcases/main/HSSF/UserModel/TestHSSFSheet.cs b/testcases/main/HSSF/UserModel/TestHSSFSheet.cs index a53538337..d1e9a1c3b 100644 --- a/testcases/main/HSSF/UserModel/TestHSSFSheet.cs +++ b/testcases/main/HSSF/UserModel/TestHSSFSheet.cs @@ -741,47 +741,6 @@ public void TestAutoSizeColumn() wb1.Close(); } - [Test] - public void TestAutoSizeDate() - { - IWorkbook wb = new HSSFWorkbook(); - ISheet s = wb.CreateSheet("Sheet1"); - IRow r = s.CreateRow(0); - r.CreateCell(0).SetCellValue(1); - r.CreateCell(1).SetCellValue(123456); - - // Will be sized fairly small - s.AutoSizeColumn((short)0); - s.AutoSizeColumn((short)1); - - // Size ranges due to different fonts on different machines - //Assert.That(s.GetColumnWidth(0), Is.InRange(350, 550), "Single number column width"); - //Assert.That(s.GetColumnWidth(1), Is.InRange(1500, 2000), "6 digit number column width"); - POITestCase.AssertBetween("Single number column width", (int) s.GetColumnWidth(0), 350, 550); - POITestCase.AssertBetween("6 digit number column width", (int) s.GetColumnWidth(1), 1500, 2000); - - // Set a date format - ICellStyle cs = wb.CreateCellStyle(); - HSSFDataFormat f = (HSSFDataFormat)wb.CreateDataFormat(); - cs.DataFormat = (/*setter*/f.GetFormat("yyyy-mm-dd MMMM hh:mm:ss")); - r.GetCell(0).CellStyle = (/*setter*/cs); - r.GetCell(1).CellStyle = (/*setter*/cs); - - Assert.IsTrue(DateUtil.IsCellDateFormatted(r.GetCell(0))); - Assert.IsTrue(DateUtil.IsCellDateFormatted(r.GetCell(1))); - - // Should Get much bigger now - s.AutoSizeColumn((short)0); - s.AutoSizeColumn((short)1); - - //Assert.That(s.GetColumnWidth(0), Is.InRange(4750, 7000), "Date column width"); - //Assert.That(s.GetColumnWidth(1), Is.InRange(4750, 7000), "Date column width"); - POITestCase.AssertBetween("Date column width", (int) s.GetColumnWidth(0), 4750, 7000); - POITestCase.AssertBetween("Date column width", (int) s.GetColumnWidth(1), 4750, 7000); - - wb.Close(); - } - [Test] public void TestAutoSizeRow() diff --git a/testcases/main/SS/UserModel/BaseTestSheet.cs b/testcases/main/SS/UserModel/BaseTestSheet.cs index c0809fa07..f3d3ebbd5 100644 --- a/testcases/main/SS/UserModel/BaseTestSheet.cs +++ b/testcases/main/SS/UserModel/BaseTestSheet.cs @@ -1453,6 +1453,45 @@ public void SetActiveCell() wb2.Close(); } + [Test] + public void TestAutoSizeDate() + { + IWorkbook wb = _testDataProvider.CreateWorkbook(); + ISheet s = wb.CreateSheet("Sheet1"); + IRow r = s.CreateRow(0); + r.CreateCell(0).SetCellValue(1); + r.CreateCell(1).SetCellValue(123456); + + // for the streaming-variant we need to enable autosize-tracking to make it work + TrackColumnsForAutoSizingIfSXSSF(s); + + // Will be sized fairly small + s.AutoSizeColumn((short) 0); + s.AutoSizeColumn((short) 1); + + // Size ranges due to different fonts on different machines + POITestCase.AssertBetween("Single number column width", (int) s.GetColumnWidth(0), 350, 570); + POITestCase.AssertBetween("6 digit number column width", (int) s.GetColumnWidth(1), 1500, 2100); + + // Set a date format + ICellStyle cs = wb.CreateCellStyle(); + IDataFormat f = wb.CreateDataFormat(); + cs.DataFormat = (/*setter*/f.GetFormat("yyyy-mm-dd MMMM hh:mm:ss")); + r.GetCell(0).CellStyle = (/*setter*/cs); + r.GetCell(1).CellStyle = (/*setter*/cs); + + Assert.IsTrue(DateUtil.IsCellDateFormatted(r.GetCell(0))); + Assert.IsTrue(DateUtil.IsCellDateFormatted(r.GetCell(1))); + + // Should Get much bigger now + s.AutoSizeColumn((short) 0); + s.AutoSizeColumn((short) 1); + + POITestCase.AssertBetween("Date column width", (int) s.GetColumnWidth(0), 4750, 7300); + POITestCase.AssertBetween("Date column width", (int) s.GetColumnWidth(1), 4750, 7300); + + wb.Close(); + } } } \ No newline at end of file