[bug-60541] fix issue with setColumnAttributes

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1897678 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
PJ Fanning 2022-02-01 23:05:54 +00:00
parent ddeb98816e
commit f16b36cc51
4 changed files with 280 additions and 67 deletions

View File

@ -1600,6 +1600,7 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet, OoxmlSheetEx
public void groupColumn(int fromColumn, int toColumn) {
groupColumn1Based(fromColumn+1, toColumn+1);
}
private void groupColumn1Based(int fromColumn, int toColumn) {
CTCols ctCols=worksheet.getColsArray(0);
CTCol ctCol=CTCol.Factory.newInstance();
@ -2314,7 +2315,7 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet, OoxmlSheetEx
CTCol col = columnHelper.getColumn(columnIndex, false);
int colInfoIx = columnHelper.getIndexOfColumn(cols, col);
int idx = findColInfoIdx(Math.toIntExact(col.getMax()), colInfoIx);
int idx = col == null ? -1 : findColInfoIdx(Math.toIntExact(col.getMax()), colInfoIx);
if (idx == -1) {
return;
}
@ -2329,7 +2330,7 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet, OoxmlSheetEx
int endIdx = findEndOfColumnOutlineGroup(idx);
// expand:
// colapsed bit must be unset
// collapsed bit must be unset
// hidden bit gets unset _if_ surrounding groups are expanded you can
// determine
// this by looking at the hidden bit of the enclosing group. You will

View File

@ -255,7 +255,6 @@ public class ColumnHelper {
if(fromCol.isSetCollapsed()) toCol.setCollapsed(fromCol.getCollapsed());
if(fromCol.isSetPhonetic()) toCol.setPhonetic(fromCol.getPhonetic());
if(fromCol.isSetOutlineLevel()) toCol.setOutlineLevel(fromCol.getOutlineLevel());
toCol.setCollapsed(fromCol.isSetCollapsed());
}
public void setColBestFit(long index, boolean bestFit) {

View File

@ -45,6 +45,7 @@ import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
import org.apache.commons.io.output.UnsynchronizedByteArrayOutputStream;
import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.ooxml.POIXMLException;
import org.apache.poi.poifs.crypt.CryptoFunctions;
@ -329,7 +330,7 @@ public final class TestXSSFSheet extends BaseTestXSheet {
sheet.removeMergedRegion(0);
assertEquals(0, sheet.getNumMergedRegions());
assertNull(sheet.getCTWorksheet().getMergeCells(),
"CTMergeCells should be deleted after removing the last merged region on the sheet.");
"CTMergeCells should be deleted after removing the last merged region on the sheet.");
assertEquals(0, sheet.addMergedRegion(region_1));
assertEquals(1, sheet.addMergedRegion(region_2));
assertEquals(2, sheet.addMergedRegion(region_3));
@ -370,6 +371,195 @@ public final class TestXSSFSheet extends BaseTestXSheet {
}
}
@Test
void saveGroupColumns() throws IOException {
try (
XSSFWorkbook workbook = new XSSFWorkbook();
UnsynchronizedByteArrayOutputStream bos = new UnsynchronizedByteArrayOutputStream()
) {
XSSFSheet sheet = workbook.createSheet();
XSSFRow row0 = sheet.createRow(0);
XSSFRow row1 = sheet.createRow(1);
for (int i = 0; i < 8; i++) {
XSSFCell cell0 = row0.createCell(i);
cell0.setCellValue("Col" + CellReference.convertNumToColString(cell0.getColumnIndex()));
XSSFCell cell1 = row1.createCell(i);
cell1.setCellValue(cell1.getAddress().formatAsString());
}
sheet.groupColumn(2, 3);
sheet.groupColumn(5, 7);
workbook.write(bos);
try (XSSFWorkbook wb2 = new XSSFWorkbook(bos.toInputStream())) {
XSSFSheet wb2Sheet = wb2.getSheetAt(0);
CTCols cols = wb2Sheet.getCTWorksheet().getColsArray(0);
assertEquals(2, cols.sizeOfColArray());
CTCol col0 = cols.getColArray(0);
CTCol col1 = cols.getColArray(1);
assertEquals(3, col0.getMin());
assertEquals(4, col0.getMax());
assertFalse(col0.getHidden());
assertFalse(col0.getCollapsed());
assertEquals(6, col1.getMin());
assertEquals(8, col1.getMax());
assertFalse(col1.getHidden());
assertFalse(col1.getCollapsed());
}
}
}
@Test
void collapseGroupColumn() throws IOException {
try (XSSFWorkbook workbook = new XSSFWorkbook()) {
XSSFSheet sheet = workbook.createSheet();
XSSFRow row0 = sheet.createRow(0);
XSSFRow row1 = sheet.createRow(1);
for (int i = 0; i < 8; i++) {
XSSFCell cell0 = row0.createCell(i);
cell0.setCellValue("Col" + CellReference.convertNumToColString(cell0.getColumnIndex()));
XSSFCell cell1 = row1.createCell(i);
cell1.setCellValue(cell1.getAddress().formatAsString());
}
sheet.groupColumn(2, 3);
sheet.groupColumn(5, 7);
CTCols cols = sheet.getCTWorksheet().getColsArray(0);
assertEquals(2, cols.sizeOfColArray());
CTCol col0 = cols.getColArray(0);
CTCol col1 = cols.getColArray(1);
assertEquals(3, col0.getMin());
assertEquals(4, col0.getMax());
assertFalse(col0.getHidden());
assertFalse(col0.getCollapsed());
assertEquals(6, col1.getMin());
assertEquals(8, col1.getMax());
assertFalse(col1.getHidden());
assertFalse(col1.getCollapsed());
sheet.setColumnGroupCollapsed(3, true);
cols = sheet.getCTWorksheet().getColsArray(0);
assertEquals(3, cols.sizeOfColArray());
col0 = cols.getColArray(0);
col1 = cols.getColArray(1);
CTCol col2 = cols.getColArray(2);
assertEquals(3, col0.getMin());
assertEquals(4, col0.getMax());
assertTrue(col0.getHidden());
assertFalse(col0.getCollapsed());
assertEquals(5, col1.getMin());
assertEquals(5, col1.getMax());
assertFalse(col1.getHidden());
assertTrue(col1.getCollapsed());
assertEquals(6, col2.getMin());
assertEquals(8, col2.getMax());
assertFalse(col2.getHidden());
assertFalse(col2.getCollapsed());
}
}
@Test
void expandGroupColumn() throws IOException {
try (XSSFWorkbook workbook = new XSSFWorkbook()) {
XSSFSheet sheet = workbook.createSheet();
XSSFRow row0 = sheet.createRow(0);
XSSFRow row1 = sheet.createRow(1);
for (int i = 0; i < 8; i++) {
XSSFCell cell0 = row0.createCell(i);
cell0.setCellValue("Col" + CellReference.convertNumToColString(cell0.getColumnIndex()));
XSSFCell cell1 = row1.createCell(i);
cell1.setCellValue(cell1.getAddress().formatAsString());
}
sheet.groupColumn(2, 3);
sheet.groupColumn(5, 7);
sheet.setColumnGroupCollapsed(3, true);
CTCols cols = sheet.getCTWorksheet().getColsArray(0);
assertEquals(3, cols.sizeOfColArray());
CTCol col0 = cols.getColArray(0);
CTCol col1 = cols.getColArray(1);
CTCol col2 = cols.getColArray(2);
assertEquals(3, col0.getMin());
assertEquals(4, col0.getMax());
assertTrue(col0.getHidden());
assertFalse(col0.getCollapsed());
assertEquals(5, col1.getMin());
assertEquals(5, col1.getMax());
assertFalse(col1.getHidden());
assertTrue(col1.getCollapsed());
assertEquals(6, col2.getMin());
assertEquals(8, col2.getMax());
assertFalse(col2.getHidden());
assertFalse(col2.getCollapsed());
sheet.setColumnGroupCollapsed(3, false);
cols = sheet.getCTWorksheet().getColsArray(0);
assertEquals(3, cols.sizeOfColArray());
col0 = cols.getColArray(0);
col1 = cols.getColArray(1);
col2 = cols.getColArray(2);
assertEquals(3, col0.getMin());
assertEquals(4, col0.getMax());
assertFalse(col0.getHidden());
assertFalse(col0.getCollapsed());
assertEquals(5, col1.getMin());
assertEquals(5, col1.getMax());
assertFalse(col1.getHidden());
assertFalse(col1.getCollapsed());
assertEquals(6, col2.getMin());
assertEquals(8, col2.getMax());
assertFalse(col2.getHidden());
assertFalse(col2.getCollapsed());
}
}
@Test
void collapseNonExistentGroupColumn() throws IOException {
try (XSSFWorkbook workbook = new XSSFWorkbook()) {
XSSFSheet sheet = workbook.createSheet();
XSSFRow row0 = sheet.createRow(0);
XSSFRow row1 = sheet.createRow(1);
for (int i = 0; i < 8; i++) {
XSSFCell cell0 = row0.createCell(i);
cell0.setCellValue("Col" + CellReference.convertNumToColString(cell0.getColumnIndex()));
XSSFCell cell1 = row1.createCell(i);
cell1.setCellValue(cell1.getAddress().formatAsString());
}
sheet.groupColumn(2, 3);
sheet.groupColumn(5, 7);
CTCols cols = sheet.getCTWorksheet().getColsArray(0);
assertEquals(2, cols.sizeOfColArray());
CTCol col0 = cols.getColArray(0);
CTCol col1 = cols.getColArray(1);
assertEquals(3, col0.getMin());
assertEquals(4, col0.getMax());
assertFalse(col0.getHidden());
assertFalse(col0.getCollapsed());
assertEquals(6, col1.getMin());
assertEquals(8, col1.getMax());
assertFalse(col1.getHidden());
assertFalse(col1.getCollapsed());
sheet.setColumnGroupCollapsed(4, true); //has no effect, col 4 is not in a group
cols = sheet.getCTWorksheet().getColsArray(0);
assertEquals(2, cols.sizeOfColArray());
col0 = cols.getColArray(0);
col1 = cols.getColArray(1);
assertEquals(3, col0.getMin());
assertEquals(4, col0.getMax());
assertFalse(col0.getHidden());
assertFalse(col0.getCollapsed());
assertEquals(6, col1.getMin());
assertEquals(8, col1.getMax());
assertFalse(col1.getHidden());
assertFalse(col1.getCollapsed());
}
}
@Test
void groupUngroupColumn() throws IOException {
@ -486,28 +676,29 @@ public final class TestXSSFSheet extends BaseTestXSheet {
sheet1.groupColumn(4, 7);
assertEquals(1, cols.sizeOfColArray());
checkColumnGroup(cols.getColArray(0), 4, 7); // false, true
checkColumnGroup(cols.getColArray(0), 4, 7, false, false);
sheet1.groupColumn(9, 12);
assertEquals(2, cols.sizeOfColArray());
checkColumnGroup(cols.getColArray(0), 4, 7); // false, true
checkColumnGroup(cols.getColArray(1), 9, 12); // false, true
checkColumnGroup(cols.getColArray(0), 4, 7, false, false);
checkColumnGroup(cols.getColArray(1), 9, 12, false, false);
sheet1.groupColumn(10, 11);
assertEquals(4, cols.sizeOfColArray());
checkColumnGroup(cols.getColArray(0), 4, 7); // false, true
checkColumnGroup(cols.getColArray(1), 9, 9); // false, true
checkColumnGroup(cols.getColArray(2), 10, 11); // false, true
checkColumnGroup(cols.getColArray(3), 12, 12); // false, true
checkColumnGroup(cols.getColArray(0), 4, 7, false, false);
checkColumnGroup(cols.getColArray(1), 9, 9, false, false);
checkColumnGroup(cols.getColArray(2), 10, 11, false, false);
checkColumnGroup(cols.getColArray(3), 12, 12, false, false);
// collapse columns - 1
sheet1.setColumnGroupCollapsed(5, true);
// FIXME: we grew a column?
//TODO setColumnGroupCollapsed is currently broken (and may never have worked well)
// FIXME: we grew a column? -- this whole section needs investigation
assertEquals(5, cols.sizeOfColArray());
checkColumnGroupIsCollapsed(cols.getColArray(0), 4, 7); // true, true
checkColumnGroupIsCollapsed(cols.getColArray(0), 4, 7);
checkColumnGroup(cols.getColArray(1), 8, 8); // false, true
checkColumnGroup(cols.getColArray(2), 9, 9); // false, true
checkColumnGroup(cols.getColArray(3), 10, 11); // false, true
@ -518,22 +709,22 @@ public final class TestXSSFSheet extends BaseTestXSheet {
sheet1.setColumnGroupCollapsed(5, false);
assertEquals(5, cols.sizeOfColArray());
checkColumnGroupIsExpanded(cols.getColArray(0), 4, 7); // false, true
checkColumnGroupIsExpanded(cols.getColArray(0), 4, 7);
checkColumnGroup(cols.getColArray(1), 8, 8, false, false);
checkColumnGroup(cols.getColArray(2), 9, 9); // false, true
checkColumnGroup(cols.getColArray(3), 10, 11); // false, true
checkColumnGroup(cols.getColArray(4), 12, 12); // false, true
checkColumnGroup(cols.getColArray(2), 9, 9, false, false);
checkColumnGroup(cols.getColArray(3), 10, 11, false, false);
checkColumnGroup(cols.getColArray(4), 12, 12, false, false);
//collapse - 2
sheet1.setColumnGroupCollapsed(9, true);
// it grew again?
assertEquals(6, cols.sizeOfColArray());
checkColumnGroup(cols.getColArray(0), 4, 7); // false, true
checkColumnGroup(cols.getColArray(0), 4, 7, false, false);
checkColumnGroup(cols.getColArray(1), 8, 8, false, false);
checkColumnGroupIsCollapsed(cols.getColArray(2), 9, 9); // true, true
checkColumnGroupIsCollapsed(cols.getColArray(3), 10, 11); // true, true
checkColumnGroupIsCollapsed(cols.getColArray(4), 12, 12); // true, true
checkColumnGroupIsCollapsed(cols.getColArray(2), 9, 9); // true, true);
checkColumnGroupIsCollapsed(cols.getColArray(3), 10, 11); // true, true);
checkColumnGroupIsCollapsed(cols.getColArray(4), 12, 12); // true, true);
// why was this column group added?
checkColumnGroup(cols.getColArray(5), 13, 13); // false, true
@ -579,12 +770,12 @@ public final class TestXSSFSheet extends BaseTestXSheet {
cols = sheet1.getCTWorksheet().getColsArray(0);
assertEquals(6, cols.sizeOfColArray());
checkColumnGroup(cols.getColArray(0), 4, 7, false, true);
checkColumnGroup(cols.getColArray(1), 8, 8, false, true);
checkColumnGroup(cols.getColArray(2), 9, 9, false, true);
checkColumnGroup(cols.getColArray(3), 10, 11, false, true);
checkColumnGroup(cols.getColArray(4), 12, 12, false, true);
checkColumnGroup(cols.getColArray(5), 13, 13, false, true);
checkColumnGroup(cols.getColArray(0), 4, 7, false, false);
checkColumnGroup(cols.getColArray(1), 8, 8, false, false);
checkColumnGroup(cols.getColArray(2), 9, 9, false, false);
checkColumnGroup(cols.getColArray(3), 10, 11, false, false);
checkColumnGroup(cols.getColArray(4), 12, 12, false, false);
checkColumnGroup(cols.getColArray(5), 13, 13, false, false);
}
}
}
@ -600,8 +791,7 @@ public final class TestXSSFSheet extends BaseTestXSheet {
private static void checkColumnGroup(
CTCol col,
int fromColumnIndex, int toColumnIndex,
boolean isSetHidden, boolean isSetCollapsed
) {
boolean isSetHidden, boolean isSetCollapsed) {
assertEquals(fromColumnIndex, col.getMin() - 1, "from column index"); // 1 based
assertEquals(toColumnIndex, col.getMax() - 1, "to column index"); // 1 based
assertEquals(isSetHidden, col.isSetHidden(), "isSetHidden");
@ -619,7 +809,6 @@ public final class TestXSSFSheet extends BaseTestXSheet {
assertEquals(fromColumnIndex, col.getMin() - 1, "from column index"); // 1 based
assertEquals(toColumnIndex, col.getMax() - 1, "to column index"); // 1 based
assertFalse(col.isSetHidden(), "isSetHidden");
assertTrue(col.isSetCollapsed(), "isSetCollapsed"); //not necessarily set
}
/**
@ -630,11 +819,25 @@ public final class TestXSSFSheet extends BaseTestXSheet {
* @param toColumnIndex 0-indexed
*/
private static void checkColumnGroupIsCollapsed(CTCol col, int fromColumnIndex, int toColumnIndex) {
checkColumnGroupIsCollapsed(col, fromColumnIndex, toColumnIndex, false, false);
}
/**
* Verify that column groups were created correctly after Sheet.groupColumn
*
* @param col the column group xml bean
* @param fromColumnIndex 0-indexed
* @param toColumnIndex 0-indexed
*/
private static void checkColumnGroupIsCollapsed(CTCol col, int fromColumnIndex, int toColumnIndex,
boolean isSetCollapsed, boolean collapsed) {
assertEquals(fromColumnIndex, col.getMin() - 1, "from column index"); // 1 based
assertEquals(toColumnIndex, col.getMax() - 1, "to column index"); // 1 based
assertTrue(col.isSetHidden(), "isSetHidden");
assertTrue(col.isSetCollapsed(), "isSetCollapsed");
//assertTrue(col.getCollapsed(), "getCollapsed");
assertEquals(isSetCollapsed, col.isSetCollapsed(), "isSetCollapsed");
if (isSetCollapsed) {
assertEquals(collapsed, col.getCollapsed(), "getCollapsed");
}
}
/**
@ -649,9 +852,7 @@ public final class TestXSSFSheet extends BaseTestXSheet {
assertEquals(fromColumnIndex, col.getMin() - 1, "from column index"); // 1 based
assertEquals(toColumnIndex, col.getMax() - 1, "to column index"); // 1 based
assertFalse(col.isSetHidden(), "isSetHidden");
assertTrue(col.isSetCollapsed(), "isSetCollapsed");
//assertTrue(!col.isSetCollapsed() || !col.getCollapsed(), "isSetCollapsed");
//assertFalse(col.getCollapsed(), "getCollapsed");
assertTrue(!col.isSetCollapsed() || !col.getCollapsed(), "isSetCollapsed");
}
/**
@ -1202,13 +1403,13 @@ public final class TestXSSFSheet extends BaseTestXSheet {
@ParameterizedTest
@CsvSource(value = {
// run with the file provided in the Bug-Report
"54607.xlsx, '1, 0, 0', '0, 0, 0'",
// run with the file provided in the Bug-Report
"54607.xlsx, '1, 0, 0', '0, 0, 0'",
// run with some other flie to see
"54436.xlsx, '0', '0'",
"TwoSheetsNoneHidden.xlsx, '0, 0', '0, 0'",
"TwoSheetsNoneHidden.xls, '0, 0', '0, 0'"
// run with some other flie to see
"54436.xlsx, '0', '0'",
"TwoSheetsNoneHidden.xlsx, '0, 0', '0, 0'",
"TwoSheetsNoneHidden.xls, '0, 0', '0, 0'"
})
void bug54607(String file, String topRows, String leftCols) throws IOException {
Consumer<Workbook> testFun = (wb) -> {
@ -1219,8 +1420,8 @@ public final class TestXSSFSheet extends BaseTestXSheet {
wb.forEach(sh -> assertNotNull(sh.getSheetName()));
String act = StreamSupport.stream(Spliterators.spliterator(wb.iterator(), wb.getNumberOfSheets(), Spliterator.ORDERED), false).
map(sh -> sheetFun.apply(sh).toString()).
collect(Collectors.joining(", "));
map(sh -> sheetFun.apply(sh).toString()).
collect(Collectors.joining(", "));
assertEquals(exp, act);
}

View File

@ -25,11 +25,13 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.IOException;
import jdk.nashorn.internal.ir.annotations.Ignore;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.model.StylesTable;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.junit.jupiter.api.Test;
@ -408,33 +410,43 @@ public final class TestColumnHelper {
@SuppressWarnings("deprecation")
@Test
void testColumnsCollapsed() {
Workbook wb = new XSSFWorkbook();
Sheet sheet = wb.createSheet("test");
Row row = sheet.createRow(0);
row.createCell(0);
row.createCell(1);
row.createCell(2);
void testColumnsCollapsed() throws IOException {
try (XSSFWorkbook wb = new XSSFWorkbook()) {
XSSFSheet sheet = wb.createSheet("test");
XSSFRow row = sheet.createRow(0);
row.createCell(0);
row.createCell(1);
row.createCell(2);
sheet.setColumnWidth(0, 10);
sheet.setColumnWidth(1, 10);
sheet.setColumnWidth(2, 10);
sheet.setColumnWidth(0, 10);
sheet.setColumnWidth(1, 10);
sheet.setColumnWidth(2, 10);
sheet.groupColumn(0, 1);
sheet.setColumnGroupCollapsed(0, true);
CTCols ctCols = sheet.getCTWorksheet().getColsArray()[0];
CTCol col0 = ctCols.getColArray(0);
CTCol col1 = ctCols.getColArray(1);
CTCol col2 = ctCols.getColArray(2);
assertFalse(col0.getCollapsed());
assertFalse(col0.getHidden());
assertFalse(col1.getCollapsed());
assertFalse(col1.getHidden());
assertFalse(col2.getCollapsed());
assertFalse(col2.getHidden());
CTCols ctCols = ((XSSFSheet) sheet).getCTWorksheet().getColsArray()[0];
assertEquals(3, ctCols.sizeOfColArray());
assertTrue(ctCols.getColArray(0).isSetCollapsed());
assertTrue(ctCols.getColArray(1).isSetCollapsed());
assertTrue(ctCols.getColArray(2).isSetCollapsed());
sheet.groupColumn(0, 1);
sheet.setColumnGroupCollapsed(0, true);
ColumnHelper helper = new ColumnHelper(CTWorksheet.Factory.newInstance());
helper.setColumnAttributes(ctCols.getColArray(1), ctCols.getColArray(2));
ctCols = ((XSSFSheet) sheet).getCTWorksheet().getColsArray()[0];
assertTrue(ctCols.getColArray(0).isSetCollapsed());
assertTrue(ctCols.getColArray(1).isSetCollapsed());
assertTrue(ctCols.getColArray(2).isSetCollapsed());
ctCols = sheet.getCTWorksheet().getColsArray()[0];
assertEquals(3, ctCols.sizeOfColArray());
col0 = ctCols.getColArray(0);
col1 = ctCols.getColArray(1);
col2 = ctCols.getColArray(2);
assertFalse(col0.getCollapsed());
assertTrue(col0.getHidden());
assertFalse(col1.getCollapsed());
assertTrue(col1.getHidden());
assertTrue(col2.getCollapsed());
assertFalse(col2.getHidden());
}
}
}