iTEXT 使用

读取模板, 写入响应流, 自定义绘制

public class PdfUtilBean {

    private PdfStamper stamper;

    private PdfReader reader;
}
// 获取pdf模板
public static PdfUtilBean getPdfStamper(HttpServletResponse response,String readPdfName){
    PdfUtilBean bean = new PdfUtilBean();
    PdfStamper stamper = null;
    try {
        OutputStream bos = response.getOutputStream();
        ClassPathResource classPathResource = new ClassPathResource(StrUtil.concat(true, "/pdffile/", readPdfName));
        InputStream stream = classPathResource.getStream();
        PdfReader reader = new PdfReader(stream);
        stamper = new PdfStamper(reader, bos);
        return bean;
    } catch (Exception e) {
        log.error("获取PDF操作对象异常,",e);
    }
    return null;
}

//写入response
 public static void outPrint(HttpServletResponse response,PdfStamper stamper,String outFileName) {
    try {
        OutputStream bos = response.getOutputStream();
        //设置为生成的pdf不可修改文本域
        stamper.setFormFlattening(true);
        stamper.close();
        //直接写入返回的流
        response.setContentType("application/x-download");
        response.addHeader("Content-Disposition", "attachment;filename=" + outFileName + ".pdf");
        bos.flush();
    } catch (Exception e) {
        log.error("输出PDF对象到输出流异常,",e);
    }
}

//自定义绘制
PdfContentByte cb = stamper.getOverContent(1);// 1为页数, pdf的页数
ColumnText ct = new ColumnText(cb);
//设置对齐方式
ct.setAlignment(Element.ALIGN_CENTER);
//设置此正方体 布局
ct.setSimpleColumn(36, 36, PageSize.A4.getWidth()-36, PageSize.A4.getHeight()-590);
//ct.addElement(table); //添加元素
int status = ct.go();// 绘制
while (ColumnText.hasMoreText(status)){// 绘制不完, 新增页绘制, 直到绘制完
	stamper.insertPage(pdfStamper.getReader().getNumberOfPages() + 1, pdfStamper.getReader().getPageSizeWithRotation(1));
	PdfContentByte canvas = stamper.getOverContent(pdfStamper.getReader().getNumberOfPages());
	ct.setCanvas(canvas);
	ct.setSimpleColumn(36, 36, PageSize.A4.getWidth()-36, PageSize.A4.getHeight()-70);
	status = ct.go();
}

添加图片, 通过设置按钮的图标方法实现添加图片

PushbuttonField ad = form.getNewPushbuttonFromField(imageFieldName);
ad.setLayout(PushbuttonField.LAYOUT_ICON_ONLY);
ad.setProportionalIcon(true);
ad.setImage(Image.getInstance("E:/signature/signature.png"));
form.replacePushbuttonField("advertisement", ad.getField());

为模板添加动态表格

PdfPTable table = new PdfPTable(25);
BaseFont baseFont2 = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H",BaseFont.NOT_EMBEDDED);
Font font2 = new Font(baseFont2);
font2.setSize(14);

PdfPCell questionTypeCell = new PdfPCell(new Paragraph("问: ", font2));
// 定义一个表格单元的跨度
questionTypeCell.setColspan(2);
questionTypeCell.disableBorderSide(15);
// 把单元加到表格中
table.addCell(questionTypeCell);

PdfPCell questionContentCell = new PdfPCell(new Paragraph("你好啊?", font2));
// 定义一个表格单元的跨度
questionContentCell.setColspan(23);
//设置边框 样式, 13 为只保留下, 15全都隐藏
questionContentCell.disableBorderSide(15);
// 把单元加到表格中
table.addCell(questionContentCell);

//写入
PdfContentByte cb = stamper.getOverContent(1);
ColumnText ct = new ColumnText(cb);
ct.setAlignment(Element.ALIGN_CENTER);
//前两个参数应该是 左右页边距, 后两个参数是相对于PDF 左上角为坐标原点的绝对定位
ct.setSimpleColumn(36, 36, PageSize.A4.getWidth()-36, PageSize.A4.getHeight()-590);
//添加元素
ct.addElement(table);
int status = ct.go();
// 动态添加新页
while (ColumnText.hasMoreText(status)){
    stamper.insertPage(pdfStamper.getReader().getNumberOfPages() + 1, pdfStamper.getReader().getPageSizeWithRotation(1));
    PdfContentByte canvas = stamper.getOverContent(pdfStamper.getReader().getNumberOfPages());
    ct.setCanvas(canvas);
    ct.setSimpleColumn(36, 36, PageSize.A4.getWidth()-0, PageSize.A4.getHeight()-70);
    status = ct.go();
}

边框样式

//隐藏上边框
// cell.disableBorderSide(1);
//隐藏下边框
// cell.disableBorderSide(2);
//隐藏上、下边框
//cell.disableBorderSide(3);
//隐藏左边框
//cell.disableBorderSide(4);
//隐藏左、上边框
//cell.disableBorderSide(5);
//隐藏左、下边框
//cell.disableBorderSide(6);
//隐藏左、上、下边框
//cell.disableBorderSide(7);
//隐藏右边框
//cell.disableBorderSide(8);
//隐藏右、上边框
// cell.disableBorderSide(9);
//隐藏右、下边框
//cell.disableBorderSide(10);
//隐藏右、上、下边框
//cell.disableBorderSide(11);
//隐藏左、右边框
//cell.disableBorderSide(12);
//隐藏上、左、右边框
//cell.disableBorderSide(13);
//隐藏下、左、右边框
//cell.disableBorderSide(14);
//隐藏全部
//cell.disableBorderSide(15);

