最近使用itext生成pdf文件并下载,其中涉及到金额的计算,所以代码比较啰嗦点,maven和代码如下:
<!-- iText -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.11</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
package com.xxx.controller;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;
import lombok.AllArgsConstructor;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
@RestController
@AllArgsConstructor
@RequestMapping("/xxxx")
public class ITextController{
/**
* 大写数字
*/
private static final String[] NUMBERS = {"零", "壹", "贰", "叁", "肆", "伍",
"陆", "柒", "捌", "玖"};
/**
* 整数部分的单位
*/
private static final String[] IUNIT = {"元", "拾", "佰", "仟", "万", "拾", "佰",
"仟", "亿", "拾", "佰", "仟", "万", "拾", "佰", "仟"};
/**
* 小数部分的单位
*/
private static final String[] DUNIT = {"角", "分", "厘"};
@RequestMapping(value = "/itext", method = RequestMethod.GET)
@ResponseBody
public void importExcel(HttpServletResponse response) throws IOException {
OutputStream out = null;
try {
ByteArrayOutputStream baos = createPdf();
//设置请求返回类型
response.setHeader("Content-Disposition", "attachment; filename=" + new String("销售合同.pdf".getBytes(), StandardCharsets.ISO_8859_1));
response.setContentLength(baos.size());
out = response.getOutputStream();
baos.writeTo(out);
out.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
out.close();
}
}
public ByteArrayOutputStream createPdf() throws DocumentException, IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
/* 解决中文无法显示:使用iTextAsian.jar包中的字体 */
BaseFont baseFont = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
Font font_normal = new Font(baseFont, 10, Font.NORMAL);
Font font_bold = new Font(baseFont, 10, Font.BOLD);
/* 第一步 创建文档实例 自定义页面大小使用 */
Document document = new Document(PageSize.A4);
/* 第二步 获取PdfWriter实例 */
PdfWriter.getInstance(document, baos);
document.setMargins(64, 64, 36, 36);
/* 第三步 打开文档 */
document.open();
/* 第四步 添加段落内容 */
Paragraph paragraph = new Paragraph("xxx行业应用服务平台\n" + "销售合同", new Font(baseFont, 18, Font.BOLD));
paragraph.setAlignment(Element.ALIGN_CENTER);
/* 上一段落与下一段落的间距加大10个单位 */
paragraph.setSpacingAfter(10);
document.add(paragraph);
paragraph = new Paragraph("买方(以下简称“甲方”):", font_normal);
document.add(paragraph);
paragraph = new Paragraph("卖方(以下简称“乙方”):xxx有限公司", font_normal);
document.add(paragraph);
paragraph = new Paragraph("根据《中华人民共和国合同法》及相关法律、法规的规定,买卖双方本着友好合作," +
"达成以下协议:", font_normal);
document.add(paragraph);
paragraph = new Paragraph("一、产品名称、数量、价格:", font_bold);
document.add(paragraph);
/* 生成表格 */
PdfPTable table = new PdfPTable(8);
/* 设置表格上面空白宽度 */
table.setSpacingBefore(10f);
table.setTotalWidth(new float[]{36, 88, 88, 88, 50, 56, 56, 56});
/* 锁住宽度 */
table.setLockedWidth(true);
/* 添加表头元素 */
PdfPCell cell = new PdfPCell(new Paragraph("编号", font_bold));
setCellStyle(24, cell);
table.addCell(cell);
cell = new PdfPCell(new Paragraph("名称", font_bold));
setCellStyle(24, cell);
table.addCell(cell);
cell = new PdfPCell(new Paragraph("型号", font_bold));
setCellStyle(24, cell);
table.addCell(cell);
cell = new PdfPCell(new Paragraph("规格", font_bold));
setCellStyle(24, cell);
table.addCell(cell);
cell = new PdfPCell(new Paragraph("单位", font_bold));
setCellStyle(24, cell);
table.addCell(cell);
cell = new PdfPCell(new Paragraph("数量", font_bold));
setCellStyle(24, cell);
table.addCell(cell);
cell = new PdfPCell(new Paragraph("单价(元)", font_bold));
setCellStyle(24, cell);
table.addCell(cell);
cell = new PdfPCell(new Paragraph("总价(元)", font_bold));
setCellStyle(24, cell);
table.addCell(cell);
/* 添加表格的内容 */
BigDecimal amount = new BigDecimal(0);
for (int i = 0; i < 5; i++) {
cell = new PdfPCell(new Paragraph(i + 1 + "", font_normal));
setCellStyle(0, cell);
table.addCell(cell);
cell = new PdfPCell(new Paragraph("工业互联网标识", font_normal));
setCellStyle(0, cell);
table.addCell(cell);
cell = new PdfPCell(new Paragraph("304不锈钢、激光雕刻", font_normal));
setCellStyle(0, cell);
table.addCell(cell);
cell = new PdfPCell(new Paragraph("尺寸:60mm*40mm厚度0.5mm", font_normal));
setCellStyle(0, cell);
table.addCell(cell);
cell = new PdfPCell(new Paragraph("个", font_normal));
setCellStyle(0, cell);
table.addCell(cell);
cell = new PdfPCell(new Paragraph(84 + "", font_normal));
setCellStyle(0, cell);
table.addCell(cell);
cell = new PdfPCell(new Paragraph(12.02 + "", font_normal));
setCellStyle(0, cell);
table.addCell(cell);
BigDecimal quantity = new BigDecimal(84);
BigDecimal price = new BigDecimal(12.02 + "");
BigDecimal total_price = quantity.multiply(price);
amount = amount.add(total_price);
cell = new PdfPCell(new Paragraph(total_price + "", font_normal));
setCellStyle(0, cell);
table.addCell(cell);
}
/* 金额转为大写 */
String total_RMB = convertAmount(amount.toString());
/* 表格总价合计 */
cell = new PdfPCell(new Paragraph("合计人民币(大写):" + total_RMB, font_bold));
cell.setColspan(8);
setCellStyle(24, cell);
table.addCell(cell);
/* 设置表格下面空白宽度 */
table.setSpacingAfter(8f);
document.add(table);
paragraph = new Paragraph("二、质量要求与技术标准:", font_bold);
document.add(paragraph);
paragraph = new Paragraph("执行国家、地方颁发的质量标准和行业标准。供货时附产品说明书、合格证。" +
"乙方保证提供符合合同所规定的质量、规格、型号等要求的全新设备。", font_normal);
document.add(paragraph);
paragraph = new Paragraph("三、付款及交货:", font_bold);
document.add(paragraph);
paragraph = new Paragraph("1、双方签订合同后2个工作日内,乙方开具同等价值发票,甲方付清合同总价款。", font_normal);
document.add(paragraph);
paragraph = new Paragraph("2、乙方收到货款后7个工作日发货。", font_normal);
document.add(paragraph);
paragraph = new Paragraph("3、乙方负责运输并承担运费、甲方负责装卸货费用。", font_normal);
document.add(paragraph);
paragraph = new Paragraph("4、交货地点:双方协议。", font_normal);
document.add(paragraph);
paragraph = new Paragraph("四、设备的包装、发运及运输:", font_bold);
document.add(paragraph);
paragraph = new Paragraph("1、乙方应采用满足产品运输要求的包装,以保证货物安全运输。", font_normal);
document.add(paragraph);
paragraph = new Paragraph("2、产品发货24小时内通知甲方。", font_normal);
document.add(paragraph);
paragraph = new Paragraph("五、其他:", font_bold);
document.add(paragraph);
paragraph = new Paragraph("1、因乙方原因造成的逾期交货,乙方每天按合同总价的万分之五向对方支付违约金。" +
"甲方无正当理由拒收的,应向乙方支付合同总价30%的违约金。因不可抗力导致合同无法执行除外。", font_normal);
document.add(paragraph);
paragraph = new Paragraph("2、本协议在履行过程中,如发生争议,双方友好协商解决,如协商不成,双方由先诉方法院管辖。", font_normal);
document.add(paragraph);
paragraph = new Paragraph("3、本协议自双方签字/盖章之日起生效。本协议一式四份,甲乙双方各执两份,具有同等法律效力。", font_normal);
document.add(paragraph);
/* 生成尾部签字部分的表格 */
table = new PdfPTable(2);
/* 设置表格上面空白宽度 */
table.setSpacingBefore(5f);
table.setTotalWidth(new float[]{271, 200});
/* 锁住宽度 */
table.setLockedWidth(true);
/* 添加签字部分第一行元素 */
setSignStyle("甲方:", table, font_normal);
setSignStyle("乙方:xxx有限公司", table, font_normal);
/* 添加第二行元素 */
setSignStyle("地址:", table, font_normal);
setSignStyle("地址:xxx", table, font_normal);
/* 添加第三行元素 */
setSignStyle("法定代表人:", table, font_normal);
setSignStyle("法定代表人:xxx", table, font_normal);
/* 添加第四行元素 */
setSignStyle("授权代表:", table, font_normal);
setSignStyle("授权代表:", table, font_normal);
/* 添加第五行元素 */
setSignStyle("电话:", table, font_normal);
setSignStyle("电话:xxx", table, font_normal);
/* 添加第六行元素 */
setSignStyle("开户行:", table, font_normal);
setSignStyle("开户行:xxx支行", table, font_normal);
/* 添加第七行元素 */
setSignStyle("帐号:", table, font_normal);
setSignStyle("帐号:xxxx", table, font_normal);
/* 添加第八行元素 */
setSignStyle("税号:", table, font_normal);
setSignStyle("税号:xxxx", table, font_normal);
/* 添加第九行元素 */
setSignStyle(" 年 月 日", table, font_normal);
setSignStyle(" 年 月 日", table, font_normal);
document.add(table);
/* 第五部 操作完成后必须执行文档关闭操作。*/
document.close();
return baos;
}
private String convertAmount(String str) {
/* 去掉"," */
str = str.replaceAll(",", "");
/* 整数部分数字 */
String integerStr;
/* 小数部分数字 */
String decimalStr;
/* 初始化:分离整数部分和小数部分 */
if (str.indexOf(".") > 0) {
integerStr = str.substring(0, str.indexOf("."));
decimalStr = str.substring(str.indexOf(".") + 1);
} else if (str.indexOf(".") == 0) {
integerStr = "";
decimalStr = str.substring(1);
} else {
integerStr = str;
decimalStr = "";
}
/* integerStr去掉首0,不必去掉decimalStr的尾0(超出部分舍去) */
if (!integerStr.equals("")) {
integerStr = Long.toString(Long.parseLong(integerStr));
if (integerStr.equals("0")) {
integerStr = "";
}
}
/* overflow超出处理能力,直接返回 */
if (integerStr.length() > IUNIT.length) {
System.out.println(str + ":超出处理能力");
return str;
}
/* 整数部分数字 */
int[] integers = toArray(integerStr);
/* 设置万单位 */
boolean isMust5 = isMust5(integerStr);
/* 小数部分数字 */
int[] decimals = toArray(decimalStr);
return getChineseInteger(integers, isMust5)
+ getChineseDecimal(decimals);
}
/**
* 整数部分和小数部分转换为数组,从高位至低位
*/
private static int[] toArray(String number) {
int[] array = new int[number.length()];
for (int i = 0; i < number.length(); i++) {
array[i] = Integer.parseInt(number.substring(i, i + 1));
}
return array;
}
/**
* 得到中文金额的整数部分。
*/
private static String getChineseInteger(int[] integers, boolean isMust5) {
StringBuffer chineseInteger = new StringBuffer("");
int length = integers.length;
for (int i = 0; i < length; i++) {
/* 0出现在关键位置:1234(万)5678(亿)9012(万)3456(元) */
/* 特殊情况:10(拾元、壹拾元、壹拾万元、拾万元) */
String key = "";
if (integers[i] == 0) {
/* 万(亿)(必填) */
if ((length - i) == 13)
key = IUNIT[4];
/* 亿(必填) */
else if ((length - i) == 9)
key = IUNIT[8];
/* 万(不必填) */
else if ((length - i) == 5 && isMust5)
key = IUNIT[4];
/* 元(必填) */
else if ((length - i) == 1)
key = IUNIT[0];
/* 0遇非0时补零,不包含最后一位 */
if ((length - i) > 1 && integers[i + 1] != 0)
key += NUMBERS[0];
}
chineseInteger.append(integers[i] == 0 ? key
: (NUMBERS[integers[i]] + IUNIT[length - i - 1]));
}
return chineseInteger.toString();
}
/**
* 得到中文金额的小数部分。
*/
private static String getChineseDecimal(int[] decimals) {
StringBuffer chineseDecimal = new StringBuffer("");
for (int i = 0; i < decimals.length; i++) {
/* 舍去3位小数之后的 */
if (i == 3)
break;
chineseDecimal.append(decimals[i] == 0 ? "" : (NUMBERS[decimals[i]] + DUNIT[i]));
}
return chineseDecimal.toString();
}
/**
* 判断第5位数字的单位"万"是否应加。
*/
private static boolean isMust5(String integerStr) {
int length = integerStr.length();
if (length > 4) {
String subInteger = "";
if (length > 8) {
/* 取得从低位数,第5到第8位的字串 */
subInteger = integerStr.substring(length - 8, length - 4);
} else {
subInteger = integerStr.substring(0, length - 4);
}
return Integer.parseInt(subInteger) > 0;
} else {
return false;
}
}
private void setSignStyle(String str, PdfPTable table, Font font_normal) {
PdfPCell cell = new PdfPCell(new Paragraph(str, font_normal));
cell.setHorizontalAlignment(Element.ALIGN_LEFT);
cell.setBorderColor(BaseColor.WHITE);
table.addCell(cell);
}
private void setCellStyle(int height, PdfPCell cell) {
/* 单元格高度,0时表示随内容动态显示高度 */
if (height != 0) {
cell.setFixedHeight(height);
}
cell.setHorizontalAlignment(Element.ALIGN_CENTER);
cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
}
}