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