java 操作 PDF

近来收到一个需求, 制作 PDF 制作发票.

类似于制作这样的发票


技术选型我选择java

在网上寻找了一些操作PDF的框架决定用iText制作, 因为它比较活跃, 而且后期做签章和插入图片二维码都有着现成的接口.

大体想了下难点都在什么地方, 插入图片,商品太多时候的分页问题,数字签章........

于是我就开始尝试着使用 iText的新建操作pdf,

新建maven工程

加入依赖

<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.20</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.3.2</version>
</dependency>

起初准备自己画这个table, 后来花了几个都很丑于是参考网上发可以先制作模板,预设表单值再往里面填入表单数据.

具体可以通过Adobe Acrobat Pro去制作


制作好的模板



JAVA操作PDF

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import com.boss.hmc.bean.Commodity;
import com.boss.hmc.bean.Ticket;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Image;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.AcroFields;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;

public class PDFTemplet2Ticket {
//	public static String modelPath = "D:\\work\\pdf\\发票模板123_bak.pdf";
	public static String modelPath = "D:\\work\\pdf\\模板1.pdf";
	public static String modelPath2 = "D:\\work\\pdf\\模板2.pdf";
	private static String imagePath = "D:\\study\\practice\\chapter.png";

	public void ticketInPDF(Ticket ticket, File target) throws IOException, DocumentException {
		if (target == null)
			target.createNewFile();
		PdfReader reader = new PdfReader(modelPath);
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		// 读pdf
		PdfStamper ps = new PdfStamper(reader, bos);
		AcroFields s = ps.getAcroFields();

		ArrayList<BaseFont> fontList = new ArrayList<BaseFont>();
//        BaseFont bf = BaseFont.createFont("STSong-Light","UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
		BaseFont bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_CACHED);

		insertImage(s, "quickMark", ps);

		fontList.add(bf);
		s.setSubstitutionFonts(fontList);

		s.setField("machineIdentificNumber", ticket.getMachineIdentificNumber());
		s.setField("invoiceNumber", ticket.getInvoiceNumber());
		s.setField("invoiceCode", ticket.getInvoiceCode());
		s.setField("consumerPassword", ticket.getConsumerPassword());
		String date = ticket.getInvoiceDate();
		s.setField("invoiceDate",
				new StringBuilder(date.substring(0, 4)).append("    ").append(date.substring(4, 6)).append("    ")
						+ date.substring(6));
		s.setField("checkCode", ticket.getCheckCode());
		s.setField("consumerName", ticket.getConsumerName());
		s.setField("consumerIdentityNumber", ticket.getConsumerIdentityNumber());
		s.setField("consumerAddTel", ticket.getConsumerAddTel());
		s.setField("consumerAccount", ticket.getConsumerAccount());
		s.setField("figure", "¥"+ticket.getFigure() + " .");
		s.setField("tax", "¥"+ticket.getTax() + " .");
		s.setField("sumFigureTax", "¥"+ticket.getSumFigureTax() + " ");
		s.setField("chineseSumFigureTax", ticket.getChineseSumFigureTax());

		List<Commodity> list = ticket.getCommodities();
		if (list != null && list.size() >= 5) {
			s.setField("name0", " (详见销货清单)");
			addDetailItems(list);
		} else if (list != null && list.size() < 5) {
			addItems(list, s);
		}

		s.setField("merchantName", ticket.getMerchantName());
		s.setField("merchantIdentityNumber", ticket.getMerchantIdentityNumber());

		s.setField("merchantAddTel", ticket.getMerchantAddTel());
		s.setField("merchantAccount", ticket.getMerchantAccount());
		s.setField("receiver", ticket.getReceiver());
		s.setField("proofreader", ticket.getProofreader());
		s.setField("drawer", ticket.getDrawer());

		ps.setFormFlattening(true);
		ps.close();

		FileOutputStream fos = new FileOutputStream(target);
		fos.write(bos.toByteArray());
		fos.close();
	}

	private void addDetailItems(List<Commodity> list) throws IOException, DocumentException {
		int size = list.size();
		//每页最多的条数
		int pageSize = 20;
		//总页数
		int total = size/pageSize + (size%pageSize > 0 ? 1 : 0);
		for (int i = 0; i < total; i++) {
			int nowPageSize = pageSize;
			//末页条数
			if(i == total-1) nowPageSize = (size%pageSize == 0 ? pageSize : size % pageSize);
			printEveryDetails(list,i*pageSize,i,nowPageSize,total);
		}
	}
	
	private void printEveryDetails(List<Commodity> list, int start, int page, int size, int total) throws IOException, DocumentException {
		PdfReader reader = new PdfReader(modelPath2);
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		// 读pdf
		PdfStamper ps = new PdfStamper(reader, bos);
		AcroFields s = ps.getAcroFields();
		s.addSubstitutionFont(BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_CACHED));
		for (int i = start,j = 1; i < start+size; i++,j++) {
			Commodity c = list.get(i);
			s.setField("no", j+"");
			s.setField("name" + i, c.getName());
			s.setField("modelType" + i, c.getModelType());
			s.setField("unit" + i, c.getUnit());
			s.setField("count" + i, c.getCount() + "");
			s.setField("price" + i, c.getPrice().toString());
			s.setField("figure" + i, c.getFigure().toString());
			s.setField("taxRate" + i, c.getTaxRate());
			s.setField("taxMoney" + i, c.getTaxMoney() + "");
		}
		ps.setFormFlattening(true);
		ps.close();
		FileOutputStream fos = new FileOutputStream(new File("detail"+page));
		fos.write(bos.toByteArray());
		fos.close();
	}

	private void addItems(List<Commodity> list, AcroFields s) throws IOException, DocumentException {
		for (int i = 0; i < list.size(); i++) {
			Commodity c = list.get(i);
			s.setField("name" + i, c.getName());
			s.setField("modelType" + i, c.getModelType());
			s.setField("unit" + i, c.getUnit());
			s.setField("count" + i, c.getCount() + "");
			s.setField("price" + i, c.getPrice().toString());
			s.setField("figure" + i, c.getFigure().toString());
			s.setField("taxRate" + i, c.getTaxRate());
			s.setField("taxMoney" + i, c.getTaxMoney() + "");
		}
	}

	public static void generatePDF() {
		 PDFMergerUtility PDFmerger = new PDFMergerUtility();
		 
	}
	
	public static void insertImage(AcroFields form, String fieldName, PdfStamper stamper)
			throws DocumentException, IOException {
//		form.addSubstitutionFont(BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED));
		// 通过域名获取所在页和坐标,左下角为起点
		int pageNo = form.getFieldPositions(fieldName).get(0).page;
		Rectangle signRect = form.getFieldPositions(fieldName).get(0).position;
		float x = signRect.getLeft();
		float y = signRect.getBottom();
		// 读图片
		Image image = Image.getInstance(imagePath);
		// 获取操作的页面
		PdfContentByte under = stamper.getOverContent(pageNo);
		// 根据域的大小缩放图片
		image.scaleToFit(signRect.getWidth(), signRect.getHeight());
		// 添加图片
		image.setAbsolutePosition(x, y);
		under.addImage(image);
	}

	public static void main(String[] args) throws IOException, DocumentException {
		// 读模板
		Ticket ticket = Xml2Ticket.xml2ticket(new File("example.txt"));
		File file = new File("D:\\work\\pdf\\target.pdf");
		// 打印pdf
		new PDFTemplet2Ticket().ticketInPDF(ticket, file);
	}
}

制作好的初期效果,细节慢慢调整




猜你喜欢

转载自blog.csdn.net/reol_fan/article/details/81014287