<dependency>
<groupId>com.github.librepdf</groupId>
<artifactId>openpdf</artifactId>
<version>1.3.35</version>
</dependency>
package org.lyy.security;
import java.awt.Color;
import java.io.FileOutputStream;
import java.io.IOException;
import org.apache.commons.lang3.StringUtils;
import com.lowagie.text.Cell;
import com.lowagie.text.Chunk;
import com.lowagie.text.Document;
import com.lowagie.text.Element;
import com.lowagie.text.Font;
import com.lowagie.text.HeaderFooter;
import com.lowagie.text.Image;
import com.lowagie.text.PageSize;
import com.lowagie.text.Paragraph;
import com.lowagie.text.Phrase;
import com.lowagie.text.Rectangle;
import com.lowagie.text.Table;
import com.lowagie.text.alignment.HorizontalAlignment;
import com.lowagie.text.alignment.VerticalAlignment;
import com.lowagie.text.pdf.BaseFont;
import com.lowagie.text.pdf.PdfContentByte;
import com.lowagie.text.pdf.PdfWriter;
import com.lowagie.text.pdf.draw.DottedLineSeparator;
import lombok.extern.slf4j.Slf4j;
import static com.lowagie.text.Font.BOLD;
import static com.lowagie.text.Font.UNDEFINED;
@Slf4j
public class OpenPdfTest {
public static BaseFont MSYH;
public static BaseFont MSYHL;
public static Font MSYHL_TEXT_BOLD;
public static Font MSYHL_TEXT;
static {
try {
MSYH = BaseFont.createFont("fonts/msyh.ttc,0", BaseFont.IDENTITY_H, true);
MSYHL = BaseFont.createFont("fonts/msyhl.ttc,0", BaseFont.IDENTITY_H, true);
MSYHL_TEXT_BOLD = new Font(MSYHL, 10, BOLD);
MSYHL_TEXT = new Font(MSYHL, 10f);
} catch (IOException ex) {
log.info("font not find", ex);
}
}
public static void main(String[] args) throws Exception {
String pdfFile = "C:\\bak11\\v3\\statement.pdf";
// 设置第一页为A3大小
Document document = new Document(PageSize.A3);
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(pdfFile));
// 添加页脚
HeaderFooter footer = new HeaderFooter(new Phrase("2023/12/25 Privacy Statement of Confirmation Letter with Supplier Bank Information Page", MSYHL_TEXT), true);
footer.setAlignment(Element.ALIGN_CENTER);
footer.setBorder(Rectangle.NO_BORDER);
document.setFooter(footer);
// 打开文档
document.open();
// 绘制第一页的表格内容
addTable(document);
// 设置第二页为A4大小
document.setPageSize(PageSize.A4);
// 另起一页
document.newPage();
// 绘制第二页的内容
addStatement(document);
addRectangle(writer, document);
// 关闭文档流
document.close();
log.info("=========done=========");
}
private static void addRectangle(PdfWriter writer, Document document) throws IOException {
PdfContentByte canvas = writer.getDirectContentUnder();
Rectangle rect = new Rectangle(40, 102, 420, 121);
rect.setBackgroundColor(Color.RED);
canvas.rectangle(rect);
Image image = Image.getInstance(ClassLoader.getSystemResource("img/checkbox.png"));
image.scaleAbsolute(18, 18);
image.setAbsolutePosition(42, 103);
document.add(image);
}
private static void addStatement(Document document) {
Table table = new Table(1);
setTableStyle(table);
table.setWidth(100);
Paragraph text1 = new Paragraph("关于供应商银行信息确认函的隐私声明", new Font(MSYHL, 8, BOLD));
text1.setIndentationLeft(188);
Cell cell = new Cell(text1);
cell.setHorizontalAlignment(HorizontalAlignment.LEFT);
cell.setVerticalAlignment(VerticalAlignment.CENTER);
cell.setBorder(Rectangle.BOX);
cell.setBorderWidth(1);
Paragraph text2 = new Paragraph("本隐私声明适用于供应商银行确认函上收集和使用的个人信息。与您的公司有合同关系的XXXXX关联公司(以下简称“XXXXX”、“我们”、" +
"“我们的”或“我们的”)将通过以下方式处理通过银行信息函收集的个人信息。作为数据管理者,我们了解您隐私的重要性。 在您提供包" +
"含供应商银行信息的确认函之前,请花时间仔细阅读本隐私声明,以了解我们将如何使用您的个人数据。\n" +
"1. 我们收集关于您的哪些数据?\n" +
"我们将收集您直接提供给我们的贵公司联系人的个人信息,包括姓名、通讯电话和电子邮箱地址。\n" +
"注意:请确保您在向我们提供上述信息前已获得相关员工的同意。 如贵司通讯人员有变动,请通知我们更改通讯人员资料。\n" +
"2. 我们如何使用您的数据\n" +
"我们会将您的信息用于以下目的:\n" +
"1)向供应商发送付款通知,以便供应商获取信息并进行对帐。\n" +
"2)供应商对账:我们会向供应商邮箱发送对账请求,完成对账/核对,提高业务透明度和供应商与我们的合作关系。\n" +
"3. 我们如何存储您的数据?\n" +
"供应商银行信息确认函中收集的个人信息将保存在位于中国的服务器上。 您在此同意我们出于第 2 节中规定的目的在相关员工居住的国家/" +
"地区之外共享和/或转移相关员工的个人数据,并且 XXXXX 遵守所有适用的法律要求来保护这些个人数据。" +
"我们保留您的个人数据的时间不会超过本声明中定义的目的所必需的时间。\n" +
"4. 如何联系我们?\n" +
"如果您需要行使您的隐私权、提出投诉或隐私保护问题,请访问隐私问题页面(https://www.XXXXXXX.com/cn/privacy/feedback/),我们会" +
"尽快回复。\n" +
"如果您想了解更多荣耀的隐私承诺,请阅读我们的全球隐私政策 (https://www.XXXXXXX.com/cn/privacy/privacy-policy/)。", new Font(MSYHL, 8, BOLD));
text2.setLeading(13, 13);
cell.add(text2);
Paragraph text3 = new Paragraph("Privacy Statement of Confirmation Letter with Supplier Bank Information", new Font(MSYH, 8));
text3.setLeading(25);
text3.setIndentationLeft(120);
cell.add(text3);
Paragraph text4 = new Paragraph("This privacy statement applies to the information collected and used by this Confirmation Letter with Supplier Bank Information. " +
"XXXXX affiliated company (hereinafter referred to as \"XXXXX\", \"we\", \"us\" or \"our\"), which has a contractual relationship with your " +
"company and processes the collected information, will be the data controller of the personal information collected through this " +
"Confirmation Letter, and requires suppliers to provide Confirmation Letter with Supplier Bank Information which contains the " +
"necessary information for supplier payments.\n" +
"As the data controller, we understand the importance of your privacy. Please take the time to read this Privacy Statement carefully " +
"to understand how we will use your personal data before you provide the Confirmation Letter with Supplier Bank Information.\n\n", new Font(MSYH, 8));
text4.setLeading(13, 13);
cell.add(text4);
Paragraph text5 = new Paragraph("1. What Data Do We Collect About You?\n" +
"We will collect the personal information of the correspondent person at your company that you have directly provided to us, " +
"including his/her name, correspondence phone number and email address." +
"Note: please ensure that you have obtained the relevant employee’s consent before providing the above information to us. If the " +
"correspondent personnel at your company have changed, please inform us to change the information of the correspondent " +
"personnel. \n" +
"2. How Do We Use Your Data\n" +
"We will use your information for the following purposes:\n" +
"1)To send payment notices to suppliers so that suppliers can obtain information and perform account reconciliation.\n" +
"2)Supplier Account Reconciliation: We will send an account reconciliation request to suppliers’ email to complete account " +
"reconciliation/account check, so as to improve the business transparency and the cooperation relationship between suppliers and " +
"us.\n" +
"3. How Do We Store Your Data?\n" +
"The personal information collected in Confirmation Letter with Supplier Bank Information will be kept on the server located in " +
"China. You hereby agree and give your consent for us to share and/or transfer relevant employees’ personal data outside the " +
"country where they live for the purposes set out in Section 2, and XXXXX complies with all applicable legal requirements to " +
"safeguard these personal data.\n" +
"We will retain your personal data for no longer than is necessary for the purposes defined in this Statement.\n" +
"4. How to Contact Us?\n" +
"If you need to exercise your privacy rights, lodge a complaint, or consult with our Data Protection Officer (DPO) about privacy " +
"protection, please contact us by visiting the Privacy Questions page (https://www.XXXXXXX.com/global/privacy/feedback/), we will " +
"reply as soon as possible.\n" +
"If you want to learn more about XXXXX’s privacy commitments in general, please read our Global Privacy Policy " +
"(https://www.XXXXXXX.com/global/privacy/privacy-policy).", new Font(MSYH, 8));
text5.setLeading(13, 13);
cell.add(text5);
Paragraph text6 = new Paragraph("同意,本人已阅读“隐私声明”的内容 Agree. I have read the Privacy Statement.", new Font(MSYH, 9));
text6.setLeading(20);
text6.setIndentationLeft(24);
cell.add(text6);
table.addCell(cell);
document.add(table);
}
/**
* 添加表格
* 表格有两个基本的元素:Table和Cell,其中Table可以认为是一张画布,Cell是放置于其上的拼图。这就是OpenPDF中表格的基本结构
*
* @param document pdf文档对象
*/
private static void addTable(Document document) {
Paragraph title1 = new Paragraph("供应商银行信息确认函版本V3.4.7", new Font(MSYH, 12, BOLD));
title1.setLeading(60);
title1.setAlignment(Element.ALIGN_CENTER);
document.add(title1);
Paragraph title2 = new Paragraph("Confirmation Letter with Supplier Bank InformationVersion V3.4.7", new Font(MSYH, 12, BOLD));
title2.setAlignment(Element.ALIGN_CENTER);
document.add(title2);
Table table = new Table(2);
setTableStyle(table);
table.addCell(createCell("Supplier Basic information(Mandatory)", 2));
table.addCell(createCell("*Supplier Name(供应商名称):Supplier name should be the" +
"same with Business license, for Individual Supplier, the supplier" +
"name should be the same with ID card. May not use the"));
table.addCell(createCell("asdfasdf", false));
table.addCell(createRequiredCell("Supplier Finance Contact Name(供应商财务联系人):"));
table.addCell(createCell("asdfadsf", false));
table.addCell(createRequiredCell("Supplier Finance Contact Email(供应商财务联系人邮箱): It " +
"should be supplier’s email and it’s used to receive XXXXX’s " +
"information related to payment" ));
table.addCell(createCell("12@qq.com", false));
table.addCell(createCell("Supplier tax-registered full address:(供应商税务地址: 如果" +
"是非本币或跨境支付,则需填写英文详细地址。Supplier's " +
"detailed English address , required for cross-border payment or " +
"non-local currency)." ));
table.addCell(createCell(""));
table.addCell(createRequiredCell("Supplier Telephone(供应商联系电话):"));
table.addCell(createCell("135984646546", false));
table.addCell(createCell("Supplier Bank Account Information(Mandatory)", 2));
table.addCell(createRequiredCell("Bank Country/Region:(收款国家/地区) "));
table.addCell(createCell("China", false));
table.addCell(createRequiredCell("Country Code"));
table.addCell(createCell("CN", false));
table.addCell(createCell("Swift Code(BIC):(8 or 11 digits,中国境内付款,付款语言为中" +
"文时,可以不维护SWIFT code;其他情况都应维护)"));
table.addCell(createCell(""));
table.addCell(createRequiredCell("Bank Name:(开户银行)"));
table.addCell(createCell("卓资县农村信用合作联社", false));
table.addCell(createRequiredCell("Branch Number:(联行号12 digits,中国境内付款、境外付人民" +
"币到中国,必须提供联行号\\The correspondent code for China" +
"(CNAPS),China's domestic payment、pay CNY from abroad to " +
"China, must provide the correspondent code.)"));
table.addCell(createCell("402203581020", false));
table.addCell(createRequiredCell("Branch Name:(支行分理处)"));
table.addCell(createCell("总行", false));
table.addCell(createRequiredCell("Account Number:(银行账号)"));
table.addCell(createCell("123132132", false));
table.addCell(createRequiredCell("Account Name:(账户名称)"));
table.addCell(createCell("afasdfasd", false));
table.addCell(createRequiredCell("Currency:(3位币种,如:CNY、USD)"));
table.addCell(createCell("CNY", false));
table.addCell(createCell("Province:(银行所在省份,当币种为CNY时,省份必填)"));
table.addCell(createCell("内蒙古", false));
table.addCell(createCell("City:(银行所在城市,当币种为CNY时,城市必填)"));
table.addCell(createCell("乌兰察布", false));
table.addCell(createCell("Intermediary Bank information (maybe exist while cross border payment):", 2));
table.addCell(createCell("Intermediate Bank Name:(中转银行名称)"));
table.addCell(createCell(""));
table.addCell(createCell("Intermediate Bank Swift Code:(中转银行swift code,8 or 11 digits)"));
table.addCell(createCell(""));
table.addCell(createCell("Intermediate Bank Account Number:(中转银行账号)"));
table.addCell(createCell(""));
table.addCell(createCell("Note/注意:\n" +
"1. Supplier name and beneficiary name must be consistent with relevant business licenses or other equivalent documents.供应商名称和收款人名称必须与营业执照或其他相关支撑文档一致。\n" +
"2.All payments will be made according to the bank information collected on this form, not according to contract or invoices. Please fill it accurately and completely, if" +
"bank information provided wrong, supplier should take responsibility of any payment risk or loss.所有的付款信息都是基于供应商银行信息确认函维护的,而不参考" +
"合同或者发票。请准确完整的填写供应商银行信息确认函。荣耀依据供应商银行信息确认函中提供的银行账户付款即完成付款义务。若因供应商银行信息确认函" +
"提供的银行信息错误给荣耀造成的损失,供应商应负责赔偿并使荣耀免受损失。\n" +
"3. The supplier should immediately notify XXXXX of any changes to their banking information. Without timely or accurate notification, the supplier risks delay of their " +
"payment.如果银行信息有变更,请及时通知荣耀。如果因供应商未及时通知荣耀所带来的付款延迟、付款错误的风险,由供应商承担。\n" +
"4. The Supplier’s financial contact email should be the supplier’s email address, which XXXXX will use to inform supplier of their payment status,请在供应商联系人邮" +
"箱处填写供应商的邮箱。其用途是接收与荣耀付款有关的信息,\n" +
"5. If any doubt of the bank account information, supplier should contact his own bank account manager to get the information.如果对银行信息有任何疑问,供应商" +
"应该联系自己的开户银行经理获取信息。\n" +
"6. If there factoring business with suppliers XXXXX is also required on request \"factoring supplier bank account change request letter.\"如果供应商与荣耀之间有保理" +
"业务,则还需要按要求提供《保理供应商银行账户变更申请函》。", 2, new Font(MSYHL, 8, BOLD)));
table.addCell(createCell("企业供应商签章(开户银行在中国的供应商盖章必须是公章、财务专用章或者合同专用章)不允许电子盖章或签名;个人供应商签章(必须盖章或" +
"者签字)不允许电子盖章或签名;Supplier Seal or signature(Electronic signature will not accepted)\n", 2, new Font(MSYH, 10, BOLD)));
table.addCell(createDottedCell());
table.addCell(createDottedCell());
table.addCell(createDottedCell());
table.addCell(createDottedCell());
table.addCell(createDottedCell("请在此处盖章或签名", 285));
table.addCell(createDottedCell("Please seal or signature this place.", 250));
table.addCell(createDottedCell());
table.addCell(createDottedCell());
document.add(table);
}
/**
* 创建虚线
*
* @param text 文本
* @param indentLeft margin left
* @return Cell
*/
public static Cell createDottedCell(String text, float indentLeft) {
Paragraph paragraph = new Paragraph();
paragraph.setLeading(5);
paragraph.add(new DottedLineSeparator());
Cell cell = new Cell(paragraph);
cell.setColspan(2);
cell.setHorizontalAlignment(HorizontalAlignment.LEFT);
cell.setVerticalAlignment(VerticalAlignment.TOP);
cell.setBorder(Rectangle.NO_BORDER);
cell.setBorderWidth(1);
if(StringUtils.isNotBlank(text)){
Paragraph grayText = new Paragraph(text, new Font(MSYHL, 12, UNDEFINED, Color.LIGHT_GRAY));
grayText.setIndentationLeft(indentLeft);
cell.add(grayText);
}
return cell;
}
/**
* 创建虚线
*
* @return Dotted Cell
*/
public static Cell createDottedCell() {
return createDottedCell("", 0);
}
/**
* 设置表格的数据单元格样式
*
* @param text 单元格内容
*/
public static Cell createCell(String text) {
return createCell(text, 1);
}
/**
* 设置表格的数据单元格样式
*
* @param text 文本
* @param colSpan colSpan
* @return Cell
*/
public static Cell createCell(String text, int colSpan) {
return createCell(text, colSpan, HorizontalAlignment.LEFT);
}
/**
* 设置表格的数据单元格样式
*
* @param text 文本
* @param colSpan colSpan
* @param font 字体
* @return Cell
*/
public static Cell createCell(String text, int colSpan, Font font) {
return createCell(text, colSpan, HorizontalAlignment.LEFT, true, font);
}
/**
* 设置表格的数据单元格样式
*
* @param text 文本
* @param isBold 是否粗体
* @return Cell
*/
public static Cell createCell(String text, boolean isBold) {
return createCell(text, 1, HorizontalAlignment.LEFT, isBold, null);
}
/**
* 设置表格的数据单元格样式
*
* @param text 文本
* @param colSpan colSpan
* @param horizontalAlign 水平对齐方式
* @return Cell
*/
public static Cell createCell(String text, int colSpan, HorizontalAlignment horizontalAlign) {
return createCell(text, colSpan, horizontalAlign, true, null);
}
/**
* 设置表格的数据单元格样式
*
* @param text 文本
* @param colSpan colSpan
* @param horizontalAlign 水平对齐方式
* @param isBold 是否粗体
* @param font 字体
* @return Cell
*/
public static Cell createCell(String text, int colSpan, HorizontalAlignment horizontalAlign, boolean isBold, Font font) {
Font realFont = isBold ? new Font(MSYHL, 10f, BOLD) : new Font(MSYHL, 10f);
if(font != null){
realFont = font;
}
Paragraph paragraph = new Paragraph(text, realFont);
paragraph.setLeading(13, 13);
Cell cell = new Cell(paragraph);
cell.setColspan(colSpan);
// 设置水平对齐方式
cell.setHorizontalAlignment(horizontalAlign);
// 设置垂直对齐方式
cell.setVerticalAlignment(VerticalAlignment.CENTER);
// 设置单元格边框颜色,同样用四个bit位分别表示上(0001)、下(0010)、左(0100)、右(1000)四个边
cell.setBorder(Rectangle.BOX);
cell.setBorderWidth(1);
return cell;
}
/**
* 创建必填的单元格
*
* @param text 文本
* @return Cell
*/
public static Cell createRequiredCell(String text) {
Paragraph paragraph = new Paragraph("");
paragraph.setLeading(12, 12);
paragraph.add(new Chunk("*", new Font(MSYH, 10, BOLD, Color.RED)));
paragraph.add(new Chunk(text, MSYHL_TEXT_BOLD));
Cell cell = new Cell();
cell.add(paragraph);
cell.setHorizontalAlignment(HorizontalAlignment.LEFT);
cell.setVerticalAlignment(VerticalAlignment.CENTER);
cell.setBorder(Rectangle.BOX);
cell.setBorderWidth(1);
return cell;
}
/**
* 设置表格样式
*
* @param table 表格对象
*/
private static void setTableStyle(Table table) {
// 设置表格宽度为100%
table.setWidth(90);
// 表格在页面水平方向的对齐方式
table.setHorizontalAlignment(HorizontalAlignment.CENTER);
// 设置表格边框(仅最外层边框为Table的边框,内部边框属于Cell),同样用四个bit位分别表示上(0001)、下(0010)、左(0100)、右(1000)四个边
table.setBorder(Rectangle.BOX);
// 表格边框宽度
table.setBorderWidth(1);
// 设置该值可以让文字与底部表格线留出一定空间
table.setPadding(3);
// 以下两行一般同时使用:设置默认Cell,使用默认Cell填充空的Cell
table.setDefaultCell(createCell(""));
table.setAutoFillEmptyCells(true);
}
}