Java 使用ApachePOI在Excel中扩展现有表
我有一个excel表格,里面有我想添加数据的公式 我这样做的动机是excel中的表可以动态扩展到您添加到其中的数据范围,这意味着公式行会自动跟上数据行的数量 但是,我很难确定使用ApachePOI是否可以实现这一点 我要尝试的一件事(见下面的代码)是扩展表的Java 使用ApachePOI在Excel中扩展现有表,java,excel,apache-poi,Java,Excel,Apache Poi,我有一个excel表格,里面有我想添加数据的公式 我这样做的动机是excel中的表可以动态扩展到您添加到其中的数据范围,这意味着公式行会自动跟上数据行的数量 但是,我很难确定使用ApachePOI是否可以实现这一点 我要尝试的一件事(见下面的代码)是扩展表的AreaReference,以覆盖数据,但是AreaReference(CR,CR2)(如示例中所用)和区域参考(CR、CR2、SpreadsheetVersion.EXCEL2007)(见apache)给出“构造函数未定义” 不知道是什么
AreaReference
,以覆盖数据,但是AreaReference(CR,CR2)代码>(如示例中所用)和区域参考(CR、CR2、SpreadsheetVersion.EXCEL2007)
(见apache)给出“构造函数未定义”
不知道是什么导致了构造函数错误,因为我已经导入了org.apache.poi.ss.util
ApacheDocsAreaReference(java.lang.String reference)
上的另一个选项允许我编译和运行,但给出了一个“NoSuchMethod”错误
List tableList=spreadSheet.getTables();
CellReference CR=新的CellReference(0,0);
CellReference CR2=新的CellReference(5,2);
AreaReference my_data_range=新的AreaReference(CR,CR2);
tableList.get(0).setArea(我的数据范围);
任何帮助都将不胜感激。到目前为止,使用ApachePOI
的主要问题是,如果不详细了解Microsoft Office
本身以及Microsoft Office
文件的存储,就无法使用它。很多事情只准备了一半,在新版本中经常会出现倒退(已经解决的bug再次出现)
因此,您的需求:“使用ApachePOI扩展Excel中的现有表”不仅仅是使用ApachePOI
就可以实现。您必须知道,officeopenxml
文件*.xlsx
只是可以解压缩的ZIP
归档文件。解压后,我们会找到存储表的/xl/tables/table1.xml
。这个XML
我们可以将其与使用Excel
的GUI
创建的XML
进行分析和比较。因此,我们可以发现由apachepoi
的缺点导致的问题。在/xl/tables/sheet1.XML
中,工作表的XML
也是如此
我们还需要知道,apachepoi
构建在ooxml模式的低级类上。部分地,我们需要使用这些类,因为apachepoi
已经准备就绪了一半。在下面的示例中,我们还需要ooxml-schemas-1.4.jar
,因为apache-poi
的poi-ooxml-schemas-4.0.0.jar
到目前为止还没有包含org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTableFormula
。不幸的是,目前还没有关于ooxml模式的公开文档。因此,我们需要下载源代码并自己做javadoc
下面的示例适用于我,使用的是ApachePOI4.0.0
。如果在编译或运行时遇到问题,原因可能是编译时和/或运行时类路径中存在多个不同版本的apache poi
jar
s。另外,正如前面所说,我的代码需要
import org.apache.poi.ss.usermodel.*;
导入org.apache.poi.xssf.usermodel.*;
导入org.apache.poi.ss.util.*;
导入org.apache.poi.ss.SpreadsheetVersion;
导入java.io.FileInputStream;
导入java.io.FileOutputStream;
导入org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTableColumn;
类扩展表{
静态void addrowtable(XSSFTable表){
int lastTableRow=table.getEndCellReference().getRow();
int totalsRowCount=table.getTotalsRowCount();
int lastTableDataRow=lastTableRow-totalsRowCount;
//我们将在表数据中添加一行
lastTableRow++;
lastTableDataRow++;
//新表区加一行
AreaReference newTableArea=新区域参考(
表.getStartCellReference(),
新细胞参考(
最后一行,
table.getEndCellReference().getCol()
),
电子表格版本.EXCEL2007
);
//新表数据区加一行
AreaReference newTableDataArea=新的AreaReference(
表.getStartCellReference(),
新细胞参考(
lastTableDataRow,
table.getEndCellReference().getCol()
),
电子表格版本.EXCEL2007
);
XSSFSheet sheet=table.getXSSFSheet();
如果(totalsRowCount>0){
//如果有总计行,请向下移动总计行
sheet.shiftRows(lastTableDataRow,lastTableRow,1);
//修正shiftRows不调整单元格引用的错误
//如果第3行下移,则单元格中的引用保持r=“A3”,r=“B3”。。。
//必须将它们调整到新的行中:r=“A4”,r=“B4”。。。
//ApachePOI3.17已经正确地做到了这一点,但在shiftRows中还有其他缺陷。
对于(int r=lastTableDataRow;r List<XSSFTable> tableList = spreadSheet.getTables();
CellReference CR = new CellReference(0, 0);
CellReference CR2 = new CellReference(5, 2);
AreaReference my_data_range = new AreaReference(CR,CR2);
tableList.get(0).setArea(my_data_range);
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);
}
}
}