难点主要是每页展示的数据量不确定,因为有些字段内容比较多,可能该字段会存在换行的情况,我主要是利用了表格拆分事件进行处理,在数据表格每次拆分的时候,拿到上一页的表开始行下标和结束行下标,再将这些信息传到页面事件中进行求和等处理,将合计加入到每页的页脚,下面开始上主要代码
表拆分事件(主数据列表的第一列是序号,借助该序号来拿到下标)
public class TableEvent implements PdfPTableEventAfterSplit {
/**
* 每页开始计算合计的row下标
* 初始值为table的header数量
*/
private Integer startIndex;
/**
* 每页结束计算合计的row下标
*/
private Integer endIndex;
/**
* 表数据
*/
private PdfPTable pdfPTable;
public Integer getStartIndex() {
return startIndex;
}
public Integer getEndIndex() {
return endIndex;
}
public PdfPTable getPdfPTable() {
return pdfPTable;
}
/**
* 在表格拆分之后执行
* @param pdfPTable
* @param pdfPRow 下一页的第一行
* @param index 行下标记
*/
@SneakyThrows
@Override
public void afterSplitTable(PdfPTable pdfPTable, PdfPRow pdfPRow, int index) {
// 上一页统计明细截止的下标记(保证第一列为序号的情况下)
endIndex = Integer.parseInt( pdfPRow.getCells()[0].getPhrase().getContent());
}
/**
* 在拆分表格时执行
* @param pdfPTable
*/
@Override
public void splitTable(PdfPTable pdfPTable) {
this.pdfPTable = pdfPTable;
if(null == startIndex || 0 == startIndex.intValue()){
startIndex = pdfPTable.getHeaderRows();
}else{
startIndex = endIndex+1;
}
}
/**
* 在表格渲染之后执行
* @param pdfPTable
* @param widths
* @param heights
* @param headerRows
* @param rowStart
* @param canvases
*/
@Override
public void tableLayout(PdfPTable pdfPTable, float[][] widths, float[] heights, int headerRows, int rowStart, PdfContentByte[] canvases) {
}
}
页脚事件处理合计,将合计加入页脚
public class FooterHandle extends PdfPageEventHelper {
/**
* 页脚表
*/
private PdfPTable footer;
/**
* 页脚的高度
*/
private float height = -5;
/**
* 制单人
*/
private String createBy;
/**
* 需要求合计的列下标
*/
private int columIndex = 9;
/**
* 总的合计金额
*/
private BigDecimal sumAmount;
private Font font;
/**
* 上一次的开始下标
*/
private int start = 0;
/**
* 上一次的结束下标
*/
private int end = 0;
/**
* 明细数据
*/
private List<BigDecimal> detailList;
/**
* 主数据表拆分事件
*/
protected TableEvent tableEvent;
public OutStockBillFooterHandle(PdfPTable footer,Font font,String createBy,int columIndex,BigDecimal sumAmount,List<BigDecimal> detailList){
this.footer = footer;
this.font = font;
this.createBy = createBy;
this.columIndex = columIndex;
this.sumAmount = sumAmount;
this.detailList = detailList;
}
public OutStockBillFooterHandle(PdfPTable footer, Font font, String createBy, int columIndex, BigDecimal sumAmount, List<BigDecimal> detailList, float height){
this.footer = footer;
this.font = font;
this.createBy = createBy;
this.columIndex = columIndex;
this.sumAmount = sumAmount;
this.detailList = detailList;
this.height = height;
}
public void setTableEvent(BillTableEvent tableEvent) {
this.tableEvent = tableEvent;
}
@SneakyThrows
@Override
public void onEndPage(PdfWriter writer, Document document) {
BigDecimal total = BigDecimal.ZERO;
Integer startIndex = tableEvent.getStartIndex();
Integer endIndex = tableEvent.getEndIndex();
if(null == startIndex && null == endIndex){
// 本文档只有一页,未经过表格的拆分事件处理
for(BigDecimal detail:detailList){
total = total.add(detail);
}
} else {
// 确定为最后一页
if(start == startIndex && end == endIndex){
startIndex = endIndex+1;
endIndex = tableEvent.getPdfPTable().getRows().size()-1;
}
start = startIndex;
end = endIndex;
for(int i = startIndex;i <= endIndex;i++){
total = total.add(new BigDecimal(tableEvent.getPdfPTable().getRow(i).getCells()[columIndex].getPhrase().getContent()));
}
}
// 清除以前的数据
footer.deleteBodyRows();
// 将合计加入到页脚中
PdfPCell cell = new PdfPCell();
cell.setHorizontalAlignment(Element.ALIGN_RIGHT);
// 隐藏所有边框
cell.disableBorderSide(PdfPCell.BOX);
// 合并单元格
cell.setColspan(footer.getNumberOfColumns());
cell.setPhrase(new Phrase(String.format("本页合计:%.2f" +"\n"+"总计:%.2f",total,sumAmount),font));
cell.setLeading(0,1.2f);
cell.setFixedHeight(40);
footer.addCell(cell);
cell = new PdfPCell();
cell.setPhrase(new Phrase("制单人:",font));
cell.setLeading(0,1.2f);
cell.setHorizontalAlignment(Element.ALIGN_LEFT);
cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
cell.disableBorderSide(PdfPCell.BOX);
footer.addCell(cell);
cell = new PdfPCell(new Phrase(createBy,font));
cell.setLeading(0,1.2f);
cell.disableBorderSide(Element.SECTION);
footer.addCell(cell);
cell = new PdfPCell();
cell.disableBorderSide(PdfPCell.BOX);
footer.addCell(cell);
footer.writeSelectedRows(0, -1, document.left()+document.leftMargin()/2, document.bottom()-height, writer.getDirectContent());
}
绑定页脚以及数据表拆分事件(这里只上主要代码)
TableEvent tableEvent = new TableEvent();
FooterHandle footerEvent = new FooterHandle(footer, font, outstockBill.getCreateBy(), 9, sumAmount,detailList.stream().map(obj::getAmount).collect(toList()));
// 页脚传入表拆分事件
footerEvent.setTableEvent(tableEvent);
// 绑定页脚事件
writer.setPageEvent(footerEvent);
doc.open();
// 表数据
PdfPTable table = makeMainTable();
// 绑定表拆分事件
table.setTableEvent(tableEvent);