当前位置: 首页 > 面试题库 >

使用Apache POI在Excel中扩展现有表

昝宜
2023-03-14
问题内容

我在Excel中有一张要添加数据的公式表。

我这样做的动机是,Excel中的表可以动态扩展到您添加到表中的数据范围,这意味着公式行会自动跟上数据行的数量。

但是,我很难确定是否可以使用apache-POI。

我要尝试的一件事(请参见下面的代码)是扩展AreaReference表的范围以覆盖数据,但是AreaReference(CR,CR2);(在
本示例中使用的)和AreaReference(CR,CR2, SpreadsheetVersion.EXCEL2007)(在apache
文档中看到的)都给出“构造函数未定义”。

不知道是什么原因导致了org.apache.poi.ss.util导入的构造函数错误。

apache文档上的另一个选项AreaReference(java.lang.String reference)可以让我编译并运行,但是会出现“NoSuchMethod”错误。


问题答案:

apache poi根本使用的主要问题是,如果没有这样的知识Microsoft Office以及关于Microsoft Office文件存储的详细知识,就无法准备使用它。有很多事情还没准备好,在新版本中经常会有回归(错误再次出现,已经解决了)。

因此,您的要求:“
仅使用”就不可能实现“使用Apache POI扩展Excel中的现有表” apache poi。必须知道Office Open XML文件*.xlsx只是ZIP可以解压缩的存档。并
解压后,我们发现/xl/tables/table1.xml该表的存储。这个XML我们可以分析,并将其与比较XML,其使用创建
Excel的GUI。因此,我们可以发现由缺点造成的问题
apache poi。同样是与纸张的XML在/xl/tables/sheet1.xml

此外,我们还需要知道它是apache poi基于的低级类构建的
ooxml-schemas。由于的中途准备,我们部分需要使用这些类apache poi。在下面的例子中,我们需要ooxml- schemas-1.4.jar另外,因为apache poipoi-ooxml- schemas-4.0.0.jar并没有包括
org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTableFormula
现在。不幸的是,没有ooxml-schemas公开的文档
。因此,我们需要下载源代码并javadoc自己做。

以下示例对我有用apache poi 4.0.0。如果在编译或运行时遇到问题,原因可能是apache poi
jar在编译时和/或运行时,类路径中存在多个不同版本的。不要混合使用不同的Apache
Poi版本。另外,正如已经说过的那样,我的代码需要所有模式ooxml-
schemas-1.4.jar的完整jar。

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.*;
import org.apache.poi.ss.util.*;
import org.apache.poi.ss.SpreadsheetVersion;

import java.io.FileInputStream;
import java.io.FileOutputStream;

import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTableColumn;

class ExcelExpandingTable {

 static void addRowToTable(XSSFTable table) {

   int lastTableRow = table.getEndCellReference().getRow();
   int totalsRowCount = table.getTotalsRowCount();
   int lastTableDataRow = lastTableRow - totalsRowCount;

   // we will add one row in table data
   lastTableRow++;
   lastTableDataRow++;

   // new table area plus one row
   AreaReference newTableArea = new AreaReference(
                                 table.getStartCellReference(), 
                                 new CellReference(
                                  lastTableRow, 
                                  table.getEndCellReference().getCol()
                                 ),
                                 SpreadsheetVersion.EXCEL2007
                                );

   // new table data area plus one row
   AreaReference newTableDataArea = new AreaReference(
                                     table.getStartCellReference(), 
                                      new CellReference(
                                       lastTableDataRow, 
                                       table.getEndCellReference().getCol()
                                      ),
                                      SpreadsheetVersion.EXCEL2007
                                    );

   XSSFSheet sheet = table.getXSSFSheet();
   if (totalsRowCount > 0) {
    //if we have totals rows, shift totals rows down
    sheet.shiftRows(lastTableDataRow, lastTableRow, 1);

    // correcting bug that shiftRows does not adjusting references of the cells
    // if row 3 is shifted down, then reference in the cells remain r="A3", r="B3", ...
    // they must be adjusted to the new row thoug: r="A4", r="B4", ...
    // apache poi 3.17 has done this properly but had have other bugs in shiftRows.
    for (int r = lastTableDataRow; r < lastTableRow + 1; r++) {
     XSSFRow row = sheet.getRow(r); 
     if (row != null) {
      long rRef = row.getCTRow().getR();
      for (Cell cell : row) {
       String cRef = ((XSSFCell)cell).getCTCell().getR();
       ((XSSFCell)cell).getCTCell().setR(cRef.replaceAll("[0-9]", "") + rRef);
      }
     }
    }
    // end correcting bug

   }

   // if there are CalculatedColumnFormulas do filling them to the new row
   XSSFRow row = sheet.getRow(lastTableDataRow); if (row == null) row = sheet.createRow(lastTableDataRow);
   for (CTTableColumn tableCol : table.getCTTable().getTableColumns().getTableColumnList()) {
    if (tableCol.getCalculatedColumnFormula() != null) {
     int id = (int)tableCol.getId();
     String formula = tableCol.getCalculatedColumnFormula().getStringValue();
     XSSFCell cell = row.getCell(id -1); if (cell == null) cell = row.createCell(id -1);
     cell.setCellFormula(formula);
    }
   }

   table.setArea(newTableArea);

   // correcting bug that Autofilter includes possible TotalsRows after setArea new
   // Autofilter must only contain data area
   table.getCTTable().getAutoFilter().setRef(newTableDataArea.formatAsString());
   // end correcting bug

   table.updateReferences();

 }

