先来看一下我做的效果图
直接上代码
@Configuration
public class ItextPdfUtils {
private static final Logger log = LoggerFactory.getLogger(ItextPdfUtils.class);
private static String SimApiPdfUploadPath;
private static String SimApiPdfTemplete;
private static Integer onepagerow;
private static Integer towpagerow;
@Value("#{T(java.lang.Integer).parseInt('${pdf_onepagerow:9}')}")
public void setOnepagerow(Integer onepagerow) {
ItextPdfUtils.onepagerow = onepagerow;
}
@Value("#{T(java.lang.Integer).parseInt('${pdf_towpagerow:22}')}")
public void setTowpagerow(Integer towpagerow) {
ItextPdfUtils.towpagerow = towpagerow;
}
@Value("${sim_api_pdf_upload_path}")
public void setSimApiPdfUploadPath(String simApiPdfUploadPath) {
ItextPdfUtils.SimApiPdfUploadPath = simApiPdfUploadPath;
}
@Value("${sim_api_pdf_template}")
public void setSimApiPdfTemplate(String simApiPdfTemplate) {
ItextPdfUtils.SimApiPdfTemplete = simApiPdfTemplate;
}
// 利用模板生成pdf
public static File pdfout(ParamVO paramVO, List<OrderPdfVO> orderPdfVOList, String pdfFileName, Integer num) {
// 模板路径
String templatePath = SimApiPdfTemplete + File.separator + "sim_shb.pdf";
// 生成的新文件路径
String newPDFPath = SimApiPdfUploadPath + File.separator + pdfFileName;
PdfReader reader;
FileOutputStream out;
ByteArrayOutputStream bos;
PdfStamper stamper;
try {
//给表单添加中文字体 这里采用系统字体。不设置的话,中文可能无法显示
BaseFont bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", false);
Font FontChinese = new Font(bf, 5, Font.NORMAL);
// 输出流
out = new FileOutputStream(newPDFPath);
// 读取pdf模板
reader = new PdfReader(templatePath);
bos = new ByteArrayOutputStream();
stamper = new PdfStamper(reader, bos);
AcroFields form = stamper.getAcroFields();
Map<String, Object> map = packageMap(paramVO);
//遍历第一页表单map数据
Map<String, String> dateheadmap = (Map<String, String>) map.get("dateheadmap");
// 添加所创建的字体
form.addSubstitutionFont(bf);
for (String key : dateheadmap.keySet()) {
String value = dateheadmap.get(key);
form.setField(key, value);
}
//第一页table数据
List<AcroFields.FieldPosition> list = form.getFieldPositions("table");
Rectangle rect = list.get(0).position;
PdfPTable table = packageTable(rect, orderPdfVOList, 10.0F, num);
//获取总行数
int totalRow = table.getRows().size();
//计算需要分页的总页数
int totalpage = caculatePageable(totalRow);
Document document = new Document();
if (totalpage == 1) {
//获table页面
PdfContentByte under = stamper.getOverContent(1);
//添加table
table.writeSelectedRows(0, -1, rect.getLeft(), rect.getTop(), under);
} else {
//目前模板中暂时解决分页方案 (动态增加空白模板填充值初始化给9个空白模板不包含收尾两个)
for (int i = 1; i <= totalpage; i++) {
document.newPage();
PdfContentByte under = stamper.getOverContent(i);
if (i == 1) {
//第一页显示9+头尾4条
table.writeSelectedRows(0, onepagerow, rect.getLeft(), rect.getTop(), under);
}
//空白模板每页显示22条
else {
table.writeSelectedRows(onepagerow + towpagerow * (i - 2), onepagerow + towpagerow * (i - 1), 60, 800, under);
}
}
}
//遍历最后一页map数据
Map<String, String> datefootmap = (Map<String, String>) map.get("datefootmap");
// 添加所创建的字体
form.addSubstitutionFont(bf);
for (String key : datefootmap.keySet()) {
String value = datefootmap.get(key);
form.setField(key, value);
}
// 如果为false,生成的PDF文件可以编辑,如果为true,生成的PDF文件不可以编辑
stamper.setFormFlattening(true);
stamper.close();
Document doc = new Document();
PdfCopy copy = new PdfCopy(doc, out);
PdfImportedPage importPage = null;
doc.open();
copyvalidPage(totalpage, importPage, reader, copy, bos);
doc.close();
File file = new File(newPDFPath);
return file;
} catch (IOException e) {
System.out.print(e);
} catch (DocumentException e) {
System.out.print(e);
}
return null;
}
/**
* 组装pdf表头表尾的单个域内容
*/
public static Map packageMap(ParamVO paramVO) {
//组装pdf表头的单个域内容
Map<String, String> headmap = new HashMap<String, String>();
Map<String, String> footmap = new HashMap<String, String>();
headmap.put("PartnerCode", paramVO.getPartnerCode());
headmap.put("ReceiverCode", paramVO.getReceiverCode());
headmap.put("WaybillCustomerName", paramVO.getWaybillCustomerName());
headmap.put("EndPointName", paramVO.getEndPointName());
headmap.put("CityName", paramVO.getCityName());
headmap.put("EndAddress", paramVO.getEndAddress());
headmap.put("LinkMan", paramVO.getLinkMan());
headmap.put("ReceiverName", paramVO.getReceiverName());
headmap.put("Phone", paramVO.getPhone());
headmap.put("ReceiverPhone", paramVO.getReceiverPhone());
headmap.put("ShipperCode", paramVO.getShipperCode());
headmap.put("PoNO", paramVO.getPoNO());
headmap.put("Route", paramVO.getRoute());
headmap.put("CustomOrderNO", paramVO.getCustomOrderNO());
headmap.put("ODBCreateTimeStr", paramVO.getODBCreateTimeStr());
headmap.put("WaybillNO", paramVO.getWaybillNO());
headmap.put("EstimateAllNum", paramVO.getEstimateAllNum());
headmap.put("AllNum", paramVO.getAllNum());
headmap.put("AllWeight", paramVO.getAllWeight());
headmap.put("AllVolumn", paramVO.getAllVolumn());
headmap.put("TotalUnit", paramVO.getTotalUnit());
if ("1".equals(paramVO.getVirusId())) {
headmap.put("AllActualNum", paramVO.getAllActualNum());
headmap.put("AllExceptionNum", paramVO.getAllExceptionNum());
}
//尾页
footmap.put("DCLOgisticts", paramVO.getDCLOgisticts());
footmap.put("ForwardingAgent", paramVO.getForwardingAgent());
footmap.put("CustomerNote", paramVO.getCustomerNote());
footmap.put("WarehouseOperator", paramVO.getWarehouseOperator());
footmap.put("VehicleNO", paramVO.getVehicleNO());
footmap.put("TotalActualWeight", paramVO.getTotalActualWeight());
footmap.put("ContainerNumber", paramVO.getContainerNumber());
footmap.put("CheckCarOperator", paramVO.getCheckCarOperator());
if ("1".equals(paramVO.getVirusId())) {
footmap.put("FreightDate", paramVO.getFreightDate());
footmap.put("FreightSignature", paramVO.getFreightSignature());
footmap.put("CustomerDate", formart(new Date()));
footmap.put("CustomerSignature", paramVO.getUserName());
}
if ("0".equals(paramVO.getVirusId())) {
footmap.put("FreightSignature", paramVO.getUserName());
footmap.put("FreightDate", formart(new Date()));
}
footmap.put("CompanyNote", paramVO.getCompanyNote());
//组装orderWaybillMap传过去
Map<String, Object> orderWaybillMap = new HashMap<String, Object>();
orderWaybillMap.put("dateheadmap", headmap);
orderWaybillMap.put("datefootmap", footmap);
return orderWaybillMap;
}
/**
* 组装pdf 中的table 包括样式字体
*/
public static PdfPTable packageTable(Rectangle rect, List<OrderPdfVO> list, Float fontSize, Integer num) {
try {
// 创建table下面通过table.addCell添加的时候必须添加整行内容的所有列
PdfPTable table = new PdfPTable(num);
if (num == 8) {
table.setWidthPercentage(100.0F);
BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", false);
//BaseFont bfChinese = BaseFont.createFont("C://Windows//Fonts//simsun.ttc,1" , BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
Font fontZH = new Font(bfChinese, fontSize == null ? 12F : fontSize, 0);
//第一行是列表名
table.setHeaderRows(1);
table.getDefaultCell().setHorizontalAlignment(1);
float tatalWidth = rect.getRight() - rect.getLeft() - 1;
//计算表格宽度
float[] columnWidth = {(float) (tatalWidth * 0.1),
(float) (tatalWidth * 0.2), (float) (tatalWidth * 0.2),
(float) (tatalWidth * 0.1), (float) (tatalWidth * 0.1),
(float) (tatalWidth * 0.1), (float) (tatalWidth * 0.1),
(float) (tatalWidth * 0.1)};
table.setTotalWidth(columnWidth);
table.setLockedWidth(true);
//遍历List 获取每一列的数据,填充到pdfTable中
list.forEach(orderPdfVO -> {
table.addCell(createCell(orderPdfVO.getCol1(), fontZH));
table.addCell(createCell(orderPdfVO.getCol2(), fontZH));
table.addCell(createCell(orderPdfVO.getCol3(), fontZH));
table.addCell(createCell(orderPdfVO.getCol4(), fontZH));
table.addCell(createCell(orderPdfVO.getCol6(), fontZH));
table.addCell(createCell(orderPdfVO.getCol7(), fontZH));
table.addCell(createCell(orderPdfVO.getCol8(), fontZH));
table.addCell(createCell(orderPdfVO.getCol9(), fontZH));
});
}
if (num == 11) {
table.setWidthPercentage(100.0F);
BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", false);
Font fontZH = new Font(bfChinese, fontSize == null ? 12F : fontSize, 0);
table.getDefaultCell().setHorizontalAlignment(1);
float tatalWidth = rect.getRight() - rect.getLeft() - 1;
//计算表格宽度
float[] columnWidth = {
(float) (tatalWidth * 0.1), (float) (tatalWidth * 0.2),
(float) (tatalWidth * 0.1), (float) (tatalWidth * 0.08),
(float) (tatalWidth * 0.05), (float) (tatalWidth * 0.08),
(float) (tatalWidth * 0.05), (float) (tatalWidth * 0.08),
(float) (tatalWidth * 0.08), (float) (tatalWidth * 0.08),
(float) (tatalWidth * 0.1)};
table.setTotalWidth(columnWidth);
table.setLockedWidth(true);
//遍历List 获取每一列的数据,填充到pdfTable中
list.forEach(orderPdfVO -> {
table.addCell(createCell(orderPdfVO.getCol1(), fontZH));
table.addCell(createCell(orderPdfVO.getCol2(), fontZH));
table.addCell(createCell(orderPdfVO.getCol3(), fontZH));
table.addCell(createCell(orderPdfVO.getCol4(), fontZH));
table.addCell(createCell(orderPdfVO.getCol6(), fontZH));
table.addCell(createCell(orderPdfVO.getCol7(), fontZH));
table.addCell(createCell(orderPdfVO.getCol8(), fontZH));
table.addCell(createCell(orderPdfVO.getCol9(), fontZH));
table.addCell(createCell(orderPdfVO.getCol10(), fontZH));
table.addCell(createCell(orderPdfVO.getCol11(), fontZH));
table.addCell(createCell(orderPdfVO.getCol12(), fontZH));
});
//第一行是列表名
table.setHeaderRows(1);
//最后3行是表尾总和行
table.setFooterRows(3);
}
//cell跨页
table.setKeepTogether(true);
table.setSplitLate(false);
table.setSplitRows(true);
return table;
} catch (Exception e) {
log.error(e.toString());
return null;
}
}
/**
* 创建表格
* @param value
* @param fontZH
* @return
*/
private static PdfPCell createCell(String value, Font fontZH) {
PdfPCell cell = new PdfPCell();
cell.setPhrase(new Phrase(value, fontZH));
// cell.setBorder(Rectangle.NO_BORDER);
return cell;
}
/**
* 时间格式转化
*/
public static String formart(Date date) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
date = calendar.getTime();
String newdate = sdf.format(date);
return newdate;
}
/**
* 计算分页
*/
public static int caculatePageable(int totalRow) {
int totalpage = 1;
int page = (totalRow - onepagerow) % towpagerow == 0 ? (totalRow - onepagerow) / towpagerow + 1 : (totalRow - onepagerow) / towpagerow + 2;
return totalRow < onepagerow ? totalpage : page;
}
/**
* 拷贝有效页面
*/
public static void copyvalidPage(int totalpage, PdfImportedPage importPage, PdfReader reader, PdfCopy copy, ByteArrayOutputStream bos) throws IOException, BadPdfFormatException {
List<PdfImportedPage> arrayList = new ArrayList();
for (int i = 1; i <= totalpage; i++) {
importPage = copy.getImportedPage(new PdfReader(bos.toByteArray()), i);
arrayList.add(importPage);
}
//只拷贝有数据的模板包括最后一页固定模板
importPage = copy.getImportedPage(new PdfReader(bos.toByteArray()), 11);
arrayList.add(importPage);
for (PdfImportedPage newImportPage : arrayList) {
copy.addPage(newImportPage);
}
}
}
方法调用 时传入需要转换的 实体VO
@Override
public File simConvertPdf(ParamVO paramVO) {
//把paramVo 适配成ItextPdf需要的参数类型
List<OrderPdfVO> list = new ArrayList<>();
List<Good> goodList = paramVO.getGoodsList();
//需要创建的模板表格
Integer num = 0;
//司机签名模板
if ("0".equals(paramVO.getVirusId())) {
if (goodList != null && goodList.size() > 0) {
//构造表头
list.add(new OrderPdfVO(
"产品编号Materail No",
"产品名称和规格/客户产品编码MaterailDescription/CustomerItemCode",
"批号/保质期Batch CodeExpiry Date",
"批号状态BatchStatus",
"数量Quantity",
"单位Unit",
"毛重 (吨)GrossWeight",
"体 积 (m³) Volumn"));
for (int i = 0; i < goodList.size(); i++) {
list.add(new OrderPdfVO(
goodList.get(i).getGoodsNO(),
goodList.get(i).getGoodsName(),
goodList.get(i).getBatchNO(),
goodList.get(i).getBatchStatus(),
goodList.get(i).getSignNum(),
goodList.get(i).getUnit(),
goodList.get(i).getSignWeight(),
goodList.get(i).getSignVolume()));
}
list.add(new OrderPdfVO("","","","总计:",paramVO.getAllNum(),paramVO.getTotalUnit(),paramVO.getAllWeight(),paramVO.getAllVolumn(),"","",""));
list.add(new OrderPdfVO("","","","","","DSP","","","","",""));
list.add(new OrderPdfVO("","","","","","EA","","","","",""));
}
num = 8;
}
//仓管签名模板
else {
if (goodList != null && goodList.size() > 0) {
//构造表头
list.add(new OrderPdfVO(
"产品编号Materail No",
"产品名称和规格/客户产品编码MaterailDescription/CustomerItemCode",
"批号/保质期Batch CodeExpiry Date",
"批号状态BatchStatus",
"数量Quantity",
"单位Unit",
"毛重 (吨)GrossWeight",
"体 积 (m³) Volumn",
"实收数量 Real Quantity",
"异常数量 Abnormal Quantity",
"备注 Remark"));
for (int i = 0; i < goodList.size(); i++) {
list.add(new OrderPdfVO(
goodList.get(i).getGoodsNO(),
goodList.get(i).getGoodsName(),
goodList.get(i).getBatchNO(),
goodList.get(i).getBatchStatus(),
goodList.get(i).getSignNum(),
goodList.get(i).getUnit(),
goodList.get(i).getSignWeight(),
goodList.get(i).getSignVolume(),
goodList.get(i).getActualNum(),
goodList.get(i).getExceptionNum() ,
goodList.get(i).getGoodsRemark()
)
);
}
list.add(new OrderPdfVO("","","","总计:",paramVO.getAllNum(),paramVO.getTotalUnit(),paramVO.getAllWeight(),paramVO.getAllVolumn(),paramVO.getAllActualNum(),paramVO.getAllExceptionNum(),""));
list.add(new OrderPdfVO("","","","","","DSP","","","","",""));
list.add(new OrderPdfVO("","","","","","EA","","","","",""));
}
num = 11;
}
//设置pdf文件名为VirusId +标识雀巢出货单编号
String pdfName = paramVO.getVirusId()+paramVO.getWaybillNO()+".pdf";
return ItextPdfUtils.pdfout(paramVO, list, pdfName, num);
}
每页展示的条数 可在配置文件中配置 具体在我的另一篇博文中找到关于Spring 静态变量注入值