如何使用Apache Java POI在MS Excel中插入表格。

4

我正在尝试使用Java Apache Poi在Excel中插入表格。但是当我打开xlsx文件时,它会抛出以下错误,并且我无法解决它:

Removed Part: /xl/tables/table1.xml part with XML error. (Table) Load error. Line 2
repaired records: table from /xl/tables/table1.xml part (table)

我的代码如下:

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFTable;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTable;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTableColumn;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTableColumns;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTableStyleInfo;

public class Test {

  public static void main(String[] args) throws FileNotFoundException, IOException {
    XSSFWorkbook workbook = new XSSFWorkbook();
    XSSFSheet sheet = workbook.createSheet("Architecture");

    XSSFTable table = sheet.createTable();
    CTTable cttable = table.getCTTable();


    cttable.setDisplayName("Table1");
    cttable.setId(1);
    cttable.setName("Test");
    cttable.setRef("A1:C11");
    cttable.setTotalsRowShown(false);

    CTTableStyleInfo styleInfo = cttable.addNewTableStyleInfo();
    styleInfo.setShowColumnStripes(false);
    styleInfo.setShowRowStripes(true);


    CTTableColumns columns = cttable.addNewTableColumns();
    columns.setCount(3);
    for (int i = 1; i <= 3; i++) {
      CTTableColumn column = columns.addNewTableColumn();
      column.setId(i);
      column.setName("Column" + i);
    }

    try (FileOutputStream outputStream = new FileOutputStream("C:\\Office\\TimeSheet\\JavaBooks.xlsx")) {
      workbook.write(outputStream);
    }
  }
}

如何使用Apache Java Poi在Microsoft Excel中插入表格?

1
尝试升级到最新版本的Apache POI? - Gagravarr
我正在使用最新的Apache POI 3.17。 - Raj Perumalsamy
3个回答

10
在表格列名中,至少必须有单元格内容。在您的情况下,工作表Architecture中的单元格A1:C1必须具有内容。在以前的版本中,apache poi要求此内容必须与表格列名匹配。在当前版本中,设置单元格内容将更新表格列名。
您的代码已扩展以正常工作:
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFTable;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTable;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTableColumn;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTableColumns;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTableStyleInfo;

public class ExcelTableTest {

  public static void main(String[] args) throws FileNotFoundException, IOException {
    XSSFWorkbook workbook = new XSSFWorkbook();
    XSSFSheet sheet = workbook.createSheet("Architecture");

    XSSFTable table = sheet.createTable();
    //XSSFTable table = sheet.createTable(null); //since apache poi 4.0.0
    CTTable cttable = table.getCTTable();

    cttable.setDisplayName("Table1");
    cttable.setId(1);
    cttable.setName("Test");
    cttable.setRef("A1:C11");
    cttable.setTotalsRowShown(false);

    CTTableStyleInfo styleInfo = cttable.addNewTableStyleInfo();
    styleInfo.setName("TableStyleMedium2");
    styleInfo.setShowColumnStripes(false);
    styleInfo.setShowRowStripes(true);

    CTTableColumns columns = cttable.addNewTableColumns();
    columns.setCount(3);
    for (int i = 1; i <= 3; i++) {
      CTTableColumn column = columns.addNewTableColumn();
      column.setId(i);
      column.setName("Column" + i);
    }

    for (int r = 0; r < 2; r++) {
      XSSFRow row = sheet.createRow(r);
      for(int c = 0; c < 3; c++) {
        XSSFCell cell = row.createCell(c);
        if(r == 0) { //first row is for column headers
          cell.setCellValue("Column"+ (c+1)); //content **must** be here for table column names
        } else {
          //cell.setCellValue("Data R"+ (r+1) + "C" + (c+1));
        }
      }
    }    

    try (FileOutputStream outputStream = new FileOutputStream("ExcelTableTest.xlsx")) {
      workbook.write(outputStream);
    }
  }
}

这可以在旧版的HSSF工作簿中完成吗?我一直没有找到方法 :( - MattWeiler
1
@MattWeiler:目前使用apache poi不可能实现。只有XSSFTable实现了Table。到目前为止还没有HSSFTable - Axel Richter
感谢提供的信息。 这是说apache poi不支持还是.xls格式不支持? 当我使用Excel插入表格来包装数据并保存为.xls格式时,它看起来与使用.xlsx格式相同。 这是否意味着.xls格式支持表格或者Excel只是对单元格/行应用样式,使它们在.xlsx格式中看起来像表格? - MattWeiler
1
@MattWeiler:二进制的*.xls BIFF格式也支持表格(又称ListObject)。但是,目前为止apache poi没有提供任何处理它们的类。 - Axel Richter
谢谢,那很有道理。所以我想如果用户选择生成.xls文件,我只需应用单元格/行样式,如果用户选择生成.xlsx文件,则应用适当的table - MattWeiler

3

如果在打开文件时出现Excel错误......请删除包含XML错误的部分:t / xl / tables / table1.xml。

似乎是由table1.xml中的重复表/表列部分引起的。

可以通过稍微不同的列名称创建/设置来解决。

       for (int i = 0; i <= REPORT_COL_COUNT; i++) {
           String colName = sh.getRow(FIRST_DATA_ROW-1).getCell(i).getStringCellValue();
           CTTableColumn column = columns.getTableColumnArray(i);
           column.setName(colName);
       }       

使用poi 5.2.2进行测试


你能否提供一个完整的例子?因为我尝试了我写的内容,但并没有帮助。 - undefined

0

除了“Axel Richter”之外,我还需要添加自动筛选器。当我使用ZipArchiv软件打开Excel时,我意识到这一点。

这是我使用的代码:

private void createCTTable(XSSFTable table)
{
   cttable = table.getCTTable();
   cttable.setDisplayName("Tabelle1");
   cttable.setId(1);
   cttable.setName("Test");
   cttable.setTotalsRowShown(false);
   AreaReference my_data_range = new AreaReference(new CellReference(0, 0),
         new CellReference(rowVectors.size(), header.length - 1), SpreadsheetVersion.EXCEL2007);
   cttable.setRef(my_data_range.formatAsString());
   CTAutoFilter autofilter = cttable.addNewAutoFilter();
   autofilter.setRef(my_data_range.formatAsString());
}

'header' 是一个包含字符串的数组,而 'rowVectors' 则是一个对象集合,其中包含表格数据主体的值。
我使用 Apache Poi 4.1.1。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接