【问题标题】:Write data in excel(xlsx) sheet having a table在具有表格的 excel(xlsx) 工作表中写入数据
【发布时间】:2015-07-03 04:38:46
【问题描述】:

我正在尝试在已创建表格的 Excel 工作表 (xlsx) 中写入动态数据,基于该表格,我们使用宏在 Excel 本身中绘制图表。

我正在使用 POI 写入数据。

工作表中的表格已设置为 10 行。当我写入超过 10 行的数据时,表格不会展开。因此,绘制的图表仅包含对应于 10 行的数据。

如何写入数据,使数据始终将表格扩展为数据中的行数?

【问题讨论】:

  • 您可能无法添加图片,但如果您将其上传到公共共享文件网站,您可以在问题中包含该图片的 URL。甚至有人可能会编辑您的问题以包含您的图片。

标签: java excel apache-poi xlsx


【解决方案1】:

您应该从sheet.createTable(); 创建一个XSSFTable 对象。

这是我在 http://thinktibits.blogspot.co.il/2014/09/Excel-Insert-Format-Table-Apache-POI-Example.html 找到的一个示例 - 只需确保创建的表涵盖了您在文件中动态放置的所有行/列。

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.*;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.AreaReference;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
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 insertTable
{
  public static void main(String[] args)
    throws FileNotFoundException, IOException
  {
   /* Read the input file that contains the data to be converted to table */
   FileInputStream input_document = new FileInputStream(new File("FormatAsTable.xlsx"));    
   /* Create Workbook */
   XSSFWorkbook my_xlsx_workbook = new XSSFWorkbook(input_document); 
   /* Read worksheet */
   XSSFSheet sheet = my_xlsx_workbook.getSheetAt(0); 
   /* Create Table into Existing Worksheet */
   XSSFTable my_table = sheet.createTable();    
   /* get CTTable object*/
   CTTable cttable = my_table.getCTTable();
   /* Define Styles */    
   CTTableStyleInfo table_style = cttable.addNewTableStyleInfo();
   table_style.setName("TableStyleMedium9");           
   /* Define Style Options */
   table_style.setShowColumnStripes(false); //showColumnStripes=0
   table_style.setShowRowStripes(true); //showRowStripes=1    
   /* Define the data range including headers */
   AreaReference my_data_range = new AreaReference(new CellReference(0, 0), new CellReference(5, 2));    
   /* Set Range to the Table */
   cttable.setRef(my_data_range.formatAsString());
   cttable.setDisplayName("MYTABLE");      /* this is the display name of the table */
   cttable.setName("Test");    /* This maps to "displayName" attribute in <table>, OOXML */            
   cttable.setId(1L); //id attribute against table as long value
   /* Add header columns */               
   CTTableColumns columns = cttable.addNewTableColumns();
   columns.setCount(3L); //define number of columns
   /* Define Header Information for the Table */
    for (int i = 0; i < 3; i++)
    {
    CTTableColumn column = columns.addNewTableColumn();   
    column.setName("Column" + i);      
        column.setId(i+1);
    }   
    /* Write output as File */
    FileOutputStream fileOut = new FileOutputStream("Excel_Format_As_Table.xlsx");
    my_xlsx_workbook.write(fileOut);
    fileOut.close();
  }

【讨论】:

  • 该表实际上存在于我试图将数据写入其中的 excel 工作表中。我希望表格行根据我写入工作表的数据来扩展/减少。我可能需要获取现有表,然后写入数据,根据数据扩展/减少。列将始终保持不变,但行数可以增加/减少。
  • 我不确定您是否可以实际更改表格本身,因为即使在 Excel 本身中,这也是对用户不友好的东西。删除文件中的表(定义)并根据您放入其中的数据重新创建它可能会更好。
  • 那么如何删除表定义呢?我尝试从工作表中删除它,但在 XSSFSheet 工作表中没有找到任何方法。
  • 另外,由于表格已经存在于工作表中,我需要先获取该表格,然后将其删除。 CTTableStyleInfo - 我没有得到这个类来设置条纹样式。
  • POI 实际上提供了删除表的方法—— sheet.getTables().removeAll(sheet.getTables()) ——但它似乎不起作用,所以也许你应该采取查看以下消息 - 有人解释/回答有关向现有表添加列的问题:tinyurl.com/qhf3cfu
【解决方案2】:

虽然这个问题有点过时,但我花了 4 个多小时才弄清楚这一点,所以我认为发布它可能会有所帮助。这会更改现有表,而不是创建新表。

// tell your xssfsheet where its content begins and where it ends
((XSSFWorksheet) sheet).getCTWorksheet().getDimension()
    .setRef("A1:H" + (sheet.getLastRowNum() + 1));

CTTable ctTable = sheet.getTables().get(0).getCTTable();

ctTable.setRef("A1:H" + (sheet.getLastRowNum() + 1)); // adjust reference as needed

ctTable.unsetSortState(); // if you had sorted the data in Excel before reading the file,
                          // you may want an unsorted table in your output file

CTTableColumns ctColumns = ctTable.getTableColumns(); // setting new table columns will
                                                      // muck everything up, 
                                                      // so adjust the existing ones

// remove the old columns first if you plan on expanding your table in the column direction
for (int i = 0; i < ctColumns.getCount(); i++) {
    ctColumns.removeTableColumn(0);
}

// throw in your new columns
for (int i = 0; i < tableHeaders.size(); i++) {
    CTTableColumn column = ctColumns.addNewTableColumn();
    column.setName(tableHeaders.get(i));
    column.setId(i + 1);
}

// for some reason this isn't being take care of when columns are modified,
// so fix the column count manually
ctColumns.setCount(tableHeaders.size());

警告:如果表中不存在相应的属性,CTTable 中的所有 unsetX 方法将抛出 IndexOutOfBoundsExceptions,因此需要对其进行 try-catch。 @Gagravarr 在 cmets 中提到的另一种方法是先使用isSetX,然后就不需要trying。

如果这不起作用,那么您的表中可能设置了一堆其他东西。不幸的是,低级 XML 内容(封装在所有 CT 对象中)的文档记录非常差,因为它显然是从规范自动生成的,因此 API 非常不透明。我为了弄清楚要使用什么而经历的磨牙过程是解压缩 .xlsx,查看我需要调整的 XML,找出它在我的 XSSFSheet 中的位置以及我需要如何调整它,然后去寻找合适的 CT 方法,因为 XSSF-API 并不能真正让你做那么多。这样,您可以创建几乎可以在 Excel 中创建的任何内容,甚至可以更改一些您无法在 Excel 中创建的内容 - 如果您有时间和勇气的话。

【讨论】:

  • 而不是try {unsetX},为什么不先使用isSetX方法呢?
猜你喜欢
  • 2018-10-28
  • 1970-01-01
  • 1970-01-01
  • 2013-11-29
  • 1970-01-01
  • 1970-01-01
  • 2016-12-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多