Java使用ITEXT7導出pdf
背景
需要導出以下的pdf模板出來,之前做的都用freemarker來導出word,現在更換成了pdf,所以臨時整了個
准備工作
- maven依賴
<dependency>
<groupid>com.itextpdf</groupid>
<artifactid>itext7-core</artifactid>
<version>7.1.11</version>
<type>pom</type>
</dependency>
-
api
說到這個itextpdf的api就不得不吐槽下,是寫的真不太好
還有各個版本之間差異也有很多,注意自己依賴的版本
大部分都是和html的方法差不多,例如什么margin padding border 都差不多,只是寫起來麻煩,無法直觀看見效果,需要每次都去生成一遍,再來調整,注意:本人不喜歡寫html的東西,所以寫出來的效果不是很好,可以有空自己琢磨怎么好看
-
常用方法
//首先你需要一個writer對象 PdfWriter writer = new PdfWriter(導出路徑); //需要一個pdf的對象來操作pdf PdfDocument pdf = new PdfDocument(writer); //需要一個document的對象來操作數據 指定為A4大小 Document document = new Document(pdf, PageSize.A4); //每次畫完一部分的需要用document.add(table)添加到文檔對象,才能有效果 //常用的幾個實體類 //表格 本文采用的都是表格來布局 Table table = new Table(int列數) // 單元格 支持合並行 合並列 Cell cell= new Cell(行, 列) // 段落 new Paragraph(可以直接放文本); //黑色 DeviceRgb black = new DeviceRgb(0, 0, 0); //灰色 DeviceRgb gray = new DeviceRgb(220, 220, 220); //灰色虛線邊框 DashedBorder grayBorder = new DashedBorder(gray, 0.5F); //黑色實體邊框 SolidBorder solidBorder = new SolidBorder(black, 0.5F); 下面的多了一些setWidth setFontSize setFixedLeading setBold setHeight setTextAlignment setVerticalAlignment 這些名詞稍微懂點html的都知道啥意思吧,就不需要多介紹了
-
大致思路
因為要做分頁,所以抽了幾個方法出來,頭部,尾部信息都是一樣的,變化的只有中間的商品表格。
所有的布局都是通過table來實現的,有更好的想法可以提出來修改
代碼
當一個table 你的列數超過了你設置的值后,就會往下一行排列,這跟html的規則是一樣的,注意下
中文字體是需要額外配置的,否則無法顯示出來
/**
* 獲取中文字體
*
* @return
*/
private static PdfFont getChineseFont() {
try {
return PdfFontFactory.createFont("STSongStd-Light", "UniGB-UCS2-H", false);
} catch (IOException e) {
e.printStackTrace();
throw new MyException("獲取中文字體失敗");
}
}
- 頭部信息的代碼 思路就是用的一個table左邊單元格是圖片,右邊的單元格是基本信息,這邊的logo暫時是寫死路徑的,可以自己定義下
/**
* 頭部固定位置
*
* @param document
* @param pdf
* @param type 1.餐廳訂單 2.供應商訂單
* @throws MalformedURLException
*/
private void drawOrderTop(Document document, PdfDocument pdf, String type) throws MalformedURLException {
DeviceRgb black = new DeviceRgb(0, 0, 0);
DeviceRgb gray = new DeviceRgb(220, 220, 220);
// 黑色虛線邊框
DashedBorder grayBorder = new DashedBorder(gray, 0.5F);
Table table = new Table(5).setMarginLeft(10).setMarginRight(10);
table.setBorder(null);
// TODO: 2021/1/8 寫死先
// table.addCell(new Cell().add(new Image(ImageDataFactory.create(configUtil.getStaticUrl() + "/logo.png")).setWidth(25)).setBorder(Border.NO_BORDER));
//左邊的logo部分
table.addCell(new Cell(5, 2).add(new Image(ImageDataFactory
.create("E:\\Project\\xxxx\\src\\main\\resources\\static\\img\\logo.png"))
.setWidth(160))
.setBorder(Border.NO_BORDER));
//右邊的基本信息
table.addCell(new Cell(1, 3).setMarginLeft(20)
.add(new Paragraph("UNITY FRESH SUPPLY SDN. BHD")
.setFontSize(10)
.setFontColor(black)
.setFixedLeading(13)
.setBold().add(new Text(".(1381196-H)").setFontSize(7)))
.setWidth(500)
.setHeight(13)
.setBorder(null)
// .setBorderLeft(grayBorder)
// .setBorderBottom(grayBorder)
.setTextAlignment(TextAlignment.LEFT));
table.addCell(new Cell(1, 3)
.add(
new Paragraph("Address:")
.setFontSize(7)
.add(new Text("66, Jalan 5/116b, Kuchai Entrepreneurs Park, ").setFontSize(5))
)
.setHeight(10)
.setBorder(null)
// .setBorderLeft(grayBorder)
// .setBorderBottom(grayBorder)
.setTextAlignment(TextAlignment.LEFT));
table.addCell(new Cell(1, 3)
.add(
new Paragraph()
.setFontSize(7)
.add(new Text("58200 Kuala Lumpur, Malaysia.").setFontSize(5))
)
.setHeight(10)
.setBorder(null)
// .setBorderLeft(grayBorder)
// .setBorderBottom(grayBorder)
.setTextAlignment(TextAlignment.LEFT));
table.addCell(new Cell(1, 3)
.add(
new Paragraph("Email:")
.setFontSize(7)
.add(new Text("newpower.my@gmail.com").setFontSize(5))
)
.setHeight(10)
.setBorder(null)
// .setBorderLeft(grayBorder)
// .setBorderBottom(grayBorder)
.setTextAlignment(TextAlignment.LEFT));
table.addCell(new Cell(1, 3)
.add(
new Paragraph("TEL:")
.setFontSize(7)
.add(new Text("+60 10 280 2037").setFontSize(5))
)
.setHeight(10)
.setBorder(null)
// .setBorderLeft(grayBorder)
// .setBorderBottom(grayBorder)
.setTextAlignment(TextAlignment.LEFT));
if (StringUtils.equals(type, "1")) {
table.addCell(new Cell(1, 5).add(
new Paragraph("ORDER").setFixedLeading(20))
.setFontSize(10)
.setHeight(20)
.setBold()
.setTextAlignment(TextAlignment.RIGHT)
.setBorder(null)
);
}
if (StringUtils.equals(type, "2")) {
table.addCell(new Cell(1, 5).add(
new Paragraph("PURCHASE ORDER").setFixedLeading(20))
.setFontSize(10)
.setHeight(20)
.setBold()
.setTextAlignment(TextAlignment.RIGHT)
.setBorder(null)
);
}
document.add(table);
}
-
基本信息的
思路也是一樣的 都是table 依次排列出來
/** * @param document * @param billInfo * @param i * @param count * @param type 1.餐廳訂單 2.供應商訂單 */ public void drawOrderBaseInfo(Document document, BillInfoDto billInfo, int i, int count, String type) { DeviceRgb black = new DeviceRgb(0, 0, 0); DeviceRgb gray = new DeviceRgb(220, 220, 220); // 黑色虛線邊框 DashedBorder grayBorder = new DashedBorder(gray, 0.5F); SolidBorder solidBorder = new SolidBorder(black, 0.5F); Table table = new Table(6).setMarginLeft(10).setMarginRight(10); table.setBorder(null); table.addCell( new Cell(8, 4).setBorder(null).setMargin(0).setPadding(0).add( new Table(4).setMargin(0).setPadding(0) .addCell( new Cell(3, 4).setBorder(null).setWidth(300).setMargin(0).setPadding(0).add( new Table(4).setMargin(0).setPadding(0).setBorder(null) .addCell( new Cell(1, 2).setBorder(null).setWidth(228).add(new Paragraph("Bill to:")) ) .addCell( new Cell(1, 2).setBorder(null).setWidth(200).add(new Paragraph("Delivery Address:")) ) .addCell( new Cell(1, 2).setBorder(null).add(new Paragraph(billInfo.getBillName()).setFont(getChineseFont()).setFontSize(8).setHeight(20)) ) .addCell( new Cell(1, 2).setBorder(null).add(new Paragraph(billInfo.getDeliveryAddress()).setFontSize(8).setHeight(20)) ) .addCell( new Cell(1, 2).setBorder(null).add(new Paragraph(billInfo.getBillTo()).setFont(getChineseFont()).setFontSize(8).setHeight(20)) ) .addCell( new Cell(1, 2).setBorder(null).add(new Paragraph(billInfo.getArea()).setFont(getChineseFont()).setFontSize(8).setHeight(20)) ) ) ) .addCell( new Cell(1, 4).setBorder(null) .setBorder(null) .add(new Paragraph("").setHeight(10)) ) .addCell( new Cell(1, 2).setBorder(null) .setBorder(null) // .setBorderRight(solidBorder) .add(new Paragraph("Attn:") .add(new Text(billInfo.getName()).setFont(getChineseFont()).setFontSize(9))) ) .addCell( new Cell(1, 2).setPaddingLeft(10) .setBorder(null) .add(new Paragraph("Attn:") .add(new Text(billInfo.getAgent()).setFont(getChineseFont()).setFontSize(9))) ) .addCell( new Cell(1, 2).setBorder(null) .setBorder(null) // .setBorderRight(solidBorder) .add(new Paragraph("TEL:").setFontSize(10) .add(new Text(billInfo.getTel()).setFont(getChineseFont()).setFontSize(9))) ) .addCell( new Cell(1, 2).setBorder(null) .setBorder(null) .add(new Paragraph("TEL:").setFontSize(10).setPaddingLeft(10) .add(new Text(billInfo.getAgentPhone()).setFont(getChineseFont()).setFontSize(9))) ) .addCell( new Cell(2, 2).setBorder(null) .setBorder(null) .setHeight(40) .add(new Paragraph("Email:").setFontSize(10) .add(new Text(billInfo.getEmail()).setFont(getChineseFont()).setFontSize(9))) ) .addCell( new Cell(2, 2).setBorder(null) .setBorder(null) .setHeight(40) ) ) ); if (StringUtils.equals("1", type)) { table.addCell( new Cell(7, 2) .setBorder(null) .setWidth(160) .add( new Table(2).addCell( new Cell(1, 1).setBorder(null).add( new Paragraph("Order No.:").setFontSize(9)) ).addCell(new Cell(1, 1).setBorder(null).add( new Paragraph(billInfo.getInvoiceNo()).setFontSize(8) )).addCell(new Cell(1, 1).setBorder(null).add( new Paragraph("Area:").setFontSize(9) )).addCell(new Cell(1, 1).setBorder(null).add( new Paragraph(billInfo.getArea()).setFontSize(8).setFont(getChineseFont()) )).addCell(new Cell(1, 1).setBorder(null).add( new Paragraph("Agent:").setFontSize(9) )).addCell(new Cell(1, 1).setBorder(null).add( new Paragraph(billInfo.getAgent()).setFontSize(8).setFont(getChineseFont()) )).addCell(new Cell(1, 1).setBorder(null).add( new Paragraph("Date : ").setFontSize(9) )).addCell(new Cell(1, 1).setBorder(null).add( new Paragraph(billInfo.getDate()).setFontSize(8) )).addCell(new Cell(1, 1).setBorder(null).add( new Paragraph("Terms : ").setFontSize(9) )).addCell(new Cell(1, 1).setBorder(null).add( new Paragraph("Cash").setFontSize(8) )).addCell(new Cell(1, 1).setBorder(null).add( new Paragraph("Page :").setFontSize(9) )).addCell(new Cell(1, 1).setBorder(null).add( new Paragraph(i + "/" + count).setFontSize(8) )).addCell(new Cell(2, 1).setBorder(null).add( new Paragraph("").setFontSize(9) )) ) ); } if (StringUtils.equals("2", type)) { table.addCell( new Cell(7, 2) .setBorder(null) .setWidth(160) .add( new Table(2).addCell( new Cell(1, 1).setBorder(null).add( new Paragraph("Order No.:").setFontSize(9)) ).addCell(new Cell(1, 1).setBorder(null).add( new Paragraph(billInfo.getInvoiceNo()).setFontSize(8) )).addCell(new Cell(1, 1).setBorder(null).add( new Paragraph("Area:").setFontSize(9) )).addCell(new Cell(1, 1).setBorder(null).add( new Paragraph(billInfo.getArea()).setFontSize(8).setFont(getChineseFont()) )).addCell(new Cell(1, 1).setBorder(null).add( new Paragraph("Date : ").setFontSize(9) )).addCell(new Cell(1, 1).setBorder(null).add( new Paragraph(billInfo.getDate()).setFontSize(8) )).addCell(new Cell(1, 1).setBorder(null).add( new Paragraph("Page :").setFontSize(9) )).addCell(new Cell(1, 1).setBorder(null).add( new Paragraph(i + "/" + count).setFontSize(8) )).addCell(new Cell(2, 1).setBorder(null).add( new Paragraph("").setFontSize(9) )).addCell(new Cell(3, 2).setBorder(null).add(new Paragraph(""))) ) ); } document.add(table); }
-
商品表格 因為我這邊是做了分頁效果的,思路也是一樣的,先畫表頭,再循環添加每一條商品信息進去,下面的代碼因為分了兩個端,所以有兩個方法
/** * 餐廳 * * @param document * @param goods */ public void drawMerchantGoodsInfo(Document document, List<goodinfodto> goods) { DeviceRgb black = new DeviceRgb(0, 0, 0); DeviceRgb gray = new DeviceRgb(220, 220, 220); // 黑色虛線邊框 DashedBorder grayBorder = new DashedBorder(gray, 0.5F); SolidBorder solidBorder = new SolidBorder(black, 0.5F); Table table = new Table(7).setMarginLeft(10).setMarginRight(10); table.setBorderTop(solidBorder); table.addCell( new Cell(1, 1).setVerticalAlignment(VerticalAlignment.MIDDLE).setTextAlignment(TextAlignment.CENTER).setWidth(50).setBorder(null).setBorderBottom(solidBorder).add(new Paragraph("Item.").setFontSize(8)) ); table.addCell( new Cell(1, 2).setVerticalAlignment(VerticalAlignment.MIDDLE).setTextAlignment(TextAlignment.CENTER).setWidth(300).setBorder(null).setBorderBottom(solidBorder).add(new Paragraph("Description").setFontSize(8)) ); table.addCell( new Cell(1, 1).setWidth(70).setVerticalAlignment(VerticalAlignment.MIDDLE).setTextAlignment(TextAlignment.CENTER).setBorder(null).setBorderBottom(solidBorder).add(new Paragraph("Qty").setFontSize(8)) ); table.addCell( new Cell(1, 2).setWidth(165).setBorder(null).setBorderTop(solidBorder).setBorderBottom(solidBorder) .add( new Table(1).setBorder(null) .addCell( new Cell(1, 1).setBorder(null).setWidth(87).setTextAlignment(TextAlignment.CENTER).add(new Paragraph("Discounted Price").setFontSize(8)) ) .addCell( new Cell(1, 1).setBorder(null).setTextAlignment(TextAlignment.CENTER).add(new Paragraph("RM").setFontSize(8)) ) ) ); table.addCell( new Cell(1, 2).setWidth(165).setBorder(null).setBorderTop(solidBorder).setBorderBottom(solidBorder) .add( new Table(2).setBorder(null) .addCell( new Cell(1, 1).setBorder(null).setWidth(87).setTextAlignment(TextAlignment.CENTER).add(new Paragraph("Unit Price").setFontSize(8)) ) .addCell( new Cell(1, 1).setBorder(null).setWidth(87).setTextAlignment(TextAlignment.CENTER).add(new Paragraph("Amount").setFontSize(8)) ) .addCell( new Cell(1, 1).setBorder(null).setTextAlignment(TextAlignment.CENTER).add(new Paragraph("RM").setFontSize(8)) ) .addCell( new Cell(1, 1).setBorder(null).setTextAlignment(TextAlignment.CENTER).add(new Paragraph("RM").setFontSize(8)) ) ) ); // 商品 for (int i = 0; i < goods.size(); i++) { GoodInfoDto goodInfoDto = goods.get(i); // goodInfoDto.setDiscountedPrice(new BigDecimal("2123122.5")); table.addCell( new Cell(1, 1).setVerticalAlignment(VerticalAlignment.MIDDLE).setTextAlignment(TextAlignment.CENTER).setWidth(50).setBorder(null).add(new Paragraph(String.valueOf(i + 1)).setFont(getChineseFont())) ); table.addCell( new Cell(1, 2).setVerticalAlignment(VerticalAlignment.MIDDLE).setBorder(null).add(new Paragraph(goodInfoDto.getDescription()).setFont(getChineseFont())) ); table.addCell( new Cell(1, 1).setVerticalAlignment(VerticalAlignment.MIDDLE).setTextAlignment(TextAlignment.CENTER).setWidth(50).setBorder(null).add(new Paragraph(String.valueOf(goodInfoDto.getQty())).setFont(getChineseFont())) ); table.addCell( new Cell(1, 2).setWidth(165).setBorder(null).setMargin(0).setPadding(0) .add( new Table(1).setBorder(null).setMargin(0).setPadding(0) .addCell( new Cell(1, 1).setBorder(null).setWidth(87).setTextAlignment(TextAlignment.CENTER).add(new Paragraph(String.valueOf(goodInfoDto.getDiscountedPrice())).setFont(getChineseFont())) ) ) ); table.addCell( new Cell(1, 2).setWidth(165).setBorder(null).setMargin(0).setPadding(0) .add( new Table(2).setBorder(null).setMargin(0).setPadding(0) .addCell( new Cell(1, 1).setBorder(null).setWidth(87).setTextAlignment(TextAlignment.CENTER).add(new Paragraph(String.valueOf(goodInfoDto.getPrice())).setFont(getChineseFont())) ) .addCell( new Cell(1, 1).setBorder(null).setWidth(87).setTextAlignment(TextAlignment.CENTER).add(new Paragraph(String.valueOf(goodInfoDto.getAmount())).setFont(getChineseFont())) ) ) ); } document.add(table); } /** * 供應商 * * @param document * @param goods */ public void drawSupplierGoodsInfo(Document document, List<goodinfodto> goods) { DeviceRgb black = new DeviceRgb(0, 0, 0); DeviceRgb gray = new DeviceRgb(220, 220, 220); // 黑色虛線邊框 DashedBorder grayBorder = new DashedBorder(gray, 0.5F); SolidBorder solidBorder = new SolidBorder(black, 0.5F); Table table = new Table(6).setMarginLeft(10).setMarginRight(10); table.setBorderTop(solidBorder); table.addCell( new Cell(1, 1).setVerticalAlignment(VerticalAlignment.MIDDLE).setTextAlignment(TextAlignment.CENTER).setWidth(50).setBorder(null).setBorderBottom(solidBorder).add(new Paragraph("Item.").setFontSize(8)) ); table.addCell( new Cell(1, 2).setVerticalAlignment(VerticalAlignment.MIDDLE).setTextAlignment(TextAlignment.CENTER).setWidth(300).setBorder(null).setBorderBottom(solidBorder).add(new Paragraph("Description").setFontSize(8)) ); table.addCell( new Cell(1, 1).setWidth(70).setVerticalAlignment(VerticalAlignment.MIDDLE).setTextAlignment(TextAlignment.CENTER).setBorder(null).setBorderBottom(solidBorder).add(new Paragraph("Qty").setFontSize(8)) ); table.addCell( new Cell(1, 2).setWidth(165).setBorder(null).setBorderTop(solidBorder).setBorderBottom(solidBorder) .add( new Table(2).setBorder(null) .addCell( new Cell(1, 1).setBorder(null).setWidth(87).setTextAlignment(TextAlignment.CENTER).add(new Paragraph("Unit Price").setFontSize(8)) ) .addCell( new Cell(1, 1).setBorder(null).setWidth(87).setTextAlignment(TextAlignment.CENTER).add(new Paragraph("Amount").setFontSize(8)) ) .addCell( new Cell(1, 1).setBorder(null).setTextAlignment(TextAlignment.CENTER).add(new Paragraph("RM").setFontSize(8)) ) .addCell( new Cell(1, 1).setBorder(null).setTextAlignment(TextAlignment.CENTER).add(new Paragraph("RM").setFontSize(8)) ) ) ); // 商品 for (int i = 0; i < goods.size(); i++) { GoodInfoDto goodInfoDto = goods.get(i); table.addCell( new Cell(1, 1).setVerticalAlignment(VerticalAlignment.MIDDLE).setTextAlignment(TextAlignment.CENTER).setWidth(50).setBorder(null).add(new Paragraph(String.valueOf(i + 1))) ); table.addCell( new Cell(1, 2).setVerticalAlignment(VerticalAlignment.MIDDLE).setBorder(null).add(new Paragraph(goodInfoDto.getDescription()).setFont(getChineseFont())) ); table.addCell( new Cell(1, 1).setVerticalAlignment(VerticalAlignment.MIDDLE).setTextAlignment(TextAlignment.CENTER).setBorder(null).add(new Paragraph(String.valueOf(goodInfoDto.getQty())).setFont(getChineseFont())) ); table.addCell( new Cell(1, 2).setWidth(165).setBorder(null).setMargin(0).setPadding(0) .add( new Table(2).setBorder(null).setMargin(0).setPadding(0) .addCell( new Cell(1, 1).setBorder(null).setWidth(87).setTextAlignment(TextAlignment.CENTER).add(new Paragraph(String.valueOf(goodInfoDto.getPrice())).setFont(getChineseFont())) ) .addCell( new Cell(1, 1).setBorder(null).setWidth(87).setTextAlignment(TextAlignment.CENTER).add(new Paragraph(String.valueOf(goodInfoDto.getAmount())).setFont(getChineseFont())) ) ) ); } document.add(table); }
-
尾部信息
/** * @param document * @param map * @param remark 訂單備注 * @param type 1.餐廳訂單 2.供應商訂單 */ public void drawEnd(Document document, Map<string, object=""> map, String remark, String type) { DeviceRgb black = new DeviceRgb(0, 0, 0); DeviceRgb gray = new DeviceRgb(220, 220, 220); // 黑色虛線邊框 DashedBorder grayBorder = new DashedBorder(gray, 0.5F); SolidBorder solidBorder = new SolidBorder(black, 0.5F); Table table = new Table(6).setMarginLeft(10).setMarginRight(10); table.setBorder(null).setBorderTop(solidBorder); table.addCell(new Cell(3, 4).setBorder(null).setWidth(300).setTextAlignment(TextAlignment.LEFT).setFontSize(8).add(new Paragraph("RINGGIT MALAYSIA: " + parse(String.valueOf(map.get("subTotal")))))); if (StringUtils.equals(type, "1")) { table.addCell(new Cell(3, 2).setBorder(null).setWidth(200).setMargin(0).setPadding(0).add( new Table(2).setBorder(null).setPadding(0).setMargin(0) .addCell( new Cell(1, 1).setBorder(null).setWidth(100).setTextAlignment(TextAlignment.RIGHT).add(new Paragraph("SUBTOTAL (RM):").setFontSize(8)) ) .addCell( new Cell(1, 1).setBorder(null).setWidth(50).add(new Paragraph(String.valueOf(map.get("subTotal"))).setFontSize(8)) ) .addCell( new Cell(1, 1).setBorder(null).setWidth(100).setTextAlignment(TextAlignment.RIGHT).add(new Paragraph("DELIVERY FEE (RM):").setFontSize(8)) ) .addCell( new Cell(1, 1).setBorder(null).setWidth(50).add(new Paragraph(String.valueOf(map.get("deliveryFee"))).setFontSize(8)) ) .addCell( new Cell(1, 1).setBorder(null).setWidth(100).setTextAlignment(TextAlignment.RIGHT).add(new Paragraph("TAX (RM):").setFontSize(8)) ) .addCell( new Cell(1, 1).setBorder(null).setWidth(50).add(new Paragraph(String.valueOf(map.get("tax"))).setFontSize(8)) ) )); } if (StringUtils.equals(type, "2")) { table.addCell(new Cell(3, 2).setBorder(null).setWidth(200).setMargin(0).setPadding(0).add( new Table(2).setBorder(null).setPadding(0).setMargin(0) .addCell( new Cell(1, 1).setBorder(null).setWidth(100).setTextAlignment(TextAlignment.RIGHT).add(new Paragraph("SUBTOTAL (RM):").setFontSize(8)) ) .addCell( new Cell(1, 1).setBorder(null).setWidth(50).add(new Paragraph(String.valueOf(map.get("subTotal"))).setFontSize(8)) ) .addCell( new Cell(1, 1).setBorder(null).setWidth(100).setTextAlignment(TextAlignment.RIGHT).add(new Paragraph("TAX (RM):").setFontSize(8)) ) .addCell( new Cell(1, 1).setBorder(null).setWidth(50).add(new Paragraph(String.valueOf(map.get("tax"))).setFontSize(8)) ) .addCell( new Cell(1, 1).setBorder(null).setWidth(100).setTextAlignment(TextAlignment.RIGHT).add(new Paragraph("").setFontSize(8)) ) .addCell( new Cell(1, 1).setBorder(null).setWidth(50).add(new Paragraph("").setFontSize(8)) ) )); } table.addCell(new Cell(1, 6).setBorder(null).add( new Table(6).setPadding(0).setMargin(0).setBorder(null).setBorderTop(solidBorder) .addCell(new Cell(1, 1).setBorder(null).setWidth(90).setPadding(0).setMargin(0)) .addCell(new Cell(1, 1).setWidth(90).setBorder(null).setPadding(0).setMargin(0)) .addCell(new Cell(1, 2).setWidth(155).setTextAlignment(TextAlignment.CENTER).setBorder(null).setPadding(0).setMargin(0).add(new Paragraph("E. & O. E."))) .addCell(new Cell(1, 1).setWidth(115).setBorder(null).setPadding(0).setMargin(0).setTextAlignment(TextAlignment.RIGHT).add(new Paragraph("TOTAL (RM):")).setFontSize(8)) .addCell(new Cell(1, 1).setWidth(100).setBorder(null).setPadding(0).setMargin(0).setTextAlignment(TextAlignment.CENTER).add(new Paragraph(String.valueOf(map.get("total"))).setFontSize(8))) ).setPadding(0).setMargin(0)); // 空一行 table.addCell(new Cell(6, 4).setBorder(null).setMarginTop(10).add( new Table(4).setBorder(null).setPadding(0).setMargin(0) .addCell( new Cell(1, 4).setBorder(null).add(new Paragraph("Note:")) ) .addCell( new Cell(5, 4).setBorder(null).add(new Paragraph(remark).setFont(getChineseFont())) ) ) ); table.addCell(new Cell(6, 2).setBorder(null).add( new Table(2).setBorder(null) .addCell(new Cell(1, 1).setBorder(null).setWidth(175).setPaddingLeft(-20).add(new Paragraph(StringUtils.equals("1", type) ? "PAID AMOUNT (RM):" : "").setFontSize(8))) .addCell(new Cell(1, 1).setBorder(null).setWidth(50).setTextAlignment(TextAlignment.CENTER).add(new Paragraph(StringUtils.equals("1", type) ? String.valueOf(map.get("paidAmount")) : "").setFontSize(8))) .addCell(new Cell(1, 1).setBorder(null).setWidth(100).setHeight(9).add(new Paragraph(""))) .addCell(new Cell(1, 1).setBorder(null).setWidth(100).setHeight(9).add(new Paragraph(""))) .addCell(new Cell(1, 1).setBorder(null).setWidth(100).setHeight(9).add(new Paragraph(""))) .addCell(new Cell(1, 1).setBorder(null).setWidth(100).setHeight(9).add(new Paragraph(""))) .addCell(new Cell(1, 1).setBorder(null).setWidth(100).setHeight(9).add(new Paragraph(""))) .addCell(new Cell(1, 1).setBorder(null).setWidth(100).setHeight(9).add(new Paragraph(""))) .addCell(new Cell(1, 1).setBorder(null).setWidth(100).setHeight(9).add(new Paragraph(""))) .addCell(new Cell(1, 1).setBorder(null).setWidth(100).setHeight(9).add(new Paragraph(""))) .addCell(new Cell(1, 1).setBorder(null).setWidth(100).setHeight(9).add(new Paragraph(""))) .addCell(new Cell(1, 1).setBorder(null).setHeight(9).setWidth(100).add(new Paragraph(""))) ) ); table.addCell(new Cell(1, 6).setHeight(10).setBorder(null)); table.addCell(new Cell(1, 6).setBorder(null).setTextAlignment(TextAlignment.LEFT).add( new Paragraph("Thank you for your support. We truly appreciate your business and look forward to serving you again").setFontSize(9))); // 空一行 table.addCell(new Cell(1, 6).setBorder(null).setHeight(50).setVerticalAlignment(VerticalAlignment.BOTTOM).add(new Paragraph("UNITY FRESH SUPPLY SDN. BH"))).setTextAlignment(TextAlignment.RIGHT); document.add(table); }
-
完整代碼
下面代碼還有其他的邏輯,比如說數字金額轉為英文的之類的,但是對功能沒啥影響,不需要的可以刪除
package com.tang.tool; import com.itextpdf.io.font.FontConstants; import com.itextpdf.io.font.PdfEncodings; import com.itextpdf.io.image.ImageDataFactory; import com.itextpdf.kernel.colors.Color; import com.itextpdf.kernel.colors.DeviceRgb; import com.itextpdf.kernel.font.PdfFont; import com.itextpdf.kernel.font.PdfFontFactory; import com.itextpdf.kernel.geom.PageSize; import com.itextpdf.kernel.pdf.PdfDocument; import com.itextpdf.kernel.pdf.PdfWriter; import com.itextpdf.kernel.pdf.canvas.draw.SolidLine; import com.itextpdf.layout.Document; import com.itextpdf.layout.borders.Border; import com.itextpdf.layout.borders.DashedBorder; import com.itextpdf.layout.borders.SolidBorder; import com.itextpdf.layout.element.*; import com.itextpdf.layout.element.Cell; import com.itextpdf.layout.element.Image; import com.itextpdf.layout.element.Paragraph; import com.itextpdf.layout.element.Table; import com.itextpdf.layout.property.AreaBreakType; import com.itextpdf.layout.property.TextAlignment; import com.itextpdf.layout.property.VerticalAlignment; import com.lowagie.text.*; import com.lowagie.text.pdf.BaseFont; import com.lowagie.text.pdf.PdfTable; import com.yx.conf.MyException; import com.yx.dto.BillInfoDto; import com.yx.dto.GoodInfoDto; import freemarker.template.Configuration; import freemarker.template.Template; import freemarker.template.TemplateException; import freemarker.template.TemplateExceptionHandler; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.xhtmlrenderer.pdf.ITextRenderer; import javax.servlet.http.HttpServletResponse; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import java.io.*; import java.math.BigDecimal; import java.net.MalformedURLException; import java.util.*; import java.util.List; import java.util.stream.Collectors; /** * 賬單工具類 */ @Component @Slf4j public class BillUtil { @Autowired private ConfigUtil configUtil; private static final String[] SINGLE_NUM_ARR = new String[]{"", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine"}; //十幾的數字 private static final String[] TEN_NUM_ARR = new String[]{"Ten", "Eleven", "Tweleve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen"}; //整十的數字 private static final String[] TEN_INTEGER_ARR = new String[]{"Ten", "Twenty", "Thirty", "Forty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety"}; /** * 下載賬單 * * @param billInfo */ public void download(BillInfoDto billInfo, HttpServletResponse response) { downloadOrder(billInfo, response, "1"); } /** * 餐廳訂單 * * @param billInfo * @param response */ public void downloadOrder(BillInfoDto billInfo, HttpServletResponse response, String type) { try { String fileName = "upload/" + System.currentTimeMillis() + ".pdf"; PdfWriter writer = new PdfWriter(configUtil.getPath() + fileName); PdfDocument pdf = new PdfDocument(writer); Document document = new Document(pdf, PageSize.A4); document.setBorderTop(new DashedBorder(2)); List<goodinfodto> goodInfo = billInfo.getGoodInfo(); if (goodInfo == null || goodInfo.size() < 1) { throw new MyException("賬單信息不存在"); } int count = (goodInfo.size() + 4) / 5; Map<string, object=""> dataMap = new LinkedHashMap<>(); List<map<string, object="">> pages = new ArrayList<>(count); dataMap.put("pages", pages); for (int i = 1; i <= count; i++) { List<goodinfodto> goods = goodInfo.stream() .skip(5 * (i - 1)) .limit(5).collect(Collectors.toList()); Map<string, object=""> map = new LinkedHashMap<>(8); map.put("billTo", billInfo.getBillTo()); map.put("deliveryAddress", billInfo.getDeliveryAddress()); map.put("name", billInfo.getName()); map.put("tel", billInfo.getTel()); map.put("email", billInfo.getEmail()); map.put("invoiceNo", billInfo.getInvoiceNo()); map.put("area", billInfo.getArea()); map.put("agent", billInfo.getAgent()); map.put("date", billInfo.getDate()); map.put("page", i); map.put("totalPages", count); // 新增一頁,畫頁眉 if (i == 1) { pdf.addNewPage(); } else { nextPage(document); } // 畫頭部 drawOrderTop(document, pdf, type); // 基本信息 drawOrderBaseInfo(document, billInfo, i, count, type); List<map<string, object="">> list = new ArrayList<>(goods.size()); BigDecimal subTotal = BigDecimal.ZERO; for (int j = 0; j < goods.size(); j++) { GoodInfoDto dto = goods.get(j); Map<string, object=""> data = new LinkedHashMap<>(5); data.put("qty", dto.getQty()); data.put("description", dto.getDescription()); data.put("price", dto.getPrice()); data.put("amount", dto.getAmount()); data.put("unit", dto.getUnit()); data.put("item", j + 1); list.add(data); subTotal = subTotal.add(dto.getAmount()); } // 商品列表 if (StringUtils.equals(type, "1")) { drawMerchantGoodsInfo(document, goods); } else if (StringUtils.equals(type, "2")) { drawSupplierGoodsInfo(document, goods); } map.put("subTotal", subTotal); map.put("deliveryFee", billInfo.getDeliveryFee()); map.put("tax", billInfo.getTax()); BigDecimal total = subTotal.add(billInfo.getDeliveryFee()).add(billInfo.getTax()); map.put("total", total); map.put("upperTotal", parse(total + "")); map.put("paidAmount", billInfo.getPaidAmount()); map.put("goodsInfo", list); pages.add(map); // 尾部 drawEnd(document, map, billInfo.getRemark(), type); } document.close(); } catch (IOException e) { e.printStackTrace(); throw new MyException("獲取模板失敗"); } catch (Exception e) { e.printStackTrace(); throw new MyException("獲取模板失敗"); } } /** * 頭部固定位置 * * @param document * @param pdf * @param type 1.餐廳訂單 2.供應商訂單 * @throws MalformedURLException */ private void drawOrderTop(Document document, PdfDocument pdf, String type) throws MalformedURLException { DeviceRgb black = new DeviceRgb(0, 0, 0); DeviceRgb gray = new DeviceRgb(220, 220, 220); // 黑色虛線邊框 DashedBorder grayBorder = new DashedBorder(gray, 0.5F); Table table = new Table(5).setMarginLeft(10).setMarginRight(10); table.setBorder(null); // TODO: 2021/1/8 寫死先 // table.addCell(new Cell().add(new Image(ImageDataFactory.create(configUtil.getStaticUrl() + "/logo.png")).setWidth(25)).setBorder(Border.NO_BORDER)); table.addCell(new Cell(5, 2).add(new Image(ImageDataFactory .create("E:\\Project\\xxx_1.0\\src\\main\\resources\\static\\img\\logo.png")) .setWidth(160)) .setBorder(Border.NO_BORDER)); table.addCell(new Cell(1, 3).setMarginLeft(20) .add(new Paragraph("UNITY FRESH SUPPLY SDN. BHD") .setFontSize(10) .setFontColor(black) .setFixedLeading(13) .setBold().add(new Text(".(1381196-H)").setFontSize(7))) .setWidth(500) .setHeight(13) .setBorder(null) // .setBorderLeft(grayBorder) // .setBorderBottom(grayBorder) .setTextAlignment(TextAlignment.LEFT)); table.addCell(new Cell(1, 3) .add( new Paragraph("Address:") .setFontSize(7) .add(new Text("66, Jalan 5/116b, Kuchai Entrepreneurs Park, ").setFontSize(5)) ) .setHeight(10) .setBorder(null) // .setBorderLeft(grayBorder) // .setBorderBottom(grayBorder) .setTextAlignment(TextAlignment.LEFT)); table.addCell(new Cell(1, 3) .add( new Paragraph() .setFontSize(7) .add(new Text("58200 Kuala Lumpur, Malaysia.").setFontSize(5)) ) .setHeight(10) .setBorder(null) // .setBorderLeft(grayBorder) // .setBorderBottom(grayBorder) .setTextAlignment(TextAlignment.LEFT)); table.addCell(new Cell(1, 3) .add( new Paragraph("Email:") .setFontSize(7) .add(new Text("newpower.my@gmail.com").setFontSize(5)) ) .setHeight(10) .setBorder(null) // .setBorderLeft(grayBorder) // .setBorderBottom(grayBorder) .setTextAlignment(TextAlignment.LEFT)); table.addCell(new Cell(1, 3) .add( new Paragraph("TEL:") .setFontSize(7) .add(new Text("+60 10 280 2037").setFontSize(5)) ) .setHeight(10) .setBorder(null) // .setBorderLeft(grayBorder) // .setBorderBottom(grayBorder) .setTextAlignment(TextAlignment.LEFT)); if (StringUtils.equals(type, "1")) { table.addCell(new Cell(1, 5).add( new Paragraph("ORDER").setFixedLeading(20)) .setFontSize(10) .setHeight(20) .setBold() .setTextAlignment(TextAlignment.RIGHT) .setBorder(null) ); } if (StringUtils.equals(type, "2")) { table.addCell(new Cell(1, 5).add( new Paragraph("PURCHASE ORDER").setFixedLeading(20)) .setFontSize(10) .setHeight(20) .setBold() .setTextAlignment(TextAlignment.RIGHT) .setBorder(null) ); } document.add(table); } /** * @param document * @param billInfo * @param i * @param count * @param type 1.餐廳訂單 2.供應商訂單 */ public void drawOrderBaseInfo(Document document, BillInfoDto billInfo, int i, int count, String type) { DeviceRgb black = new DeviceRgb(0, 0, 0); DeviceRgb gray = new DeviceRgb(220, 220, 220); // 黑色虛線邊框 DashedBorder grayBorder = new DashedBorder(gray, 0.5F); SolidBorder solidBorder = new SolidBorder(black, 0.5F); Table table = new Table(6).setMarginLeft(10).setMarginRight(10); table.setBorder(null); table.addCell( new Cell(8, 4).setBorder(null).setMargin(0).setPadding(0).add( new Table(4).setMargin(0).setPadding(0) .addCell( new Cell(3, 4).setBorder(null).setWidth(300).setMargin(0).setPadding(0).add( new Table(4).setMargin(0).setPadding(0).setBorder(null) .addCell( new Cell(1, 2).setBorder(null).setWidth(228).add(new Paragraph("Bill to:")) ) .addCell( new Cell(1, 2).setBorder(null).setWidth(200).add(new Paragraph("Delivery Address:")) ) .addCell( new Cell(1, 2).setBorder(null).add(new Paragraph(billInfo.getBillName()).setFont(getChineseFont()).setFontSize(8).setHeight(20)) ) .addCell( new Cell(1, 2).setBorder(null).add(new Paragraph(billInfo.getDeliveryAddress()).setFontSize(8).setHeight(20)) ) .addCell( new Cell(1, 2).setBorder(null).add(new Paragraph(billInfo.getBillTo()).setFont(getChineseFont()).setFontSize(8).setHeight(20)) ) .addCell( new Cell(1, 2).setBorder(null).add(new Paragraph(billInfo.getArea()).setFont(getChineseFont()).setFontSize(8).setHeight(20)) ) ) ) .addCell( new Cell(1, 4).setBorder(null) .setBorder(null) .add(new Paragraph("").setHeight(10)) ) .addCell( new Cell(1, 2).setBorder(null) .setBorder(null) // .setBorderRight(solidBorder) .add(new Paragraph("Attn:") .add(new Text(billInfo.getName()).setFont(getChineseFont()).setFontSize(9))) ) .addCell( new Cell(1, 2).setPaddingLeft(10) .setBorder(null) .add(new Paragraph("Attn:") .add(new Text(billInfo.getAgent()).setFont(getChineseFont()).setFontSize(9))) ) .addCell( new Cell(1, 2).setBorder(null) .setBorder(null) // .setBorderRight(solidBorder) .add(new Paragraph("TEL:").setFontSize(10) .add(new Text(billInfo.getTel()).setFont(getChineseFont()).setFontSize(9))) ) .addCell( new Cell(1, 2).setBorder(null) .setBorder(null) .add(new Paragraph("TEL:").setFontSize(10).setPaddingLeft(10) .add(new Text(billInfo.getAgentPhone()).setFont(getChineseFont()).setFontSize(9))) ) .addCell( new Cell(2, 2).setBorder(null) .setBorder(null) .setHeight(40) .add(new Paragraph("Email:").setFontSize(10) .add(new Text(billInfo.getEmail()).setFont(getChineseFont()).setFontSize(9))) ) .addCell( new Cell(2, 2).setBorder(null) .setBorder(null) .setHeight(40) ) ) ); if (StringUtils.equals("1", type)) { table.addCell( new Cell(7, 2) .setBorder(null) .setWidth(160) .add( new Table(2).addCell( new Cell(1, 1).setBorder(null).add( new Paragraph("Order No.:").setFontSize(9)) ).addCell(new Cell(1, 1).setBorder(null).add( new Paragraph(billInfo.getInvoiceNo()).setFontSize(8) )).addCell(new Cell(1, 1).setBorder(null).add( new Paragraph("Area:").setFontSize(9) )).addCell(new Cell(1, 1).setBorder(null).add( new Paragraph(billInfo.getArea()).setFontSize(8).setFont(getChineseFont()) )).addCell(new Cell(1, 1).setBorder(null).add( new Paragraph("Agent:").setFontSize(9) )).addCell(new Cell(1, 1).setBorder(null).add( new Paragraph(billInfo.getAgent()).setFontSize(8).setFont(getChineseFont()) )).addCell(new Cell(1, 1).setBorder(null).add( new Paragraph("Date : ").setFontSize(9) )).addCell(new Cell(1, 1).setBorder(null).add( new Paragraph(billInfo.getDate()).setFontSize(8) )).addCell(new Cell(1, 1).setBorder(null).add( new Paragraph("Terms : ").setFontSize(9) )).addCell(new Cell(1, 1).setBorder(null).add( new Paragraph("Cash").setFontSize(8) )).addCell(new Cell(1, 1).setBorder(null).add( new Paragraph("Page :").setFontSize(9) )).addCell(new Cell(1, 1).setBorder(null).add( new Paragraph(i + "/" + count).setFontSize(8) )).addCell(new Cell(2, 1).setBorder(null).add( new Paragraph("").setFontSize(9) )) ) ); } if (StringUtils.equals("2", type)) { table.addCell( new Cell(7, 2) .setBorder(null) .setWidth(160) .add( new Table(2).addCell( new Cell(1, 1).setBorder(null).add( new Paragraph("Order No.:").setFontSize(9)) ).addCell(new Cell(1, 1).setBorder(null).add( new Paragraph(billInfo.getInvoiceNo()).setFontSize(8) )).addCell(new Cell(1, 1).setBorder(null).add( new Paragraph("Area:").setFontSize(9) )).addCell(new Cell(1, 1).setBorder(null).add( new Paragraph(billInfo.getArea()).setFontSize(8).setFont(getChineseFont()) )).addCell(new Cell(1, 1).setBorder(null).add( new Paragraph("Date : ").setFontSize(9) )).addCell(new Cell(1, 1).setBorder(null).add( new Paragraph(billInfo.getDate()).setFontSize(8) )).addCell(new Cell(1, 1).setBorder(null).add( new Paragraph("Page :").setFontSize(9) )).addCell(new Cell(1, 1).setBorder(null).add( new Paragraph(i + "/" + count).setFontSize(8) )).addCell(new Cell(2, 1).setBorder(null).add( new Paragraph("").setFontSize(9) )).addCell(new Cell(3, 2).setBorder(null).add(new Paragraph(""))) ) ); } document.add(table); } /** * @param document * @param map * @param remark 訂單備注 * @param type 1.餐廳訂單 2.供應商訂單 */ public void drawEnd(Document document, Map<string, object=""> map, String remark, String type) { DeviceRgb black = new DeviceRgb(0, 0, 0); DeviceRgb gray = new DeviceRgb(220, 220, 220); // 黑色虛線邊框 DashedBorder grayBorder = new DashedBorder(gray, 0.5F); SolidBorder solidBorder = new SolidBorder(black, 0.5F); Table table = new Table(6).setMarginLeft(10).setMarginRight(10); table.setBorder(null).setBorderTop(solidBorder); table.addCell(new Cell(3, 4).setBorder(null).setWidth(300).setTextAlignment(TextAlignment.LEFT).setFontSize(8).add(new Paragraph("RINGGIT MALAYSIA: " + parse(String.valueOf(map.get("subTotal")))))); if (StringUtils.equals(type, "1")) { table.addCell(new Cell(3, 2).setBorder(null).setWidth(200).setMargin(0).setPadding(0).add( new Table(2).setBorder(null).setPadding(0).setMargin(0) .addCell( new Cell(1, 1).setBorder(null).setWidth(100).setTextAlignment(TextAlignment.RIGHT).add(new Paragraph("SUBTOTAL (RM):").setFontSize(8)) ) .addCell( new Cell(1, 1).setBorder(null).setWidth(50).add(new Paragraph(String.valueOf(map.get("subTotal"))).setFontSize(8)) ) .addCell( new Cell(1, 1).setBorder(null).setWidth(100).setTextAlignment(TextAlignment.RIGHT).add(new Paragraph("DELIVERY FEE (RM):").setFontSize(8)) ) .addCell( new Cell(1, 1).setBorder(null).setWidth(50).add(new Paragraph(String.valueOf(map.get("deliveryFee"))).setFontSize(8)) ) .addCell( new Cell(1, 1).setBorder(null).setWidth(100).setTextAlignment(TextAlignment.RIGHT).add(new Paragraph("TAX (RM):").setFontSize(8)) ) .addCell( new Cell(1, 1).setBorder(null).setWidth(50).add(new Paragraph(String.valueOf(map.get("tax"))).setFontSize(8)) ) )); } if (StringUtils.equals(type, "2")) { table.addCell(new Cell(3, 2).setBorder(null).setWidth(200).setMargin(0).setPadding(0).add( new Table(2).setBorder(null).setPadding(0).setMargin(0) .addCell( new Cell(1, 1).setBorder(null).setWidth(100).setTextAlignment(TextAlignment.RIGHT).add(new Paragraph("SUBTOTAL (RM):").setFontSize(8)) ) .addCell( new Cell(1, 1).setBorder(null).setWidth(50).add(new Paragraph(String.valueOf(map.get("subTotal"))).setFontSize(8)) ) .addCell( new Cell(1, 1).setBorder(null).setWidth(100).setTextAlignment(TextAlignment.RIGHT).add(new Paragraph("TAX (RM):").setFontSize(8)) ) .addCell( new Cell(1, 1).setBorder(null).setWidth(50).add(new Paragraph(String.valueOf(map.get("tax"))).setFontSize(8)) ) .addCell( new Cell(1, 1).setBorder(null).setWidth(100).setTextAlignment(TextAlignment.RIGHT).add(new Paragraph("").setFontSize(8)) ) .addCell( new Cell(1, 1).setBorder(null).setWidth(50).add(new Paragraph("").setFontSize(8)) ) )); } table.addCell(new Cell(1, 6).setBorder(null).add( new Table(6).setPadding(0).setMargin(0).setBorder(null).setBorderTop(solidBorder) .addCell(new Cell(1, 1).setBorder(null).setWidth(90).setPadding(0).setMargin(0)) .addCell(new Cell(1, 1).setWidth(90).setBorder(null).setPadding(0).setMargin(0)) .addCell(new Cell(1, 2).setWidth(155).setTextAlignment(TextAlignment.CENTER).setBorder(null).setPadding(0).setMargin(0).add(new Paragraph("E. & O. E."))) .addCell(new Cell(1, 1).setWidth(115).setBorder(null).setPadding(0).setMargin(0).setTextAlignment(TextAlignment.RIGHT).add(new Paragraph("TOTAL (RM):")).setFontSize(8)) .addCell(new Cell(1, 1).setWidth(100).setBorder(null).setPadding(0).setMargin(0).setTextAlignment(TextAlignment.CENTER).add(new Paragraph(String.valueOf(map.get("total"))).setFontSize(8))) ).setPadding(0).setMargin(0)); // 空一行 table.addCell(new Cell(6, 4).setBorder(null).setMarginTop(10).add( new Table(4).setBorder(null).setPadding(0).setMargin(0) .addCell( new Cell(1, 4).setBorder(null).add(new Paragraph("Note:")) ) .addCell( new Cell(5, 4).setBorder(null).add(new Paragraph(remark).setFont(getChineseFont())) ) ) ); table.addCell(new Cell(6, 2).setBorder(null).add( new Table(2).setBorder(null) .addCell(new Cell(1, 1).setBorder(null).setWidth(175).setPaddingLeft(-20).add(new Paragraph(StringUtils.equals("1", type) ? "PAID AMOUNT (RM):" : "").setFontSize(8))) .addCell(new Cell(1, 1).setBorder(null).setWidth(50).setTextAlignment(TextAlignment.CENTER).add(new Paragraph(StringUtils.equals("1", type) ? String.valueOf(map.get("paidAmount")) : "").setFontSize(8))) .addCell(new Cell(1, 1).setBorder(null).setWidth(100).setHeight(9).add(new Paragraph(""))) .addCell(new Cell(1, 1).setBorder(null).setWidth(100).setHeight(9).add(new Paragraph(""))) .addCell(new Cell(1, 1).setBorder(null).setWidth(100).setHeight(9).add(new Paragraph(""))) .addCell(new Cell(1, 1).setBorder(null).setWidth(100).setHeight(9).add(new Paragraph(""))) .addCell(new Cell(1, 1).setBorder(null).setWidth(100).setHeight(9).add(new Paragraph(""))) .addCell(new Cell(1, 1).setBorder(null).setWidth(100).setHeight(9).add(new Paragraph(""))) .addCell(new Cell(1, 1).setBorder(null).setWidth(100).setHeight(9).add(new Paragraph(""))) .addCell(new Cell(1, 1).setBorder(null).setWidth(100).setHeight(9).add(new Paragraph(""))) .addCell(new Cell(1, 1).setBorder(null).setWidth(100).setHeight(9).add(new Paragraph(""))) .addCell(new Cell(1, 1).setBorder(null).setHeight(9).setWidth(100).add(new Paragraph(""))) ) ); table.addCell(new Cell(1, 6).setHeight(10).setBorder(null)); table.addCell(new Cell(1, 6).setBorder(null).setTextAlignment(TextAlignment.LEFT).add( new Paragraph("Thank you for your support. We truly appreciate your business and look forward to serving you again").setFontSize(9))); // 空一行 table.addCell(new Cell(1, 6).setBorder(null).setHeight(50).setVerticalAlignment(VerticalAlignment.BOTTOM).add(new Paragraph("UNITY FRESH SUPPLY SDN. BH"))).setTextAlignment(TextAlignment.RIGHT); document.add(table); } /** * 餐廳 * * @param document * @param goods */ public void drawMerchantGoodsInfo(Document document, List<goodinfodto> goods) { DeviceRgb black = new DeviceRgb(0, 0, 0); DeviceRgb gray = new DeviceRgb(220, 220, 220); // 黑色虛線邊框 DashedBorder grayBorder = new DashedBorder(gray, 0.5F); SolidBorder solidBorder = new SolidBorder(black, 0.5F); Table table = new Table(7).setMarginLeft(10).setMarginRight(10); table.setBorderTop(solidBorder); table.addCell( new Cell(1, 1).setVerticalAlignment(VerticalAlignment.MIDDLE).setTextAlignment(TextAlignment.CENTER).setWidth(50).setBorder(null).setBorderBottom(solidBorder).add(new Paragraph("Item.").setFontSize(8)) ); table.addCell( new Cell(1, 2).setVerticalAlignment(VerticalAlignment.MIDDLE).setTextAlignment(TextAlignment.CENTER).setWidth(300).setBorder(null).setBorderBottom(solidBorder).add(new Paragraph("Description").setFontSize(8)) ); table.addCell( new Cell(1, 1).setWidth(70).setVerticalAlignment(VerticalAlignment.MIDDLE).setTextAlignment(TextAlignment.CENTER).setBorder(null).setBorderBottom(solidBorder).add(new Paragraph("Qty").setFontSize(8)) ); table.addCell( new Cell(1, 2).setWidth(165).setBorder(null).setBorderTop(solidBorder).setBorderBottom(solidBorder) .add( new Table(1).setBorder(null) .addCell( new Cell(1, 1).setBorder(null).setWidth(87).setTextAlignment(TextAlignment.CENTER).add(new Paragraph("Discounted Price").setFontSize(8)) ) .addCell( new Cell(1, 1).setBorder(null).setTextAlignment(TextAlignment.CENTER).add(new Paragraph("RM").setFontSize(8)) ) ) ); table.addCell( new Cell(1, 2).setWidth(165).setBorder(null).setBorderTop(solidBorder).setBorderBottom(solidBorder) .add( new Table(2).setBorder(null) .addCell( new Cell(1, 1).setBorder(null).setWidth(87).setTextAlignment(TextAlignment.CENTER).add(new Paragraph("Unit Price").setFontSize(8)) ) .addCell( new Cell(1, 1).setBorder(null).setWidth(87).setTextAlignment(TextAlignment.CENTER).add(new Paragraph("Amount").setFontSize(8)) ) .addCell( new Cell(1, 1).setBorder(null).setTextAlignment(TextAlignment.CENTER).add(new Paragraph("RM").setFontSize(8)) ) .addCell( new Cell(1, 1).setBorder(null).setTextAlignment(TextAlignment.CENTER).add(new Paragraph("RM").setFontSize(8)) ) ) ); // 商品 for (int i = 0; i < goods.size(); i++) { GoodInfoDto goodInfoDto = goods.get(i); // goodInfoDto.setDiscountedPrice(new BigDecimal("2123122.5")); table.addCell( new Cell(1, 1).setVerticalAlignment(VerticalAlignment.MIDDLE).setTextAlignment(TextAlignment.CENTER).setWidth(50).setBorder(null).add(new Paragraph(String.valueOf(i + 1)).setFont(getChineseFont())) ); table.addCell( new Cell(1, 2).setVerticalAlignment(VerticalAlignment.MIDDLE).setBorder(null).add(new Paragraph(goodInfoDto.getDescription()).setFont(getChineseFont())) ); table.addCell( new Cell(1, 1).setVerticalAlignment(VerticalAlignment.MIDDLE).setTextAlignment(TextAlignment.CENTER).setWidth(50).setBorder(null).add(new Paragraph(String.valueOf(goodInfoDto.getQty())).setFont(getChineseFont())) ); table.addCell( new Cell(1, 2).setWidth(165).setBorder(null).setMargin(0).setPadding(0) .add( new Table(1).setBorder(null).setMargin(0).setPadding(0) .addCell( new Cell(1, 1).setBorder(null).setWidth(87).setTextAlignment(TextAlignment.CENTER).add(new Paragraph(String.valueOf(goodInfoDto.getDiscountedPrice())).setFont(getChineseFont())) ) ) ); table.addCell( new Cell(1, 2).setWidth(165).setBorder(null).setMargin(0).setPadding(0) .add( new Table(2).setBorder(null).setMargin(0).setPadding(0) .addCell( new Cell(1, 1).setBorder(null).setWidth(87).setTextAlignment(TextAlignment.CENTER).add(new Paragraph(String.valueOf(goodInfoDto.getPrice())).setFont(getChineseFont())) ) .addCell( new Cell(1, 1).setBorder(null).setWidth(87).setTextAlignment(TextAlignment.CENTER).add(new Paragraph(String.valueOf(goodInfoDto.getAmount())).setFont(getChineseFont())) ) ) ); } document.add(table); } /** * 供應商 * * @param document * @param goods */ public void drawSupplierGoodsInfo(Document document, List<goodinfodto> goods) { DeviceRgb black = new DeviceRgb(0, 0, 0); DeviceRgb gray = new DeviceRgb(220, 220, 220); // 黑色虛線邊框 DashedBorder grayBorder = new DashedBorder(gray, 0.5F); SolidBorder solidBorder = new SolidBorder(black, 0.5F); Table table = new Table(6).setMarginLeft(10).setMarginRight(10); table.setBorderTop(solidBorder); table.addCell( new Cell(1, 1).setVerticalAlignment(VerticalAlignment.MIDDLE).setTextAlignment(TextAlignment.CENTER).setWidth(50).setBorder(null).setBorderBottom(solidBorder).add(new Paragraph("Item.").setFontSize(8)) ); table.addCell( new Cell(1, 2).setVerticalAlignment(VerticalAlignment.MIDDLE).setTextAlignment(TextAlignment.CENTER).setWidth(300).setBorder(null).setBorderBottom(solidBorder).add(new Paragraph("Description").setFontSize(8)) ); table.addCell( new Cell(1, 1).setWidth(70).setVerticalAlignment(VerticalAlignment.MIDDLE).setTextAlignment(TextAlignment.CENTER).setBorder(null).setBorderBottom(solidBorder).add(new Paragraph("Qty").setFontSize(8)) ); table.addCell( new Cell(1, 2).setWidth(165).setBorder(null).setBorderTop(solidBorder).setBorderBottom(solidBorder) .add( new Table(2).setBorder(null) .addCell( new Cell(1, 1).setBorder(null).setWidth(87).setTextAlignment(TextAlignment.CENTER).add(new Paragraph("Unit Price").setFontSize(8)) ) .addCell( new Cell(1, 1).setBorder(null).setWidth(87).setTextAlignment(TextAlignment.CENTER).add(new Paragraph("Amount").setFontSize(8)) ) .addCell( new Cell(1, 1).setBorder(null).setTextAlignment(TextAlignment.CENTER).add(new Paragraph("RM").setFontSize(8)) ) .addCell( new Cell(1, 1).setBorder(null).setTextAlignment(TextAlignment.CENTER).add(new Paragraph("RM").setFontSize(8)) ) ) ); // 商品 for (int i = 0; i < goods.size(); i++) { GoodInfoDto goodInfoDto = goods.get(i); table.addCell( new Cell(1, 1).setVerticalAlignment(VerticalAlignment.MIDDLE).setTextAlignment(TextAlignment.CENTER).setWidth(50).setBorder(null).add(new Paragraph(String.valueOf(i + 1))) ); table.addCell( new Cell(1, 2).setVerticalAlignment(VerticalAlignment.MIDDLE).setBorder(null).add(new Paragraph(goodInfoDto.getDescription()).setFont(getChineseFont())) ); table.addCell( new Cell(1, 1).setVerticalAlignment(VerticalAlignment.MIDDLE).setTextAlignment(TextAlignment.CENTER).setBorder(null).add(new Paragraph(String.valueOf(goodInfoDto.getQty())).setFont(getChineseFont())) ); table.addCell( new Cell(1, 2).setWidth(165).setBorder(null).setMargin(0).setPadding(0) .add( new Table(2).setBorder(null).setMargin(0).setPadding(0) .addCell( new Cell(1, 1).setBorder(null).setWidth(87).setTextAlignment(TextAlignment.CENTER).add(new Paragraph(String.valueOf(goodInfoDto.getPrice())).setFont(getChineseFont())) ) .addCell( new Cell(1, 1).setBorder(null).setWidth(87).setTextAlignment(TextAlignment.CENTER).add(new Paragraph(String.valueOf(goodInfoDto.getAmount())).setFont(getChineseFont())) ) ) ); } document.add(table); } /** * 金額轉英文 * * @param x * @return */ public String parse(String x) { if (Double.parseDouble(x) <= 0) { return "Zero Cents only"; } int z = x.indexOf("."); // 取小數點位置 String lstr = "", rstr = ""; if (z > -1) { // 看是否有小數,如果有,則分別取左邊和右邊 lstr = x.substring(0, z); rstr = x.substring(z + 1); } else // 否則就是全部 { lstr = x; } String lstrrev = reverse(lstr); // 對左邊的字串取反 String[] a = new String[5]; // 定義5個字串變量來存放解析出來的叄位一組的字串 switch (lstrrev.length() % 3) { case 1: lstrrev += "00"; break; case 2: lstrrev += "0"; break; } String lm = ""; // 用來存放轉換後的整數部分 for (int i = 0; i < lstrrev.length() / 3; i++) { a[i] = reverse(lstrrev.substring(3 * i, 3 * i + 3)); // 截取第一個叄位 if (!a[i].equals("000")) { // 用來避免這種情況:1000000 = one million if (i != 0) { lm = transThree(a[i]) + " " + parseMore(String.valueOf(i)) + " " + lm; // 加: } // thousand、million、billion else { lm = transThree(a[i]); // 防止i=0時, 在多加兩個空格. } } else { lm += transThree(a[i]); } } String xs = ""; // 用來存放轉換後小數部分 if (z > -1) { String transTwo = transTwo(rstr); if (transTwo == null || "".equals(transTwo)) { xs = ""; } else { xs = "and " + transTwo + " Cents "; // 小數部分存在時轉換小數 } } return lm.trim() + " " + xs + "only"; } private String parseFirst(String s) { //String[] a = new String[] { "", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine" }; return SINGLE_NUM_ARR[Integer.parseInt(s.substring(s.length() - 1))]; } private String parseTeen(String s) { //String[] a = new String[] { "Ten", "Eleven", "Tweleve", "Thirteen", "Fourteen", "Fifteen", "Sixteen","Seventeen", "Eighteen", "Nineteen" }; return TEN_NUM_ARR[Integer.parseInt(s) - 10]; } private String parseTen(String s) { //String[] a = new String[] { "Ten", "Twenty", "Thirty", "Forty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety" }; return TEN_INTEGER_ARR[Integer.parseInt(s.substring(0, 1)) - 1]; } // 兩位 private String transTwo(String s) { String value = ""; // 判斷位數 if (s.length() > 2) { s = s.substring(0, 2); } else if (s.length() < 2) { s = s + "0"; } if (s.startsWith("0")) // 07 - seven 是否小於10 { value = parseFirst(s); } else if (s.startsWith("1")) // 17 seventeen 是否在10和20之間 { value = parseTeen(s); } else if (s.endsWith("0")) // 是否在10與100之間的能被10整除的數 { value = parseTen(s); } else { value = parseTen(s) + " " + parseFirst(s); } return value; } private String parseMore(String s) { String[] a = new String[]{"", "Thousand", "Million", "Billion"}; return a[Integer.parseInt(s)]; } // 制作叄位的數 // s.length = 3 private String transThree(String s) { String value = ""; if (s.startsWith("0")) // 是否小於100 { value = transTwo(s.substring(1)); } else if (s.substring(1).equals("00")) // 是否被100整除 { value = parseFirst(s.substring(0, 1)) + " Hundred"; } else { value = parseFirst(s.substring(0, 1)) + " Hundred and " + transTwo(s.substring(1)); } return value; } private String reverse(String s) { char[] aChr = s.toCharArray(); StringBuffer tmp = new StringBuffer(); for (int i = aChr.length - 1; i >= 0; i--) { tmp.append(aChr[i]); } return tmp.toString(); } /** * 獲取中文字體 * * @return */ private static PdfFont getChineseFont() { try { return PdfFontFactory.createFont("STSongStd-Light", "UniGB-UCS2-H", false); } catch (IOException e) { e.printStackTrace(); throw new MyException("獲取中文字體失敗"); } } /** * 新增一頁 * * @param document */ public static void nextPage(Document document) { document.add(new AreaBreak(AreaBreakType.NEXT_PAGE)); } }
dto
package com.tang.dto; import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.math.BigDecimal; import java.util.List; @Data public class BillInfoDto { @ApiModelProperty(value = "公司地址") private String billTo; @ApiModelProperty("公司名稱——餐廳訂單使用") private String billName = ""; @ApiModelProperty(value = "餐廳名稱及餐廳地址") private String deliveryAddress @ApiModelProperty(value = "聯系人姓名") private String name; @ApiModelProperty(value = "聯系人電話") private String tel; @ApiModelProperty(value = "郵件") private String email; // @ApiModelProperty(value = "發票號碼") private String invoiceNo; @ApiModelProperty(value = "配送地址") private String area; @ApiModelProperty(value = "配送人") private String agent; @ApiModelProperty("配送人聯系方式——餐廳訂單使用") private String agentPhone = ""; @ApiModelProperty(value = "日期") @JsonFormat(pattern = "dd/MM/yyyy") private String date; // @ApiModelProperty(value = "金額英文大寫") // private BigDecimal upperTotal; @ApiModelProperty(value = "小計") private BigDecimal subTotal; @ApiModelProperty(value = "配送費") private BigDecimal deliveryFee; @ApiModelProperty(value = "稅費") private BigDecimal tax; @ApiModelProperty(value = "總計") private BigDecimal total; @ApiModelProperty(value = "實際支付費用") private BigDecimal paidAmount; @ApiModelProperty("訂單備注") private String remark = ""; @ApiModelProperty(value = "商品信息") private List<goodinfodto> goodInfo; }
dto
package com.tang.dto; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.math.BigDecimal; @Data public class GoodInfoDto { @ApiModelProperty(value = "Description") private String description; @ApiModelProperty(value = "Qty(數量)") private Integer qty; @ApiModelProperty(value = "Qty(單位)") private String unit; @ApiModelProperty(value = "Price/Unit") private BigDecimal price; @ApiModelProperty(value = "Amount") private BigDecimal amount; @ApiModelProperty(value = "折后價(供應商訂單使用)") private BigDecimal discountedPrice = BigDecimal.ZERO; }
-
最后
寫到最后才發現有個pdftable的類,操作起來更方便,以后有機會再修改。歡迎各位一起學習。
貼張分頁的效果圖