From 2bde35b8ffd1d63db701a69a95ace4462cc711a3 Mon Sep 17 00:00:00 2001 From: Nick Burch Date: Wed, 21 May 2014 17:08:25 +0000 Subject: [PATCH] Patch from Yaniv Kunda from bug #56274 - Fix SXSSF writing of tables when creating from a template git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1596624 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/poi/xssf/usermodel/XSSFTable.java | 14 ++-- .../xssf/usermodel/AllXSSFUsermodelTests.java | 1 + .../poi/xssf/usermodel/TestXSSFTable.java | 73 ++++++++++++++++++ test-data/spreadsheet/56274.xlsx | Bin 0 -> 12782 bytes 4 files changed, 82 insertions(+), 6 deletions(-) create mode 100644 src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFTable.java create mode 100644 test-data/spreadsheet/56274.xlsx diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFTable.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFTable.java index 4f71c2d8c..9d7e4e77b 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFTable.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFTable.java @@ -294,13 +294,15 @@ public class XSSFTable extends POIXMLDocumentPart { int firstHeaderColumn = ref.getCol(); XSSFRow row = sheet.getRow(headerRow); - if(row != null) for(CTTableColumn col : getCTTable().getTableColumns().getTableColumnList()){ - int colIdx = (int)col.getId() - 1 + firstHeaderColumn; - XSSFCell cell = row.getCell(colIdx); - if(cell != null) { - col.setName(cell.getStringCellValue()); + if (row != null && row.getCTRow().validate()) { + int cellnum = firstHeaderColumn; + for (CTTableColumn col : getCTTable().getTableColumns().getTableColumnList()) { + XSSFCell cell = row.getCell(cellnum); + if (cell != null) { + col.setName(cell.getStringCellValue()); + } + cellnum++; } } - } } diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/AllXSSFUsermodelTests.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/AllXSSFUsermodelTests.java index 11308159b..e05b2f9a1 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/AllXSSFUsermodelTests.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/AllXSSFUsermodelTests.java @@ -50,6 +50,7 @@ import org.junit.runners.Suite; TestXSSFRow.class, TestXSSFSheet.class, TestXSSFSheetUpdateArrayFormulas.class, + TestXSSFTable.class, TestXSSFWorkbook.class, TestXSSFBorder.class, TestXSSFCellFill.class, diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFTable.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFTable.java new file mode 100644 index 000000000..78e5d80a0 --- /dev/null +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFTable.java @@ -0,0 +1,73 @@ +/* ==================================================================== + 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. +==================================================================== */ + +package org.apache.poi.xssf.usermodel; + +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.xssf.XSSFTestDataSamples; +import org.apache.poi.xssf.streaming.SXSSFWorkbook; +import org.junit.Test; +import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTable; +import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTableColumn; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public final class TestXSSFTable { + + public TestXSSFTable() { + } + + @Test + public void bug56274() throws IOException { + // read sample file + XSSFWorkbook inputWorkbook = XSSFTestDataSamples.openSampleWorkbook("56274.xlsx"); + + // read the original sheet header order + XSSFRow row = inputWorkbook.getSheetAt(0).getRow(0); + List headers = new ArrayList(); + for (Cell cell : row) { + headers.add(cell.getStringCellValue()); + } + + // save the worksheet as-is using SXSSF + File outputFile = File.createTempFile("poi-56274", ".xlsx"); + SXSSFWorkbook outputWorkbook = new org.apache.poi.xssf.streaming.SXSSFWorkbook(inputWorkbook); + outputWorkbook.write(new FileOutputStream(outputFile)); + + // re-read the saved file and make sure headers in the xml are in the original order + inputWorkbook = new org.apache.poi.xssf.usermodel.XSSFWorkbook(new FileInputStream(outputFile)); + CTTable ctTable = inputWorkbook.getSheetAt(0).getTables().get(0).getCTTable(); + List ctTableColumnList = ctTable.getTableColumns().getTableColumnList(); + + assertEquals("number of headers in xml table should match number of header cells in worksheet", + headers.size(), ctTableColumnList.size()); + for (int i = 0; i < headers.size(); i++) { + assertEquals("header name in xml table should match number of header cells in worksheet", + headers.get(i), ctTableColumnList.get(i).getName()); + } + assertTrue(outputFile.delete()); + } + +} \ No newline at end of file diff --git a/test-data/spreadsheet/56274.xlsx b/test-data/spreadsheet/56274.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..8c3573adb3699c54bbc41285212ea6af06ad8db1 GIT binary patch literal 12782 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 literal 0 HcmV?d00001