diff --git a/main/HSSF/Record/FormulaRecord.cs b/main/HSSF/Record/FormulaRecord.cs index e3eea4103..ba74708ef 100644 --- a/main/HSSF/Record/FormulaRecord.cs +++ b/main/HSSF/Record/FormulaRecord.cs @@ -248,25 +248,25 @@ public FormulaRecord() * @param in the RecordInputstream to Read the record from */ - public FormulaRecord(RecordInputStream in1):base(in1) + public FormulaRecord(RecordInputStream ris):base(ris) { - long valueLongBits = in1.ReadLong(); - field_5_options = in1.ReadShort(); + long valueLongBits = ris.ReadLong(); + field_5_options = ris.ReadShort(); specialCachedValue = SpecialCachedValue.Create(valueLongBits); if (specialCachedValue == null) { field_4_value = BitConverter.Int64BitsToDouble(valueLongBits); } - field_6_zero = in1.ReadInt(); - int field_7_expression_len = in1.ReadShort(); + field_6_zero = ris.ReadInt(); + int field_7_expression_len = ris.ReadShort(); - field_8_parsed_expr = NPOI.SS.Formula.Formula.Read(field_7_expression_len, in1,in1.Available()); + field_8_parsed_expr = NPOI.SS.Formula.Formula.Read(field_7_expression_len, ris, ris.Available()); } /** - * @return true if this {@link FormulaRecord} is followed by a - * {@link StringRecord} representing the cached text result of the formula - * evaluation. - */ + * @return true if this {@link FormulaRecord} is followed by a + * {@link StringRecord} representing the cached text result of the formula + * evaluation. + */ public bool HasCachedResultString { get diff --git a/main/POIFS/FileSystem/POIFSFileSystem.cs b/main/POIFS/FileSystem/POIFSFileSystem.cs index 32e251c2e..9068e027e 100644 --- a/main/POIFS/FileSystem/POIFSFileSystem.cs +++ b/main/POIFS/FileSystem/POIFSFileSystem.cs @@ -164,11 +164,22 @@ public static POIFSFileSystem Create(FileInfo file) // TODO Make this nicer! // Create a new empty POIFS in the file POIFSFileSystem tmp = new POIFSFileSystem(); - FileStream fout = file.Open(FileMode.OpenOrCreate, FileAccess.ReadWrite); - tmp.WriteFileSystem(fout); - fout.Close(); - tmp.Close(); - + try + { + FileStream fout = file.Open(FileMode.OpenOrCreate, FileAccess.ReadWrite); + try + { + tmp.WriteFileSystem(fout); + } + finally + { + fout.Close(); + } + } + finally + { + tmp.Close(); + } // Open it up again backed by the file return new POIFSFileSystem(file, false); } diff --git a/main/SS/Formula/Atp/WorkdayCalculator.cs b/main/SS/Formula/Atp/WorkdayCalculator.cs index b900fac31..ccad037ad 100644 --- a/main/SS/Formula/Atp/WorkdayCalculator.cs +++ b/main/SS/Formula/Atp/WorkdayCalculator.cs @@ -187,7 +187,7 @@ public int PastDaysOfWeek(double start, double end, DayOfWeek dayOfWeek) pastDaysOfWeek++; } } - return start < end ? pastDaysOfWeek : -pastDaysOfWeek; + return start <= end ? pastDaysOfWeek : -pastDaysOfWeek; } /** @@ -199,22 +199,22 @@ public int PastDaysOfWeek(double start, double end, DayOfWeek dayOfWeek) * @return number of holidays that occur in workdays, between start and end dates. */ - private int CalculateNonWeekendHolidays(double start, double end, double[] holidays) + protected internal int CalculateNonWeekendHolidays(double start, double end, double[] holidays) { int nonWeekendHolidays = 0; double startDay = start < end ? start : end; double endDay = end > start ? end : start; - for (int i = 0; i < holidays.Length; i++) + foreach (double holiday in holidays) { - if (IsInARange(startDay, endDay, holidays[i])) + if (IsInARange(startDay, endDay, holiday)) { - if (!IsWeekend(holidays[i])) + if (!IsWeekend(holiday)) { nonWeekendHolidays++; } } } - return start < end ? nonWeekendHolidays : -nonWeekendHolidays; + return start <= end ? nonWeekendHolidays : -nonWeekendHolidays; } /** @@ -236,9 +236,9 @@ private bool IsWeekend(double aDate) private bool IsHoliday(double aDate, double[] holidays) { - for (int i = 0; i < holidays.Length; i++) + foreach (double holiday in holidays) { - if (Math.Round(holidays[i]) == Math.Round(aDate)) + if (Math.Round(holiday) == Math.Round(aDate)) { return true; } @@ -251,8 +251,8 @@ private bool IsHoliday(double aDate, double[] holidays) * @param holidays an array of holidays. * @return 1 is not a workday, 0 otherwise. */ - - private int IsNonWorkday(double aDate, double[] holidays) + [Obsolete("will be removed, not used in POI itself")] + protected internal int IsNonWorkday(double aDate, double[] holidays) { return IsWeekend(aDate) || IsHoliday(aDate, holidays) ? 1 : 0; } diff --git a/main/SS/Formula/FormulaParser.cs b/main/SS/Formula/FormulaParser.cs index 5b786c8c8..2467d4969 100644 --- a/main/SS/Formula/FormulaParser.cs +++ b/main/SS/Formula/FormulaParser.cs @@ -81,7 +81,7 @@ public class FormulaParser * Tracks whether the run of whitespace preceeding "look" could be an * intersection operator. See GetChar. */ - private bool _inIntersection = false; + private bool _inIntersection; private IFormulaParsingWorkbook _book; private static SpreadsheetVersion _ssVersion; @@ -759,7 +759,7 @@ private ParseNode ParseStructuredReference(String tableName) GetChar(); } // parse column quantifier - String startColumnName = null; + String startColumnName; String endColumnName = null; int nColQuantifiers = 0; savePtr1 = _pointer; @@ -1393,6 +1393,19 @@ public override String ToString() return sb.ToString(); } } + + private String GetBookName() + { + StringBuilder sb = new StringBuilder(); + GetChar(); + while (look != ']') + { + sb.Append(look); + GetChar(); + } + GetChar(); + return sb.ToString(); + } /** * Note - caller should reset {@link #_pointer} upon null result * @return The sheet name as an identifier null if '!' is not found in the right place @@ -1403,15 +1416,7 @@ private SheetIdentifier ParseSheetName() String bookName; if (look == '[') { - StringBuilder sb = new StringBuilder(); - GetChar(); - while (look != ']') - { - sb.Append(look); - GetChar(); - } - GetChar(); - bookName = sb.ToString(); + bookName = GetBookName(); } else { @@ -1420,9 +1425,13 @@ private SheetIdentifier ParseSheetName() if (look == '\'') { - StringBuilder sb = new StringBuilder(); - Match('\''); + if (look == '[') + { + bookName = GetBookName(); + } + + StringBuilder sb = new StringBuilder(); bool done = look == '\''; while (!done) { @@ -1655,7 +1664,7 @@ private void AddName(String functionName) * Generates the variable Function ptg for the formula. * * For IF Formulas, Additional PTGs are Added To the Tokens - * @param name a {@link NamePtg} or {@link NameXPtg} or null + * @param name a {@link NamePtg} or {@link NameXPtg} or null * @return Ptg a null is returned if we're in an IF formula, it needs extreme manipulation and is handled in this Function */ private ParseNode GetFunction(String name, Ptg namePtg, ParseNode[] args) diff --git a/main/SS/UserModel/ExcelStyleDateFormatter.cs b/main/SS/UserModel/ExcelStyleDateFormatter.cs index 6aa042936..0da43fb23 100644 --- a/main/SS/UserModel/ExcelStyleDateFormatter.cs +++ b/main/SS/UserModel/ExcelStyleDateFormatter.cs @@ -59,7 +59,7 @@ static ExcelStyleDateFormatter() //DataFormatter.SetExcelStyleRoundingMode(format4digits); } - private double dateToBeFormatted = 0.0; + private double dateToBeFormatted; public ExcelStyleDateFormatter() : base() @@ -73,16 +73,18 @@ public ExcelStyleDateFormatter(String pattern) } - //public ExcelStyleDateFormatter(String pattern, - // DateFormatSymbols formatSymbols) - //{ - // super(processFormatPattern(pattern), formatSymbols); - //} + public ExcelStyleDateFormatter(String pattern, + DateTimeFormatInfo formatSymbols) + : base(ProcessFormatPattern(pattern), formatSymbols) + { + + } - //public ExcelStyleDateFormatter(String pattern, Locale locale) - //{ - // super(processFormatPattern(pattern), locale); - //} + public ExcelStyleDateFormatter(String pattern, CultureInfo locale) + : base(ProcessFormatPattern(pattern), locale) + { + + } private static string DateTimeMatchEvaluator(Match match) { return match.Groups[1].Value; @@ -94,12 +96,12 @@ private static string DateTimeMatchEvaluator(Match match) private static String ProcessFormatPattern(String f) { String t = f.Replace("MMMMM", MMMMM_START_SYMBOL + "MMM" + MMMMM_TRUNCATE_SYMBOL); - t = Regex.Replace(t, "\\[H\\]", (H_BRACKET_SYMBOL).ToString(), RegexOptions.IgnoreCase); - t = Regex.Replace(t, "\\[HH\\]", (HH_BRACKET_SYMBOL).ToString(), RegexOptions.IgnoreCase); - t = Regex.Replace(t, "\\[m\\]", (M_BRACKET_SYMBOL).ToString(), RegexOptions.IgnoreCase); - t = Regex.Replace(t, "\\[mm\\]", (MM_BRACKET_SYMBOL).ToString(), RegexOptions.IgnoreCase); - t = Regex.Replace(t, "\\[s\\]", (S_BRACKET_SYMBOL).ToString(), RegexOptions.IgnoreCase); - t = Regex.Replace(t, "\\[ss\\]", (SS_BRACKET_SYMBOL).ToString(), RegexOptions.IgnoreCase); + t = Regex.Replace(t, "\\[H]", (H_BRACKET_SYMBOL).ToString(), RegexOptions.IgnoreCase); + t = Regex.Replace(t, "\\[HH]", (HH_BRACKET_SYMBOL).ToString(), RegexOptions.IgnoreCase); + t = Regex.Replace(t, "\\[m]", (M_BRACKET_SYMBOL).ToString(), RegexOptions.IgnoreCase); + t = Regex.Replace(t, "\\[mm]", (MM_BRACKET_SYMBOL).ToString(), RegexOptions.IgnoreCase); + t = Regex.Replace(t, "\\[s]", (S_BRACKET_SYMBOL).ToString(), RegexOptions.IgnoreCase); + t = Regex.Replace(t, "\\[ss]", (SS_BRACKET_SYMBOL).ToString(), RegexOptions.IgnoreCase); t = t.Replace("s.000", "s.fff"); t = t.Replace("s.00", "s." + LL_BRACKET_SYMBOL); t = t.Replace("s.0", "s." + L_BRACKET_SYMBOL); @@ -142,7 +144,7 @@ public StringBuilder Format(DateTime date, StringBuilder paramStringBuilder, Cul // Now handle our special cases if (s.IndexOf(MMMMM_START_SYMBOL) != -1) { - Regex reg = new Regex(MMMMM_START_SYMBOL + "(\\w)\\w+" + MMMMM_TRUNCATE_SYMBOL, RegexOptions.IgnoreCase); + Regex reg = new Regex(MMMMM_START_SYMBOL + "(\\p{L}|\\p{P}|\\p{N})[\\p{L}|\\p{P}|\\p{N}]+" + MMMMM_TRUNCATE_SYMBOL, RegexOptions.IgnoreCase); Match m = reg.Match(s); if (m.Success) { diff --git a/ooxml/XSSF/UserModel/XSSFRelation.cs b/ooxml/XSSF/UserModel/XSSFRelation.cs index 960d2f959..c61b3ac69 100644 --- a/ooxml/XSSF/UserModel/XSSFRelation.cs +++ b/ooxml/XSSF/UserModel/XSSFRelation.cs @@ -315,6 +315,13 @@ public class XSSFRelation : POIXMLRelation null ); + public static XSSFRelation CUSTOM_PROPERTIES = new XSSFRelation( + "application/vnd.openxmlformats-officedocument.spreadsheetml.customProperty", + "http://schemas.openxmlformats.org/officeDocument/2006/relationships/customProperty", + "/xl/customProperty#.bin", + null + ); + public static String NS_SPREADSHEETML = "http://schemas.openxmlformats.org/spreadsheetml/2006/main"; public static String NS_DRAWINGML = "http://schemas.openxmlformats.org/drawingml/2006/main"; public static String NS_CHART = "http://schemas.openxmlformats.org/drawingml/2006/chart"; diff --git a/testcases/main/HSSF/Model/TestFormulaParser.cs b/testcases/main/HSSF/Model/TestFormulaParser.cs index e7baadb60..6f73fb084 100644 --- a/testcases/main/HSSF/Model/TestFormulaParser.cs +++ b/testcases/main/HSSF/Model/TestFormulaParser.cs @@ -1483,8 +1483,7 @@ public void TestBackSlashInNames() } /** - * TODO - delete equiv Test: - * {@link BaseTestBugzillaIssues#test42448()} + * See the related/similar test: {@link BaseTestBugzillaIssues#test42448()} */ [Test] public void TestParseAbnormalSheetNamesAndRanges_bug42448() @@ -1537,11 +1536,11 @@ public void TestRangeFuncOperand_bug46951() [Test] public void TestUnionOfFullCollFullRowRef() { + ParseFormula("3:4"); Ptg[] ptgs; - ptgs = ParseFormula("3:4"); ptgs = ParseFormula("$Z:$AC"); ConfirmTokenClasses(ptgs, typeof(AreaPtg)); - ptgs = ParseFormula("B:B"); + ParseFormula("B:B"); ptgs = ParseFormula("$11:$13"); ConfirmTokenClasses(ptgs, typeof(AreaPtg)); diff --git a/testcases/main/HSSF/UserModel/TestBugs.cs b/testcases/main/HSSF/UserModel/TestBugs.cs index 7e07fe21b..60d7ab955 100644 --- a/testcases/main/HSSF/UserModel/TestBugs.cs +++ b/testcases/main/HSSF/UserModel/TestBugs.cs @@ -2274,16 +2274,16 @@ public void Test45777() } } /** - * Problems with formula references to - * sheets via URLs - */ + * Problems with formula references to + * sheets via URLs + */ [Test] - public void Test45970() + public void Bug45970() { - HSSFWorkbook wb = OpenSample("FormulaRefs.xls"); - Assert.AreEqual(3, wb.NumberOfSheets); + HSSFWorkbook wb1 = OpenSample("FormulaRefs.xls"); + Assert.AreEqual(3, wb1.NumberOfSheets); - ISheet s = wb.GetSheetAt(0); + ISheet s = wb1.GetSheetAt(0); IRow row; row = s.GetRow(0); @@ -2310,10 +2310,20 @@ public void Test45970() Assert.AreEqual("'[$http://gagravarr.org/FormulaRefs.xls]Sheet1'!B1", row.GetCell(1).CellFormula); Assert.AreEqual(112.0, row.GetCell(1).NumericCellValue); + // Link our new workbook + IWorkbook externalWb1 = new HSSFWorkbook(); + externalWb1.CreateSheet("Sheet1"); + wb1.LinkExternalWorkbook("$http://gagravarr.org/FormulaRefs2.xls", externalWb1); + // Change 4 row.GetCell(1).CellFormula = ("'[$http://gagravarr.org/FormulaRefs2.xls]Sheet1'!B2"); row.GetCell(1).SetCellValue(123.0); + // Link our new workbook + IWorkbook externalWb2 = new HSSFWorkbook(); + externalWb2.CreateSheet("Sheet1"); + wb1.LinkExternalWorkbook("$http://example.com/FormulaRefs.xls", externalWb2); + // Add 5 row = s.CreateRow(5); row.CreateCell(1, CellType.Formula); @@ -2322,8 +2332,9 @@ public void Test45970() // Re-test - wb = WriteOutAndReadBack(wb); - s = wb.GetSheetAt(0); + HSSFWorkbook wb2 = WriteOutAndReadBack(wb1); + wb1.Close(); + s = wb2.GetSheetAt(0); row = s.GetRow(0); Assert.AreEqual(CellType.Numeric, row.GetCell(1).CellType); @@ -2344,25 +2355,20 @@ public void Test45970() Assert.AreEqual("[Formulas2.xls]Sheet1!B2", row.GetCell(1).CellFormula); Assert.AreEqual(112.0, row.GetCell(1).NumericCellValue); -#if !HIDE_UNREACHABLE_CODE - // TODO - Fix these so they work... - if (1 == 2) - { - row = s.GetRow(4); - Assert.AreEqual(CellType.Formula, row.GetCell(1).CellType); - Assert.AreEqual("'[\u0005$http://gagravarr.org/FormulaRefs2.xls]Sheet1'!B2", row.GetCell(1).CellFormula); - Assert.AreEqual(123.0, row.GetCell(1).NumericCellValue); + row = s.GetRow(4); + Assert.AreEqual(CellType.Formula, row.GetCell(1).CellType); + Assert.AreEqual("'[$http://gagravarr.org/FormulaRefs2.xls]Sheet1'!B2", row.GetCell(1).CellFormula); + Assert.AreEqual(123.0, row.GetCell(1).NumericCellValue); - row = s.GetRow(5); - Assert.AreEqual(CellType.Formula, row.GetCell(1).CellType); - Assert.AreEqual("'[\u0005$http://example.com/FormulaRefs.xls]Sheet1'!B1", row.GetCell(1).CellFormula); - Assert.AreEqual(234.0, row.GetCell(1).NumericCellValue); - } -#endif + row = s.GetRow(5); + Assert.AreEqual(CellType.Formula, row.GetCell(1).CellType); + Assert.AreEqual("'[$http://example.com/FormulaRefs.xls]Sheet1'!B1", row.GetCell(1).CellFormula); + Assert.AreEqual(234.0, row.GetCell(1).NumericCellValue); + + wb2.Close(); } [Test] - public void Test47251() - { + public void Test47251() { // Firstly, try with one that triggers on InterfaceHdrRecord OpenSample("47251.xls"); diff --git a/testcases/main/SS/Formula/Atp/TestWorkdayCalculator.cs b/testcases/main/SS/Formula/Atp/TestWorkdayCalculator.cs index 8f0f069f6..ff74d8753 100644 --- a/testcases/main/SS/Formula/Atp/TestWorkdayCalculator.cs +++ b/testcases/main/SS/Formula/Atp/TestWorkdayCalculator.cs @@ -16,6 +16,7 @@ limitations under the License. ==================================================================== */ using System; +using System.Diagnostics.CodeAnalysis; using NPOI.SS.Formula.Atp; using NPOI.SS.UserModel; using NUnit.Framework; @@ -66,6 +67,27 @@ public void TestCalculateWorkdaysShouldIgnoreWeekendHolidays() Assert.AreEqual(4, WorkdayCalculator.instance.CalculateWorkdays(A_FRIDAY, A_WEDNESDAY, new double[] { A_SATURDAY, A_SUNDAY })); } + [Test] + public void TestCalculateWorkdaysOnSameDayShouldReturn1ForWeekdays() + { + double A_MONDAY = DateUtil.GetExcelDate(new DateTime(2017, 1, 2)); + Assert.AreEqual(1, WorkdayCalculator.instance.CalculateWorkdays(A_MONDAY, A_MONDAY, new double[0])); + } + + [Test] + public void TestCalculateWorkdaysOnSameDayShouldReturn0ForHolidays() + { + double A_MONDAY = DateUtil.GetExcelDate(new DateTime(2017, 1, 2)); + Assert.AreEqual(0, WorkdayCalculator.instance.CalculateWorkdays(A_MONDAY, A_MONDAY, new double[] { A_MONDAY })); + } + + [Test] + public void TestCalculateWorkdaysOnSameDayShouldReturn0ForWeekends() + { + double A_SUNDAY = DateUtil.GetExcelDate(new DateTime(2017, 1, 1)); + Assert.AreEqual(0, WorkdayCalculator.instance.CalculateWorkdays(A_SUNDAY, A_SUNDAY, new double[0])); + } + [Test] public void TestCalculateWorkdaysNumberOfDays() { @@ -110,6 +132,44 @@ public void TestPastDaysOfWeekShouldReturn1EndingAtASaturday() double A_SATURDAY = DateUtil.GetExcelDate(new DateTime(2011, December, 10)); Assert.AreEqual(1, WorkdayCalculator.instance.PastDaysOfWeek(A_THURSDAY, A_SATURDAY, DayOfWeek.Saturday)); } + + [Test] + public void TestCalculateNonWeekendHolidays() + { + double start = DateUtil.GetExcelDate(new DateTime(2016, 12, 24)); + double end = DateUtil.GetExcelDate(new DateTime(2016, 12, 31)); + double holiday1 = DateUtil.GetExcelDate(new DateTime(2016, 12, 25)); + double holiday2 = DateUtil.GetExcelDate(new DateTime(2016, 12, 26)); + int count = WorkdayCalculator.instance.CalculateNonWeekendHolidays(start, end, new double[] { holiday1, holiday2 }); + Assert.AreEqual(1, count, + "Expected 1 non-weekend-holiday for " + start + " to " + end + " and " + holiday1 + " and " + holiday2); + } + + [Test] + public void TestCalculateNonWeekendHolidaysOneDay() + { + double start = DateUtil.GetExcelDate(new DateTime(2016, 12, 26)); + double end = DateUtil.GetExcelDate(new DateTime(2016, 12, 26)); + double holiday1 = DateUtil.GetExcelDate(new DateTime(2016, 12, 25)); + double holiday2 = DateUtil.GetExcelDate(new DateTime(2016, 12, 26)); + int count = WorkdayCalculator.instance.CalculateNonWeekendHolidays(start, end, new double[] { holiday1, holiday2 }); + Assert.AreEqual(1, count, + "Expected 1 non-weekend-holiday for " + start + " to " + end + " and " + holiday1 + " and " + holiday2); + } + + [Test] + public void TestIsNonWorkday() + { + double weekend = DateUtil.GetExcelDate(new DateTime(2016, 12, 25)); + double holiday = DateUtil.GetExcelDate(new DateTime(2016, 12, 26)); + double workday = DateUtil.GetExcelDate(new DateTime(2016, 12, 27)); +#pragma warning disable CS0618 // 类型或成员已过时 + Assert.AreEqual(1, WorkdayCalculator.instance.IsNonWorkday(weekend, new double[] { holiday })); + Assert.AreEqual(1, WorkdayCalculator.instance.IsNonWorkday(holiday, new double[] { holiday })); + Assert.AreEqual(0, WorkdayCalculator.instance.IsNonWorkday(workday, new double[] { holiday })); +#pragma warning restore CS0618 // 类型或成员已过时 + + } } } \ No newline at end of file diff --git a/testcases/main/SS/UserModel/TestExcelStyleDateFormatter.cs b/testcases/main/SS/UserModel/TestExcelStyleDateFormatter.cs new file mode 100644 index 000000000..63ac7eb87 --- /dev/null +++ b/testcases/main/SS/UserModel/TestExcelStyleDateFormatter.cs @@ -0,0 +1,139 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TestCases.SS.UserModel +{ + using NPOI.Util; + using NPOI.SS.UserModel; + using NUnit.Framework; + using System.Globalization; + using NPOI.SS.Util; + + [TestFixture] + public class TestExcelStyleDateFormatter + { + private static String EXCEL_DATE_FORMAT = "MMMMM"; + private static CultureInfo ROOT = CultureInfo.GetCultureInfo("en-US"); + /// + /// [Bug 60369] Month format 'MMMMM' issue with TEXT-formula and Java 8 + /// + [Test] + public void Test60369() + { + + // Setting up the locale to be tested together with a list of asserted unicode-formatted results and Put them in a map. + //Locale germanLocale = Locale.GERMAN; + CultureInfo germanLocale = CultureInfo.GetCultureInfo("de-DE"); + + //Locale russianLocale = new Locale("ru", "RU"); + CultureInfo russianLocale = CultureInfo.GetCultureInfo("ru-RU"); + + //Locale austrianLocale = new Locale("de", "AT"); + CultureInfo austrianLocale = CultureInfo.GetCultureInfo("de-AT"); + + //Locale englishLocale = Locale.UK; + CultureInfo englishLocale = CultureInfo.GetCultureInfo("en-GB"); + + //Locale frenchLocale = Locale.FRENCH; + CultureInfo frenchLocale = CultureInfo.GetCultureInfo("fr-FR"); + + //Locale chineseLocale = Locale.CHINESE; + CultureInfo chineseLocale = CultureInfo.GetCultureInfo("zh-Hans"); + + //Locale turkishLocale = new Locale("tr", "TR"); + CultureInfo turkishLocale = CultureInfo.GetCultureInfo("tr-TR"); + + //Locale hungarianLocale = new Locale("hu", "HU"); + CultureInfo hungarianLocale = CultureInfo.GetCultureInfo("hu-HU"); + + //Locale indianLocale = new Locale("en", "IN"); + CultureInfo indianLocale = CultureInfo.GetCultureInfo("en-IN"); + + //Locale indonesianLocale = new Locale("in", "ID"); + CultureInfo indonesianLocale = CultureInfo.GetCultureInfo("id-ID"); + + Dictionary testMap = new() + { + { chineseLocale, "123456789111"}, // "\u4e00\u4e8c\u4e09\u56db\u4e94\u516d\u4e03\u516b\u4e5d\u5341\u5341\u5341"="一二三四五六七八九十十十" ,"123456789111" + { germanLocale, "JFMAMJJASOND" }, + { russianLocale, "\u044f\u0444\u043c\u0430\u043c\u0438\u0438\u0430\u0441\u043e\u043d\u0434" }, + { austrianLocale, "JFMAMJJASOND" }, + { englishLocale, "JFMAMJJASOND" }, + { frenchLocale, "jfmamjjasond" }, + { turkishLocale, "\u004f\u015e\u004d\u004e\u004d\u0048\u0054\u0041\u0045\u0045\u004b\u0041" }, + { hungarianLocale, "\u006a\u0066\u006d\u00e1\u006d\u006a\u006a\u0061\u0073\u006f\u006e\u0064" }, + { indianLocale, "JFMAMJJASOND" }, + { indonesianLocale, "JFMAMJJASOND" } + }; + String[] dates = { + "1980-01-12", "1995-02-11", "2045-03-10", "2016-04-09", "2017-05-08", + "1945-06-07", "1998-07-06", "2099-08-05", "1988-09-04", "2023-10-03", "1978-11-02", "1890-12-01" + }; + // We have to Set up dates as well. + List testDates = new(); + Array.ForEach(dates, (s) => testDates.Add(DateTime.Parse(s))); + + + // Let's iterate over the test Setup. + foreach (CultureInfo locale in testMap.Keys) + { + //System.err.Println("Locale: " + locale); + ExcelStyleDateFormatter formatter = new ExcelStyleDateFormatter(EXCEL_DATE_FORMAT, locale.DateTimeFormat); + for (int i = 0; i < 12; i++) + { + // Call the method to be tested! + String result = + formatter.Format(testDates[i], + new StringBuilder(), + locale).ToString(); + //new FieldPosition(java.text.DateFormat.MONTH_FIELD)).ToString(); + //System.err.Println(result + " - " + GetUnicode(result[0])); + Assert.AreEqual(GetUnicode(testMap[locale][i]), GetUnicode(result[0]), + "current culture:"+ locale.ToString() + ", date="+ testDates[i]); + } + } + } + + private String GetUnicode(char c) + { + return "\\u" + HexDump.ToHex(c | 0x10000).Substring(1); + } + + [Test] + public void TestConstruct() + { + Assert.IsNotNull(new ExcelStyleDateFormatter(EXCEL_DATE_FORMAT, LocaleUtil.GetUserLocale())); + Assert.IsNotNull(new ExcelStyleDateFormatter(EXCEL_DATE_FORMAT)); + } + + [Test] + public void TestWithLocale() + { + + CultureInfo before = LocaleUtil.GetUserLocale(); + try + { + LocaleUtil.SetUserLocale(CultureInfo.GetCultureInfo("de-DE")); + String dateStr = new ExcelStyleDateFormatter(EXCEL_DATE_FORMAT).Format( + new SimpleDateFormat("yyyy-MM-dd", ROOT).Parse("2016-03-26"), + CultureInfo.GetCultureInfo("de-DE")); + Assert.AreEqual("M", dateStr); + } + finally + { + LocaleUtil.SetUserLocale(before); + } + } + + [Test] + public void TestWithPattern() + { + String dateStr = new ExcelStyleDateFormatter("yyyy|" + EXCEL_DATE_FORMAT + "|").Format( + new SimpleDateFormat("yyyy-MM-dd", ROOT).Parse("2016-03-26"), ROOT); + Assert.AreEqual("2016|M|", dateStr); + } + } +} \ No newline at end of file diff --git a/testcases/ooxml/SS/Formula/TestFormulaParser.cs b/testcases/ooxml/SS/Formula/TestFormulaParser.cs index d4b548774..7cfd8a746 100644 --- a/testcases/ooxml/SS/Formula/TestFormulaParser.cs +++ b/testcases/ooxml/SS/Formula/TestFormulaParser.cs @@ -233,7 +233,6 @@ public void TestParseExternalReferencesWithUnquotedSheetName() } // bug 60219: FormulaParser can't parse external references when sheet name is quoted - [Ignore("bug 60219: FormulaParser can't parse external references when sheet name is quoted")] [Test] public void TestParseExternalReferencesWithQuotedSheetName() { diff --git a/testcases/ooxml/XSSF/TestXSSFCloneSheet.cs b/testcases/ooxml/XSSF/TestXSSFCloneSheet.cs index aad263620..3bc014638 100644 --- a/testcases/ooxml/XSSF/TestXSSFCloneSheet.cs +++ b/testcases/ooxml/XSSF/TestXSSFCloneSheet.cs @@ -18,7 +18,10 @@ limitations under the License. namespace TestCases.XSSF { using System; + using System.IO; using NPOI.SS.UserModel; + using NPOI.Util; + using NPOI.XSSF; using NPOI.XSSF.UserModel; using NUnit.Framework; using TestCases.HSSF; @@ -59,6 +62,35 @@ public void TestCloneSheetIntStringInvalidName() { } Assert.AreEqual(1, wb.NumberOfSheets); } + + [Test] + public void Test60512() + { + XSSFWorkbook wb = XSSFTestDataSamples.OpenSampleWorkbook("60512.xlsm"); + + Assert.AreEqual(1, wb.NumberOfSheets); + ISheet sheet = wb.CloneSheet(0); + Assert.IsNotNull(sheet); + Assert.AreEqual(2, wb.NumberOfSheets); + + + IWorkbook wbBack = XSSFTestDataSamples.WriteOutAndReadBack(wb); + Assert.IsNotNull(wbBack); + wbBack.Close(); + FileInfo fi = TempFile.CreateTempFile("60512", ".xlsx"); + //Stream str = new FileStream("/tmp/60512.xlsx", FileMode.Create, FileAccess.Write); + Stream str = new FileStream(fi.FullName, FileMode.Create, FileAccess.Write); + try + { + wb.Write(str); + } + finally + { + str.Close(); + } + + wb.Close(); + } } } \ No newline at end of file diff --git a/testcases/test-data/spreadsheet/60512.xlsm b/testcases/test-data/spreadsheet/60512.xlsm new file mode 100644 index 000000000..7c38c6d27 Binary files /dev/null and b/testcases/test-data/spreadsheet/60512.xlsm differ