iText 7是AGPL/商业软件的双重许可。个人使用开源的依赖是免费的,但是商用是要收费的。
原理
先读取excel,获取excel的单元格分部,以及单元格内容。
然后在使用itext7创建空白pdf,在pdf上根据获取的到单元格信息画表格。
itext7有专用的表格类com.itextpdf.layout.element.Table
使用方式类似poi中的cell单元格,一个一个放入就行
引入依赖
一般可以使用最新版
<!-- https://mvnrepository.com/artifact/com.itextpdf/itext7-core -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext7-core</artifactId>
<version>7.2.5</version>
<type>pom</type>
</dependency>
实现功能
protected com.itextpdf.layout.element.Table toParseContentV2(Sheet sheet, FormulaEvaluator evaluator) throws IOException {
int rows = sheet.getPhysicalNumberOfRows();
for (int i = 0; i < rows; i++) {
Row row = sheet.getRow(i);
if (row == null) continue;
int columns = row.getLastCellNum();
if (columns < 0) continue;
heightInPoints += row.getHeightInPoints();
}
PdfPCellInfo2[][] tableCell = new PdfPCellInfo2[rows][];
int maxCol = 0;
//给二维数字添加值
for (int i = 0; i < rows; i++) {
Row row = sheet.getRow(i);
if (row == null) continue;
int columns = row.getLastCellNum();
if (columns < 0) continue;
if (row.getZeroHeight()) continue;
PdfPCellInfo2[] cells = new PdfPCellInfo2[columns];
tableCell[i] = cells;
maxCol = Math.max(maxCol, columns);
for (int j = 0; j < columns; j++) {
Cell cell = row.getCell(j);
if (cell == null) continue;
CellRangeAddress range = getColspanRowspanByExcel(row.getRowNum(), cell.getColumnIndex());
int rowspan = 1;
int colspan = 1;
if (range != null) {
rowspan = range.getLastRow() - range.getFirstRow() + 1;
colspan = range.getLastColumn() - range.getFirstColumn() + 1;
}
com.itextpdf.layout.element.Cell pdfpCell = new com.itextpdf.layout.element.Cell(rowspan, colspan);
pdfpCell.setKeepTogether(true);
pdfpCell.setBackgroundColor(new DeviceGray(1));
pdfpCell.setVerticalAlignment(getVAlignByExcel(cell.getCellStyle().getVerticalAlignment().getCode()));
pdfpCell.setTextAlignment(getTextAlignment(cell.getCellStyle().getAlignment().getCode()));
getFontByExcel(pdfpCell, cell, evaluator);
if (sheet.getDefaultRowHeightInPoints() != row.getHeightInPoints()) {
pdfpCell.setMinHeight(row.getHeightInPoints()*((pageSize.getHeight()-20*3f)/heightInPoints));
}
cells[j] = new PdfPCellInfo2(pdfpCell, colspan, cell);
j += colspan - 1;
addBorderByExcel(pdfpCell, cell.getCellStyle(), colspan == 1 ? null : (row.getCell(j) == null ? row.createCell(j) : row.getCell(j)));
}
}
//排除前后不需要的列
int openCol = 0;
int endCol = 0;
boolean open = true;
boolean end = true;
for (int i = 0; i < maxCol; i++) {
if (!open & !end) {
break;
}
endCol = maxCol - 1 - i;
for (int j = 0; j < rows; j++) {
if (tableCell[j] == null) continue;
open = open & (tableCell[j][i] == null || cellIsEmpty(tableCell[j][i].getCell(), evaluator, true));
end = end & (tableCell[j].length <= endCol || tableCell[j][endCol] == null || cellIsEmpty(tableCell[j][endCol].getCell(), evaluator, false));
}
if (open) openCol = i;
if (i >= endCol) {
break;
}
}
//计算长度
List<Float> widths = new ArrayList<>();
float mw = 0;
for (int i = 0; i < rows; i++) {
PdfPCellInfo2[] pdfPCellInfo2s = tableCell[i];
if (pdfPCellInfo2s == null) continue;
List<Float> cws = new ArrayList<>();
float rw = 0;
for (int j = 0; j < pdfPCellInfo2s.length; j++) {
if (j > endCol) {
break;
}
PdfPCellInfo2 pdfPCellInfo2 = pdfPCellInfo2s[j];
if (pdfPCellInfo2 != null && pdfPCellInfo2.getCell() != null) {
float width = getPOIColumnWidth(pdfPCellInfo2.getCell());
cws.add(width);
rw += width;
} else {
float width = getPOIColumnWidth(sheet.getRow(i).createCell(j));
cws.add(width);
rw += width;
}
}
if (rw > mw || mw == 0) {
widths = cws;
mw = rw;
}
}
float[] widthArr = new float[widths.size()];
for (int i = 0; i < widths.size(); i++) {
widthArr[i] = widths.get(i);
width += widths.get(i);
}
com.itextpdf.layout.element.Table table = new com.itextpdf.layout.element.Table(widthArr);
//放入table
Set<String> set = new HashSet<>();
for (int i = 0; i < rows; i++) {
for (int j = openCol; j <= endCol ; j++) {
if (tableCell[i] == null) continue;
if (set.contains(i + "" + j)) continue;
if (tableCell[i].length <= j || tableCell[i][j] == null || tableCell[i][j].getPdfPCell() == null) {
Cell cell = sheet.getRow(i).createCell(j);
blankCell.setBackgroundColor(new DeviceGray(1));
table.addCell(blankCell);
} else {
if (tableCell[i][j].getPdfPCell().getRowspan() > 1) {
int colspan = tableCell[i][j].getPdfPCell().getColspan();
for (int k = 1; k < tableCell[i][j].getPdfPCell().getRowspan(); k++) {
for (int s = 0; s < colspan; s++) {
set.add(i + k + "" + (j + s));
}
}
}
table.addCell(tableCell[i][j].getPdfPCell());
j += tableCell[i][j].getSize() - 1;
}
}
}
return table;
}