使用table手动处理换行

核心代码: float widthPoint = font.getCalculatedBaseFont(true).getWidthPoint(sb.toString(), font.getCalculatedSize());

 /**
 * 把给定的字符串 通过给定的widthPoint值 在table中生成每行内容
 *
 * @param table
 * @param questionContent
 * @param maxWidthPoint
 * @param font
 * @throws DocumentException
 * @throws IOException
 */
public static  void addRow(PdfPTable table, String questionContent, float maxWidthPoint, Font font) throws DocumentException, IOException {
	StringBuilder contentTemp = new StringBuilder(questionContent);
	for (Chunk chunk = getOneLine(contentTemp, font, maxWidthPoint); null != chunk; chunk = getOneLine(contentTemp, font, maxWidthPoint)){
		Paragraph paragraph2 = new Paragraph(chunk);
		paragraph2.setIndentationLeft(50);
		//第2列
		PdfPCell questionContentCell = new PdfPCell(paragraph2);
		// 定义一个表格单元的跨度
		questionContentCell.setColspan(24);
		questionContentCell.setHorizontalAlignment(Element.ALIGN_JUSTIFIED);
		questionContentCell.disableBorderSide(13);
		// 把单元加到表格中
		table.addCell(questionContentCell);
	}
}

/**
 * 根据maxWidthPoint从字符串种获取table的一行内容
 *
 * @param contentTemp
 * @param font
 * @param maxWidthPoint 允许的最大宽度
 * @return Chunk
 */
//不能在首行出现的标点符号集合
private static final List<String> CHARACTER = Arrays.asList("。",",","!",";","(",")","、"); // 不全可以手动添加

public static Chunk getOneLine(StringBuilder contentTemp, Font font,  float maxWidthPoint){
	//允许的最大宽度
	StringBuilder sb = new StringBuilder();
	for (;contentTemp.length()>0;){
		CharSequence string = contentTemp.subSequence(0, 1);
		sb.append(string);
		float widthPoint = font.getCalculatedBaseFont(true).getWidthPoint(sb.toString(), font.getCalculatedSize());

		// 换行符判断
		boolean isNewLine = false;
		if (contentTemp.length()>1){ // 这里判断换行符 一个换行符就在table中新起一行
			String newline = contentTemp.subSequence(0, 2).toString();
			//建议: 这里只判断windows换行符, 所以在调用当前方法时请确保String的replaceAll方法统一为windows换行符
			if (newline.matches("\r\n")){
				widthPoint = maxWidthPoint+1; // 使widthPoint大于maxWidthPoint, 后面的内容新起一行
				contentTemp.delete(0,2);
				isNewLine= true;
			}
		}

		/**
		 * 因为每行开始处不能有标点符号,当widthPoint大于maxWidthPoint或者widthPoint等于maxWidthPoint要分两种情况:
		 *
		 * 第一种: widthPoint大于maxWidthPoint
		 *        判断currentStr即需要删除的那个字符是否是标点符号, 如果是, 就把当前字符的前一个字符也截取到下一行去(即sb要去掉2个字符);
		 * 第二种: widthPoint等于maxWidthPoint
		 *        判断nextOneChar即下一个字符是否是标点符号, 如果是, 就把当前行的最后一个字符放入下一行开始处
		 * 注意: 此处理方法无法处理标点符号连续的情况, 如: 你好啊,,,是谁啊!!
		 */
		if (widthPoint >= maxWidthPoint){
			if (widthPoint > maxWidthPoint){
				String currentStr = sb.subSequence(sb.length()-1, sb.length()).toString();
				//超过maxWidth 删除倒数第一个字符
				sb.deleteCharAt(sb.length()-1);
				//如果当前字符是标点符号
				//如果是因为换行符导致的widthPoint > maxWidth, 不做判断
				if (CHARACTER.contains(currentStr) && !isNewLine){
					//把当数第二个字符插入到下一行开始
					String lastButOne = sb.substring(sb.length() - 1, sb.length());
					contentTemp.insert(0, lastButOne);
					sb.deleteCharAt(sb.length()-1);
				}
			}else{
				if(contentTemp.length() >= 2){
					String nextOneChar = contentTemp.subSequence(1, 2).toString();
					if (CHARACTER.contains(nextOneChar)) {
						sb.deleteCharAt(sb.length()-1);
					}
				}
			}
			break;
		}

		// 如果没有超过最大widthPoint, 减去字符串一个字符
		if (widthPoint != maxWidthPoint) {
			contentTemp.deleteCharAt(0);
		}
	}
	if (sb.length() == 0){
		return null;
	}

	Chunk chunk = new Chunk(sb.toString());
	chunk.setFont(font);
	chunk.setLineHeight(20f);
	return chunk;
}

效果如下:

posted @ 2021-10-19 17:03  那年长安  阅读(317)  评论(0)    收藏  举报