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.
497 lines
19 KiB
497 lines
19 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.
|
|
==================================================================== */
|
|
|
|
namespace NPOI.XSSF.UserModel
|
|
{
|
|
using System;
|
|
using NPOI.SS.UserModel;
|
|
using NPOI.XSSF;
|
|
using NUnit.Framework;
|
|
|
|
[TestFixture]
|
|
public class TestXSSFSheetRowGrouping
|
|
{
|
|
|
|
private static int ROWS_NUMBER = 200;
|
|
private static int GROUP_SIZE = 5;
|
|
|
|
//private int o_groupsNumber = 0;
|
|
|
|
[Test]
|
|
public void Test55640()
|
|
{
|
|
//long startTime = System.CurrentTimeMillis();
|
|
IWorkbook wb = new XSSFWorkbook();
|
|
FillData(wb);
|
|
WriteToFile(wb);
|
|
|
|
//System.out.Println("Number of groups: " + o_groupsNumber);
|
|
//System.out.Println("Execution time: " + (System.CurrentTimeMillis()-startTime) + " ms");
|
|
}
|
|
|
|
|
|
private void FillData(IWorkbook p_wb)
|
|
{
|
|
ISheet sheet = p_wb.CreateSheet("sheet123");
|
|
sheet.RowSumsBelow = (/*setter*/false);
|
|
int i;
|
|
for (i = 0; i < ROWS_NUMBER; i++)
|
|
{
|
|
IRow row = sheet.CreateRow(i);
|
|
ICell cell = row.CreateCell(0);
|
|
cell.SetCellValue(i + 1);
|
|
}
|
|
|
|
i = 1;
|
|
while (i < ROWS_NUMBER)
|
|
{
|
|
int end = i + (GROUP_SIZE - 2);
|
|
int start = i; // natural order
|
|
// int start = end - 1; // reverse order
|
|
while (start < end)
|
|
{ // natural order
|
|
// while (start >= i) { // reverse order
|
|
sheet.GroupRow(start, end);
|
|
//o_groupsNumber++;
|
|
bool collapsed = IsCollapsed();
|
|
//System.out.Println("Set group " + start + "->" + end + " to " + collapsed);
|
|
sheet.SetRowGroupCollapsed(start, collapsed);
|
|
start++; // natural order
|
|
// start--; // reverse order
|
|
}
|
|
i += GROUP_SIZE;
|
|
}
|
|
}
|
|
|
|
private bool IsCollapsed()
|
|
{
|
|
Random rnd = new Random();
|
|
return rnd.NextDouble() > 0.5d;
|
|
}
|
|
|
|
private void WriteToFile(IWorkbook p_wb)
|
|
{
|
|
// FileOutputStream fileOut = new FileOutputStream("/tmp/55640.xlsx");
|
|
// try {
|
|
// p_wb.Write(fileOut);
|
|
// } finally {
|
|
// fileOut.Close();
|
|
// }
|
|
Assert.IsNotNull(XSSFTestDataSamples.WriteOutAndReadBack(p_wb));
|
|
}
|
|
|
|
[Test]
|
|
public void Test55640reduce1()
|
|
{
|
|
IWorkbook wb = new XSSFWorkbook();
|
|
ISheet sheet = wb.CreateSheet("sheet123");
|
|
sheet.RowSumsBelow = (/*setter*/false);
|
|
int i;
|
|
for (i = 0; i < ROWS_NUMBER; i++)
|
|
{
|
|
IRow row = sheet.CreateRow(i);
|
|
ICell cell = row.CreateCell(0);
|
|
cell.SetCellValue(i + 1);
|
|
}
|
|
|
|
i = 1;
|
|
while (i < ROWS_NUMBER)
|
|
{
|
|
int end = i + (GROUP_SIZE - 2);
|
|
int start = i; // natural order
|
|
while (start < end)
|
|
{ // natural order
|
|
sheet.GroupRow(start, end);
|
|
//o_groupsNumber++;
|
|
bool collapsed = start % 2 == 0 ? false : true;
|
|
//System.out.Println("Set group " + start + "->" + end + " to " + collapsed);
|
|
sheet.SetRowGroupCollapsed(start, collapsed);
|
|
start++; // natural order
|
|
}
|
|
i += GROUP_SIZE;
|
|
}
|
|
WriteToFile(wb);
|
|
}
|
|
|
|
|
|
[Test]
|
|
public void Test55640_VerifyCases()
|
|
{
|
|
// NOTE: This is currently based on current behavior of POI, somehow
|
|
// what POI returns in the calls to collapsed/hidden is not fully matching
|
|
// the examples in the spec or I did not fully understand how POI stores the data internally...
|
|
|
|
// all expanded
|
|
verifyGroupCollapsed(
|
|
// level1, level2, level3
|
|
false, false, false,
|
|
// collapsed:
|
|
new Boolean[] { false, false, false, false, false },
|
|
// hidden:
|
|
new bool[] { false, false, false, false, false },
|
|
// outlineLevel
|
|
new int[] { 1, 2, 3, 3, 3 }
|
|
);
|
|
|
|
|
|
// Level 1 collapsed, others expanded, should only have 4 rows, all hidden:
|
|
verifyGroupCollapsed(
|
|
// level1, level2, level3
|
|
true, false, false,
|
|
// collapsed:
|
|
new Boolean[] { false, false, false, false, false },
|
|
// hidden:
|
|
new bool[] { true, true, true, true, true },
|
|
// outlineLevel
|
|
new int[] { 1, 2, 3, 3, 3 }
|
|
);
|
|
|
|
// Level 1 and 2 collapsed, Level 3 expanded,
|
|
verifyGroupCollapsed(
|
|
// level1, level2, level3
|
|
true, true, false,
|
|
// collapsed:
|
|
new Boolean[] { false, false, false, false, true, false },
|
|
// hidden:
|
|
new bool[] { true, true, true, true, true, false },
|
|
// outlineLevel
|
|
new int[] { 1, 2, 3, 3, 3, 0 }
|
|
);
|
|
|
|
// Level 1 collapsed, Level 2 expanded, Level 3 collapsed
|
|
verifyGroupCollapsed(
|
|
// level1, level2, level3
|
|
true, false, true,
|
|
// collapsed:
|
|
new Boolean[] { false, false, false, false, false, true },
|
|
// hidden:
|
|
new bool[] { true, true, true, true, true, false },
|
|
// outlineLevel
|
|
new int[] { 1, 2, 3, 3, 3, 0 }
|
|
);
|
|
|
|
// Level 2 collapsed, others expanded:
|
|
verifyGroupCollapsed(
|
|
// level1, level2, level3
|
|
false, true, false,
|
|
// collapsed:
|
|
new Boolean[] { false, false, false, false, false, false },
|
|
// hidden:
|
|
new bool[] { false, true, true, true, true, false },
|
|
// outlineLevel
|
|
new int[] { 1, 2, 3, 3, 3, 0 }
|
|
);
|
|
|
|
// Level 3 collapsed, others expanded
|
|
verifyGroupCollapsed(
|
|
// level1, level2, level3
|
|
false, false, true,
|
|
// collapsed:
|
|
new Boolean[] { false, false, false, false, false, true },
|
|
// hidden:
|
|
new bool[] { false, false, true, true, true, false },
|
|
// outlineLevel
|
|
new int[] { 1, 2, 3, 3, 3, 0 }
|
|
);
|
|
|
|
// All collapsed
|
|
verifyGroupCollapsed(
|
|
// level1, level2, level3
|
|
true, true, true,
|
|
// collapsed:
|
|
new Boolean[] { false, false, false, false, true, true },
|
|
// hidden:
|
|
new bool[] { true, true, true, true, true, false },
|
|
// outlineLevel
|
|
new int[] { 1, 2, 3, 3, 3, 0 }
|
|
);
|
|
}
|
|
|
|
|
|
private void verifyGroupCollapsed(bool level1, bool level2, bool level3,
|
|
Boolean[] collapsed, bool[] hidden, int[] outlineLevel)
|
|
{
|
|
IWorkbook wb = new XSSFWorkbook();
|
|
ISheet sheet = wb.CreateSheet("sheet123");
|
|
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
sheet.CreateRow(i);
|
|
}
|
|
|
|
sheet.GroupRow(0, 4);
|
|
sheet.GroupRow(1, 4);
|
|
sheet.GroupRow(2, 4);
|
|
|
|
sheet.SetRowGroupCollapsed(0, level1);
|
|
sheet.SetRowGroupCollapsed(1, level2);
|
|
sheet.SetRowGroupCollapsed(2, level3);
|
|
|
|
CheckWorkbookGrouping(wb, collapsed, hidden, outlineLevel);
|
|
}
|
|
|
|
[Test]
|
|
public void Test55640_VerifyCasesSpec()
|
|
{
|
|
// NOTE: This is currently based on current behavior of POI, somehow
|
|
// what POI returns in the calls to collapsed/hidden is not fully matching
|
|
// the examples in the spec or I did not fully understand how POI stores the data internally...
|
|
|
|
// all expanded
|
|
verifyGroupCollapsedSpec(
|
|
// level3, level2, level1
|
|
false, false, false,
|
|
// collapsed:
|
|
new Boolean[] { false, false, false, false },
|
|
// hidden:
|
|
new bool[] { false, false, false, false },
|
|
// outlineLevel
|
|
new int[] { 3, 3, 2, 1 }
|
|
);
|
|
|
|
|
|
verifyGroupCollapsedSpec(
|
|
// level3, level2, level1
|
|
false, false, true,
|
|
// collapsed:
|
|
new Boolean[] { false, false, false, true },
|
|
// hidden:
|
|
new bool[] { true, true, true, false },
|
|
// outlineLevel
|
|
new int[] { 3, 3, 2, 1 }
|
|
);
|
|
|
|
verifyGroupCollapsedSpec(
|
|
// level3, level2, level1
|
|
false, true, false,
|
|
// collapsed:
|
|
new Boolean[] { false, false, true, false },
|
|
// hidden:
|
|
new bool[] { true, true, true, false },
|
|
// outlineLevel
|
|
new int[] { 3, 3, 2, 1 }
|
|
);
|
|
|
|
verifyGroupCollapsedSpec(
|
|
// level3, level2, level1
|
|
false, true, true,
|
|
// collapsed:
|
|
new Boolean[] { false, false, true, true },
|
|
// hidden:
|
|
new bool[] { true, true, true, false },
|
|
// outlineLevel
|
|
new int[] { 3, 3, 2, 1 }
|
|
);
|
|
}
|
|
|
|
private void verifyGroupCollapsedSpec(bool level1, bool level2, bool level3,
|
|
Boolean[] collapsed, bool[] hidden, int[] outlineLevel)
|
|
{
|
|
IWorkbook wb = new XSSFWorkbook();
|
|
ISheet sheet = wb.CreateSheet("sheet123");
|
|
|
|
for (int i = 5; i < 9; i++)
|
|
{
|
|
sheet.CreateRow(i);
|
|
}
|
|
|
|
sheet.GroupRow(5, 6);
|
|
sheet.GroupRow(5, 7);
|
|
sheet.GroupRow(5, 8);
|
|
|
|
sheet.SetRowGroupCollapsed(6, level1);
|
|
sheet.SetRowGroupCollapsed(7, level2);
|
|
sheet.SetRowGroupCollapsed(8, level3);
|
|
|
|
CheckWorkbookGrouping(wb, collapsed, hidden, outlineLevel);
|
|
}
|
|
|
|
private void CheckWorkbookGrouping(IWorkbook wb, bool[] collapsed, bool[] hidden, int[] outlineLevel)
|
|
{
|
|
printWorkbook(wb);
|
|
ISheet sheet = wb.GetSheetAt(0);
|
|
|
|
Assert.AreEqual(collapsed.Length, hidden.Length);
|
|
Assert.AreEqual(collapsed.Length, outlineLevel.Length);
|
|
Assert.AreEqual(collapsed.Length, sheet.LastRowNum - sheet.FirstRowNum + 1,
|
|
"Expected " + collapsed.Length + " rows with collapsed state, but had " + (sheet.LastRowNum - sheet.FirstRowNum + 1) + " rows ("
|
|
+ sheet.FirstRowNum + "-" + sheet.LastRowNum + ")");
|
|
for (int i = sheet.FirstRowNum; i < sheet.LastRowNum; i++)
|
|
{
|
|
if (collapsed[i - sheet.FirstRowNum] == null)
|
|
{
|
|
continue;
|
|
}
|
|
XSSFRow row = (XSSFRow)sheet.GetRow(i);
|
|
Assert.IsNotNull(row, "Could not read row " + i);
|
|
Assert.IsNotNull(row.GetCTRow(), "Could not read row " + i);
|
|
Assert.AreEqual(collapsed[i - sheet.FirstRowNum], row.GetCTRow().collapsed, "Row: " + i + ": collapsed");
|
|
Assert.AreEqual(hidden[i - sheet.FirstRowNum], row.GetCTRow().hidden, "Row: " + i + ": hidden");
|
|
|
|
Assert.AreEqual(outlineLevel[i - sheet.FirstRowNum], row.GetCTRow().outlineLevel, "Row: " + i + ": level");
|
|
}
|
|
|
|
WriteToFile(wb);
|
|
}
|
|
private void CheckWorkbookGrouping(IWorkbook wb, bool?[] collapsed, bool[] hidden, int[] outlineLevel)
|
|
{
|
|
printWorkbook(wb);
|
|
ISheet sheet = wb.GetSheetAt(0);
|
|
|
|
Assert.AreEqual(collapsed.Length, hidden.Length);
|
|
Assert.AreEqual(collapsed.Length, outlineLevel.Length);
|
|
Assert.AreEqual(collapsed.Length, sheet.LastRowNum - sheet.FirstRowNum + 1,
|
|
"Expected " + collapsed.Length + " rows with collapsed state, but had " + (sheet.LastRowNum - sheet.FirstRowNum + 1) + " rows ("
|
|
+ sheet.FirstRowNum + "-" + sheet.LastRowNum + ")");
|
|
for (int i = sheet.FirstRowNum; i < sheet.LastRowNum; i++)
|
|
{
|
|
if (collapsed[i - sheet.FirstRowNum] == null)
|
|
{
|
|
continue;
|
|
}
|
|
XSSFRow row = (XSSFRow)sheet.GetRow(i);
|
|
Assert.IsNotNull(row, "Could not read row " + i);
|
|
Assert.IsNotNull(row.GetCTRow(), "Could not read row " + i);
|
|
Assert.AreEqual(collapsed[i - sheet.FirstRowNum], row.GetCTRow().collapsed, "Row: " + i + ": collapsed");
|
|
Assert.AreEqual(hidden[i - sheet.FirstRowNum], row.GetCTRow().hidden, "Row: " + i + ": hidden");
|
|
|
|
Assert.AreEqual(outlineLevel[i - sheet.FirstRowNum], row.GetCTRow().outlineLevel, "Row: " + i + ": level");
|
|
}
|
|
|
|
WriteToFile(wb);
|
|
}
|
|
|
|
[Test]
|
|
public void Test55640working()
|
|
{
|
|
IWorkbook wb = new XSSFWorkbook();
|
|
ISheet sheet = wb.CreateSheet("sheet123");
|
|
|
|
sheet.GroupRow(1, 4);
|
|
sheet.GroupRow(2, 5);
|
|
sheet.GroupRow(3, 6);
|
|
|
|
sheet.SetRowGroupCollapsed(1, true);
|
|
sheet.SetRowGroupCollapsed(2, false);
|
|
sheet.SetRowGroupCollapsed(3, false);
|
|
|
|
WriteToFile(wb);
|
|
}
|
|
|
|
// just used for printing out contents of spreadsheets
|
|
[Test]
|
|
public void Test55640printSample()
|
|
{
|
|
XSSFWorkbook wb = XSSFTestDataSamples.OpenSampleWorkbook("55640.xlsx");
|
|
printWorkbook(wb);
|
|
|
|
wb = XSSFTestDataSamples.OpenSampleWorkbook("GroupTest.xlsx");
|
|
printWorkbook(wb);
|
|
}
|
|
|
|
private void printWorkbook(IWorkbook wb)
|
|
{
|
|
// disable all output for now...
|
|
// ISheet sheet = wb.GetSheetAt(0);
|
|
//
|
|
// for(Iterator<Row> it = sheet.RowIterator();it.HasNext();) {
|
|
// XSSFRow row = (XSSFRow) it.Next();
|
|
// bool collapsed = row.CTRow.Collapsed;
|
|
// bool hidden = row.CTRow.Hidden;
|
|
// short level = row.CTRow.OutlineLevel;
|
|
//
|
|
// System.out.Println("Row: " + row.RowNum + ": Level: " + level + " Collapsed: " + collapsed + " Hidden: " + hidden);
|
|
// }
|
|
}
|
|
|
|
[Test]
|
|
public void TestGroupingTest()
|
|
{
|
|
XSSFWorkbook wb = XSSFTestDataSamples.OpenSampleWorkbook("GroupTest.xlsx");
|
|
|
|
Assert.AreEqual(31, wb.GetSheetAt(0).LastRowNum);
|
|
|
|
// NOTE: This is currently based on current behavior of POI, somehow
|
|
// what POI returns in the calls to collapsed/hidden is not fully matching
|
|
// the examples in the spec or I did not fully understand how POI stores the data internally...
|
|
CheckWorkbookGrouping(wb,
|
|
new bool?[] {
|
|
// 0-4
|
|
false, false, false, false, false, null, null,
|
|
// 7-11
|
|
false, false, true, true, true, null, null,
|
|
// 14-18
|
|
false, false, true, false, false, null,
|
|
// 20-24
|
|
false, false, true, true, false, null, null,
|
|
// 27-31
|
|
false, false, false, true, false },
|
|
new bool[] {
|
|
// 0-4
|
|
false, false, false, false, false, false, false,
|
|
// 7-11
|
|
true, true, true, true, false, false, false,
|
|
// 14-18
|
|
true, true, false, false, false, false,
|
|
// 20-24
|
|
true, true, true, false, false, false, false,
|
|
// 27-31
|
|
true, true, true, true, false },
|
|
// outlineLevel
|
|
new int[] {
|
|
// 0-4
|
|
3, 3, 2, 1, 0, 0, 0,
|
|
// 7-11
|
|
3, 3, 2, 1, 0, 0, 0,
|
|
// 14-18
|
|
3, 3, 2, 1, 0, 0,
|
|
// 20-24
|
|
3, 3, 2, 1, 0, 0, 0,
|
|
// 27-31
|
|
3, 3, 2, 1, 0,
|
|
}
|
|
);
|
|
/*
|
|
Row: 0: Level: 3 Collapsed: false Hidden: false
|
|
Row: 1: Level: 3 Collapsed: false Hidden: false
|
|
Row: 2: Level: 2 Collapsed: false Hidden: false
|
|
Row: 3: Level: 1 Collapsed: false Hidden: false
|
|
Row: 4: Level: 0 Collapsed: false Hidden: false
|
|
Row: 7: Level: 3 Collapsed: false Hidden: true
|
|
Row: 8: Level: 3 Collapsed: false Hidden: true
|
|
Row: 9: Level: 2 Collapsed: true Hidden: true
|
|
Row: 10: Level: 1 Collapsed: true Hidden: true
|
|
Row: 11: Level: 0 Collapsed: true Hidden: false
|
|
Row: 14: Level: 3 Collapsed: false Hidden: true
|
|
Row: 15: Level: 3 Collapsed: false Hidden: true
|
|
Row: 16: Level: 2 Collapsed: true Hidden: false
|
|
Row: 17: Level: 1 Collapsed: false Hidden: false
|
|
Row: 18: Level: 0 Collapsed: false Hidden: false
|
|
Row: 20: Level: 3 Collapsed: false Hidden: true
|
|
Row: 21: Level: 3 Collapsed: false Hidden: true
|
|
Row: 22: Level: 2 Collapsed: true Hidden: true
|
|
Row: 23: Level: 1 Collapsed: true Hidden: false
|
|
Row: 24: Level: 0 Collapsed: false Hidden: false
|
|
Row: 27: Level: 3 Collapsed: false Hidden: true
|
|
Row: 28: Level: 3 Collapsed: false Hidden: true
|
|
Row: 29: Level: 2 Collapsed: false Hidden: true
|
|
Row: 30: Level: 1 Collapsed: true Hidden: true
|
|
Row: 31: Level: 0 Collapsed: true Hidden: false
|
|
*/
|
|
}
|
|
}
|
|
}
|