 public static void main(String[] args) throws Exception {
  try (Workbook workbook = WorkbookFactory.create(new FileInputStream("SAMPLE.xlsx"));
       FileOutputStream out = new FileOutputStream("SAMPLE_NEW.xlsx")) {

   XSSFSheet sheet = ((XSSFWorkbook)workbook).getSheetAt(0);
   XSSFTable table = sheet.getTables().get(0);

   addRowToTable(table);

   workbook.write(out);
  } 
 }
}


 类似资料:
  • 用户可以将Excel文档保存为. xls或xml-table。结果是一个具有固定结构的xml-file,Excel可以用它纠正工作。 可以用java中的ApachePOI打开这种类型的excel文件吗? 事先谢谢你,安德烈。

  • 我正试图用三个额外的日期(时间戳)字段扩展扩展扩展名(新闻),并希望在(新闻)的fluidtemplate中调用这些字段。 我已经连线到目前为止,我可以看到我的后端额外的字段,而无需选择一个外部类型-我已经相应地修改了ext_tables.php,并可以保存数据。 现在,我试图在我的新闻流模板中使用这些字段,在我的Partials/List/Item中使用以下代码。html-{newsItem.d

  • 问题内容: 我目前正在使用Selenium来运行Chrome实例来测试网页。每次我的脚本运行时,都会启动一个干净的Chrome实例(清理扩展程序,书签,浏览历史记录等)。我想知道是否可以使用Chrome扩展程序运行脚本。我曾尝试搜索Python示例,但是当我在Google上搜索时什么都没想到。 问题答案: 您应该使用Chrome WebDriver 选项设置要加载的扩展程序列表。这是一个例子: 希

  • 本文向大家介绍Yii安装与使用Excel扩展的方法,包括了Yii安装与使用Excel扩展的方法的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了Yii安装与使用Excel扩展的方法。分享给大家供大家参考,具体如下: 1.下载EExcelBehavior到项目扩展目录下 2.下载phpexcl到扩展目录 3.控制器调用: 4.具体用法: 更多关于Yii相关内容感兴趣的读者可查看本站专题:《Yi

  • 我有个小问题。我做了一个生成jtable的程序,比你可以用一些值填充这个表,比把整个表保存到Excel。 在乞讨开始时,我定义了file: 当我打开这个文件时,我得到消息,文件的格式与其扩展名(.xls)不同。所以我点击“另存为”,建议的扩展名是。txt。我将文件保存为。xls(似乎与java程序保存的文件相同),并且我可以将JTable从excel导入java程序,而不会出现任何错误。谁能建议如

  • 我使用的是、。我正在尝试向现有的数据库和表添加一个新列。我在POJO类MyTable中添加了一个新字段。尽管具有属性,但新列没有被添加。 更新:我已经调试到代码中,发现它没有试图生成新列,它在类中的方法处抛出一个错误,并表示表已经存在并从该方法返回。 如果我手动将类的方法中有一个名为的字段。然后成功生成新列。因为字段是false,所以没有触发extend。我不确定,如果这是正确的领域去。