You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
360 lines
15 KiB
360 lines
15 KiB
/* ====================================================================
|
|
Licensed to the Apache Software Foundation (ASF) under one or more
|
|
contributor license agreements. See the NOTICE file distributed with
|
|
this work for Additional information regarding copyright ownership.
|
|
The ASF licenses this file to You under the Apache License, Version 2.0
|
|
(the "License"); you may not use this file except in compliance with
|
|
the License. You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
==================================================================== */
|
|
|
|
using NPOI.OpenXmlFormats.Spreadsheet;
|
|
using NPOI.SS.UserModel;
|
|
using NPOI.SS.Util;
|
|
using NPOI.Util;
|
|
using NPOI.XSSF;
|
|
using NPOI.XSSF.Streaming;
|
|
using NPOI.XSSF.UserModel;
|
|
using NUnit.Framework;using NUnit.Framework.Legacy;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Text;
|
|
using TestCases.HSSF;
|
|
|
|
namespace TestCases.XSSF.UserModel
|
|
{
|
|
[TestFixture]
|
|
public class TestUnfixedBugs
|
|
{
|
|
[Test]
|
|
public void TestBug54084Unicode()
|
|
{
|
|
// sample XLSX with the same text-contents as the text-file above
|
|
XSSFWorkbook wb = XSSFTestDataSamples.OpenSampleWorkbook("54084 - Greek - beyond BMP.xlsx");
|
|
|
|
verifyBug54084Unicode(wb);
|
|
|
|
// OutputStream baos = new FileOutputStream("/tmp/test.xlsx");
|
|
// try {
|
|
// wb.Write(baos);
|
|
// } finally {
|
|
// baos.Close();
|
|
// }
|
|
|
|
// now write the file and read it back in
|
|
XSSFWorkbook wbWritten = (XSSFWorkbook)XSSFTestDataSamples.WriteOutAndReadBack(wb);
|
|
verifyBug54084Unicode(wbWritten);
|
|
|
|
// finally also write it out via the streaming interface and verify that we still can read it back in
|
|
SXSSFWorkbook swb = new SXSSFWorkbook(wb);
|
|
IWorkbook wbStreamingWritten = SXSSFITestDataProvider.instance.WriteOutAndReadBack(swb);
|
|
verifyBug54084Unicode(wbStreamingWritten);
|
|
|
|
wbWritten.Close();
|
|
swb.Close();
|
|
wbStreamingWritten.Close();
|
|
wb.Close();
|
|
}
|
|
|
|
private void verifyBug54084Unicode(IWorkbook wb)
|
|
{
|
|
// expected data is stored in UTF-8 in a text-file
|
|
byte[] data = HSSFTestDataSamples.GetTestDataFileContent("54084 - Greek - beyond BMP.txt");
|
|
String testData = Encoding.UTF8.GetString(data).Trim();
|
|
|
|
ISheet sheet = wb.GetSheetAt(0);
|
|
IRow row = sheet.GetRow(0);
|
|
ICell cell = row.GetCell(0);
|
|
|
|
String value = cell.StringCellValue;
|
|
//Console.WriteLine(value);
|
|
|
|
ClassicAssert.AreEqual(testData, value, "The data in the text-file should exactly match the data that we read from the workbook");
|
|
}
|
|
[Test]
|
|
public void Test54071()
|
|
{
|
|
IWorkbook workbook = XSSFTestDataSamples.OpenSampleWorkbook("54071.xlsx");
|
|
ISheet sheet = workbook.GetSheetAt(0);
|
|
int rows = sheet.PhysicalNumberOfRows;
|
|
Console.WriteLine(">> file rows is:" + (rows - 1) + " <<");
|
|
IRow title = sheet.GetRow(0);
|
|
|
|
DateTime? prev = null;
|
|
for (int row = 1; row < rows; row++)
|
|
{
|
|
IRow rowObj = sheet.GetRow(row);
|
|
for (int col = 0; col < 1; col++)
|
|
{
|
|
String titleName = title.GetCell(col).ToString();
|
|
ICell cell = rowObj.GetCell(col);
|
|
if (titleName.StartsWith("time"))
|
|
{
|
|
// here the output will produce ...59 or ...58 for the rows, probably POI is
|
|
// doing some different rounding or some other small difference...
|
|
Console.WriteLine("==Time:" + cell.DateCellValue);
|
|
if (prev != null)
|
|
{
|
|
ClassicAssert.AreEqual(prev, cell.DateCellValue);
|
|
prev = cell.DateCellValue;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
workbook.Close();
|
|
}
|
|
[Ignore("test")]
|
|
public void Test54071Simple()
|
|
{
|
|
double value1 = 41224.999988425923;
|
|
double value2 = 41224.999988368058;
|
|
|
|
int wholeDays1 = (int)Math.Floor(value1);
|
|
int millisecondsInDay1 = (int)((value1 - wholeDays1) * DateUtil.DAY_MILLISECONDS + 0.5);
|
|
|
|
int wholeDays2 = (int)Math.Floor(value2);
|
|
int millisecondsInDay2 = (int)((value2 - wholeDays2) * DateUtil.DAY_MILLISECONDS + 0.5);
|
|
|
|
ClassicAssert.AreEqual(wholeDays1, wholeDays2);
|
|
// here we see that the time-value is 5 milliseconds apart, one is 86399000 and the other is 86398995,
|
|
// thus one is one second higher than the other
|
|
ClassicAssert.AreEqual(millisecondsInDay1, millisecondsInDay2, "The time-values are 5 milliseconds apart");
|
|
|
|
// when we do the calendar-stuff, there is a bool which determines if
|
|
// the milliseconds are rounded or not, having this at "false" causes the
|
|
// second to be different here!
|
|
int startYear = 1900;
|
|
int dayAdjust = -1; // Excel thinks 2/29/1900 is a valid date, which it isn't
|
|
//calendar1.Set(startYear, 0, wholeDays1 + dayAdjust, 0, 0, 0);
|
|
//calendar1.Set(Calendar.MILLISECOND, millisecondsInDay1);
|
|
DateTime calendar1 = new DateTime(startYear, 0, wholeDays1 + dayAdjust, 0, 0, 0);
|
|
calendar1.AddMilliseconds(millisecondsInDay1);
|
|
// this is the rounding part:
|
|
//calendar1.Add(Calendar.MILLISECOND, 500);
|
|
//calendar1.Clear(Calendar.MILLISECOND);
|
|
calendar1.AddMilliseconds(500);
|
|
calendar1.AddMilliseconds(-calendar1.Millisecond);
|
|
|
|
DateTime calendar2 = new DateTime(startYear, 0, wholeDays2 + dayAdjust, 0, 0, 0);
|
|
calendar2.AddMilliseconds(millisecondsInDay2);
|
|
//calendar2.Set(startYear, 0, wholeDays2 + dayAdjust, 0, 0, 0);
|
|
//calendar2.Set(Calendar.MILLISECOND, millisecondsInDay2);
|
|
// this is the rounding part:
|
|
//calendar2.Add(Calendar.MILLISECOND, 500);
|
|
//calendar2.Clear(Calendar.MILLISECOND);
|
|
calendar2.AddMilliseconds(500);
|
|
calendar2.AddMilliseconds(-calendar2.Millisecond);
|
|
|
|
// now the calendars are equal
|
|
ClassicAssert.AreEqual(calendar1, calendar2);
|
|
|
|
ClassicAssert.AreEqual(DateUtil.GetJavaDate(value1, false), DateUtil.GetJavaDate(value2, false));
|
|
}
|
|
|
|
|
|
// When this is fixed, the test case should go to BaseTestXCell with
|
|
// adjustments to use _testDataProvider to also verify this for XSSF
|
|
[Test]
|
|
[Ignore("TODO FIX CI TESTS")]
|
|
public void TestBug57294()
|
|
{
|
|
IWorkbook wb = SXSSFITestDataProvider.instance.CreateWorkbook();
|
|
|
|
ISheet sheet = wb.CreateSheet();
|
|
IRow row = sheet.CreateRow(0);
|
|
ICell cell = row.CreateCell(0);
|
|
|
|
IRichTextString str = new XSSFRichTextString("Test rich text string");
|
|
str.ApplyFont(2, 4, (short)0);
|
|
ClassicAssert.AreEqual(3, str.NumFormattingRuns);
|
|
cell.SetCellValue(str);
|
|
|
|
IWorkbook wbBack = SXSSFITestDataProvider.instance.WriteOutAndReadBack(wb);
|
|
wb.Close();
|
|
|
|
// re-read after serializing and reading back
|
|
ICell cellBack = wbBack.GetSheetAt(0).GetRow(0).GetCell(0);
|
|
ClassicAssert.IsNotNull(cellBack);
|
|
IRichTextString strBack = cellBack.RichStringCellValue;
|
|
ClassicAssert.IsNotNull(strBack);
|
|
ClassicAssert.AreEqual(3, strBack.NumFormattingRuns);
|
|
ClassicAssert.AreEqual(0, strBack.GetIndexOfFormattingRun(0));
|
|
ClassicAssert.AreEqual(2, strBack.GetIndexOfFormattingRun(1));
|
|
ClassicAssert.AreEqual(4, strBack.GetIndexOfFormattingRun(2));
|
|
|
|
wbBack.Close();
|
|
}
|
|
[Test]
|
|
public void TestBug55752()
|
|
{
|
|
IWorkbook wb = new XSSFWorkbook();
|
|
try
|
|
{
|
|
ISheet sheet = wb.CreateSheet("test");
|
|
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
IRow row = sheet.CreateRow(i);
|
|
for (int j = 0; j < 2; j++)
|
|
{
|
|
ICell cell = row.CreateCell(j);
|
|
cell.CellStyle = (wb.CreateCellStyle());
|
|
}
|
|
}
|
|
|
|
// set content
|
|
IRow row1 = sheet.GetRow(0);
|
|
row1.GetCell(0).SetCellValue("AAA");
|
|
IRow row2 = sheet.GetRow(1);
|
|
row2.GetCell(0).SetCellValue("BBB");
|
|
IRow row3 = sheet.GetRow(2);
|
|
row3.GetCell(0).SetCellValue("CCC");
|
|
IRow row4 = sheet.GetRow(3);
|
|
row4.GetCell(0).SetCellValue("DDD");
|
|
|
|
// merge cells
|
|
CellRangeAddress range1 = new CellRangeAddress(0, 0, 0, 1);
|
|
sheet.AddMergedRegion(range1);
|
|
CellRangeAddress range2 = new CellRangeAddress(1, 1, 0, 1);
|
|
sheet.AddMergedRegion(range2);
|
|
CellRangeAddress range3 = new CellRangeAddress(2, 2, 0, 1);
|
|
sheet.AddMergedRegion(range3);
|
|
ClassicAssert.AreEqual(0, range3.FirstColumn);
|
|
ClassicAssert.AreEqual(1, range3.LastColumn);
|
|
ClassicAssert.AreEqual(2, range3.LastRow);
|
|
CellRangeAddress range4 = new CellRangeAddress(3, 3, 0, 1);
|
|
sheet.AddMergedRegion(range4);
|
|
|
|
// set border
|
|
RegionUtil.SetBorderBottom((int)BorderStyle.Thin, range1, sheet);
|
|
|
|
row2.GetCell(0).CellStyle.BorderBottom = BorderStyle.Thin;
|
|
row2.GetCell(1).CellStyle.BorderBottom = BorderStyle.Thin;
|
|
ICell cell0 = CellUtil.GetCell(row3, 0);
|
|
CellUtil.SetCellStyleProperty(cell0, CellUtil.BORDER_BOTTOM, BorderStyle.Thin);
|
|
ICell cell1 = CellUtil.GetCell(row3, 1);
|
|
CellUtil.SetCellStyleProperty(cell1, CellUtil.BORDER_BOTTOM, BorderStyle.Thin);
|
|
RegionUtil.SetBorderBottom((int)BorderStyle.Thin, range4, sheet);
|
|
|
|
// write to file
|
|
Stream stream = new FileStream("55752.xlsx", FileMode.Create, FileAccess.ReadWrite);
|
|
try
|
|
{
|
|
wb.Write(stream, false);
|
|
}
|
|
finally
|
|
{
|
|
stream.Close();
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
wb.Close();
|
|
}
|
|
}
|
|
[Test]
|
|
public void Test57423()
|
|
{
|
|
IWorkbook wb = XSSFTestDataSamples.OpenSampleWorkbook("57423.xlsx");
|
|
|
|
ISheet testSheet = wb.GetSheetAt(0);
|
|
// row shift (negative or positive) causes corrupted output xlsx file when the shift value is bigger
|
|
// than the number of rows being shifted
|
|
// Excel 2010 on opening the output file says:
|
|
// "Excel found unreadable content" and offers recovering the file by removing the unreadable content
|
|
// This can be observed in cases like the following:
|
|
// negative shift of 1 row by less than -1
|
|
// negative shift of 2 rows by less than -2
|
|
// positive shift of 1 row by 2 or more
|
|
// positive shift of 2 rows by 3 or more
|
|
|
|
//testSheet.shiftRows(4, 5, -3);
|
|
testSheet.ShiftRows(10, 10, 2);
|
|
|
|
checkRows57423(testSheet);
|
|
|
|
IWorkbook wbBack = XSSFTestDataSamples.WriteOutAndReadBack(wb);
|
|
/*FileOutputStream stream = new FileOutputStream("C:\\temp\\57423.xlsx");
|
|
try {
|
|
wb.write(stream);
|
|
} finally {
|
|
stream.close();
|
|
}*/
|
|
wb.Close();
|
|
|
|
checkRows57423(wbBack.GetSheetAt(0));
|
|
|
|
wbBack.Close();
|
|
}
|
|
private void checkRows57423(ISheet testSheet)
|
|
{
|
|
checkRow57423(testSheet, 0, "0");
|
|
checkRow57423(testSheet, 1, "1");
|
|
checkRow57423(testSheet, 2, "2");
|
|
checkRow57423(testSheet, 3, "3");
|
|
checkRow57423(testSheet, 4, "4");
|
|
checkRow57423(testSheet, 5, "5");
|
|
checkRow57423(testSheet, 6, "6");
|
|
checkRow57423(testSheet, 7, "7");
|
|
checkRow57423(testSheet, 8, "8");
|
|
checkRow57423(testSheet, 9, "9");
|
|
|
|
ClassicAssert.IsNull(testSheet.GetRow(10),
|
|
"Row number 10 should be gone after the shift");
|
|
|
|
checkRow57423(testSheet, 11, "11");
|
|
checkRow57423(testSheet, 12, "10");
|
|
checkRow57423(testSheet, 13, "13");
|
|
checkRow57423(testSheet, 14, "14");
|
|
checkRow57423(testSheet, 15, "15");
|
|
checkRow57423(testSheet, 16, "16");
|
|
checkRow57423(testSheet, 17, "17");
|
|
checkRow57423(testSheet, 18, "18");
|
|
|
|
ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
|
try
|
|
{
|
|
((XSSFSheet)testSheet).Write(stream);
|
|
}
|
|
finally
|
|
{
|
|
stream.Close();
|
|
}
|
|
|
|
// verify that the resulting XML has the rows in correct order as required by Excel
|
|
String xml = Encoding.UTF8.GetString(stream.ToByteArray());
|
|
int posR12 = xml.IndexOf("<row r=\"12\"");
|
|
int posR13 = xml.IndexOf("<row r=\"13\"");
|
|
|
|
// both need to be found
|
|
ClassicAssert.IsTrue(posR12 != -1);
|
|
ClassicAssert.IsTrue(posR13 != -1);
|
|
|
|
ClassicAssert.IsTrue(posR12 < posR13,
|
|
"Need to find row 12 before row 13 after the shifting, but had row 12 at " + posR12 + " and row 13 at " + posR13);
|
|
}
|
|
private void checkRow57423(ISheet testSheet, int rowNum, String contents)
|
|
{
|
|
IRow row = testSheet.GetRow(rowNum);
|
|
ClassicAssert.IsNotNull(row, "Expecting row at rownum " + rowNum);
|
|
|
|
CT_Row ctRow = ((XSSFRow)row).GetCTRow();
|
|
ClassicAssert.AreEqual(rowNum + 1, ctRow.r);
|
|
|
|
ICell cell = row.GetCell(0);
|
|
ClassicAssert.IsNotNull(cell, "Expecting cell at rownum " + rowNum);
|
|
//why concate ".0"? There is no ".0" in excel.
|
|
ClassicAssert.AreEqual(contents, cell.ToString(), "Did not have expected contents at rownum " + rowNum);
|
|
//ClassicAssert.AreEqual(contents + ".0", cell.ToString(), "Did not have expected contents at rownum " + rowNum);
|
|
}
|
|
}
|
|
}
|
|
|