Bootstrap

java编辑pdf,替换文本

前言

用户会在PDF模板中放入占位符,程序需要直接编辑PDF,将PDF中的占位符替换成指定字符。

目前java领域有很多框架组件都能够将Office文件转换成pdf,一般都是先在Office文件中替换再转换成pdf。支持直接编辑pdf的框架比较少。支持的好的且免费的更少。例如:iText,aspose,Apache PdfBox,PDFClown 等等。其中iText虽然能编辑pdf,但是他读出来是1个个字符的坐标,不能直接替换整个文本。

本文使用的是Spire.pdf的免费版本5.1。支持直接替换占位符。

框架技术

Jdk 1.8

<dependencies>
	<dependency>
        <groupId>e-iceblue</groupId>
        <artifactId>spire.pdf.free</artifactId>
        <version>5.1.0</version>
    </dependency>
</dependencies>


<repositories>
    <repository>
        <id>com.e-iceblue</id>
        <name>e-iceblue</name>
        <url>https://repo.e-iceblue.cn/repository/maven-public/</url>
    </repository>
</repositories>

实现方案

spire.pdf

参考代码

import java.awt.Font;
import java.awt.geom.Dimension2D;
import java.awt.geom.Rectangle2D;

import com.spire.pdf.FileFormat;
import com.spire.pdf.PdfDocument;
import com.spire.pdf.PdfPageBase;
import com.spire.pdf.general.find.PdfTextFind;
import com.spire.pdf.general.find.PdfTextFindCollection;
import com.spire.pdf.graphics.PdfBrushes;
import com.spire.pdf.graphics.PdfFont;
import com.spire.pdf.graphics.PdfFontFamily;
import com.spire.pdf.graphics.PdfGraphicsState;
import com.spire.pdf.graphics.PdfStringFormat;
import com.spire.pdf.graphics.PdfTextAlignment;
import com.spire.pdf.graphics.PdfTrueTypeFont;
import com.spire.pdf.graphics.PdfVerticalAlignment;
import com.spire.pdf.widget.PdfPageCollection;

public class SpirePdfTest {
	public static void main(String[] args) {
		String src = "D:\\Resource\\Desktop\\原图纸-中文签名.pdf";
		String dest = "D:\\Resource\\Desktop\\替换文本.pdf";

		String keyWord = "[**SSRQ**]";
		String keyWordNew = "2026-07-08";
		// 创建 PdfDocument 类的对象
		PdfDocument doc = new PdfDocument();

		// 载入PDF文档
		doc.loadFromFile(src);

		PdfPageCollection pages = doc.getPages();
		for (int i = 0; i < pages.getCount(); i++) {
			// 获取文档的每一页
			PdfPageBase page = doc.getPages().get(i);

			// 搜索关键字
			PdfTextFindCollection collection = page.findText(keyWord, false);

			// 指定替换文本
			String newText = keyWordNew;

			// 创建 PdfTrueTypeFont 类的对象以设置字体
			PdfTrueTypeFont font = new PdfTrueTypeFont(new Font("宋体", Font.BOLD, 6));

			for (Object findObj : collection.getFinds()) {
				PdfTextFind find = (PdfTextFind) findObj;
				Dimension2D size = find.getSize();
				// 获取文本在页面中的范围
				Rectangle2D.Float rec = (Rectangle2D.Float) find.getBounds();
				// 写入空白范围遮住原来的文本
				page.getCanvas().drawRectangle(PdfBrushes.getWhite(), rec);

//                page.getCanvas().drawString(newText, font, PdfBrushes.getBlue(), rec.getX(), rec.getY() - 3);
				double width = size.getWidth();
				double height = size.getHeight();

				//根据要替换的文本方向,如果要竖过来的需要旋转以下
				if (width < height) {
					RotateText(page, rec.getX(), rec.getY(), newText);
				} else {
					page.getCanvas().drawString(newText, font, PdfBrushes.getBlue(), rec.getX(), rec.getY());
				}
			}
		}

		// 保存文档
		doc.saveToFile(dest, FileFormat.PDF);
		System.out.println("success");
	}

	private static void RotateText(PdfPageBase page, double x, double y, String newText) {
		PdfGraphicsState state = page.getCanvas().save();// 保存画布状态

		PdfFont font = new PdfFont(PdfFontFamily.Helvetica, 6f);// 创建字体

		PdfStringFormat centerAlignment = new PdfStringFormat(PdfTextAlignment.Left, PdfVerticalAlignment.Middle);// 设置文本对齐方式

		// 指定文本在画布中的坐标位置
		page.getCanvas().translateTransform(x, y);

		// 循环绘制12条文本内容,并设置每条文本内容间隔30度,即每一条文本内容以绘制的上一文本内容旋转30度(这里如只需绘制单个文本,直接指定旋转角度即可)
		page.getCanvas().rotateTransform(90);
		page.getCanvas().drawString(newText, font, PdfBrushes.getBlue(), 0, -5, centerAlignment);

		// 再次保存画布状态
		page.getCanvas().restore(state);
	}
}

执行效果

执行前

执行效果

悦读

道可道,非常道;名可名,非常名。 无名,天地之始,有名,万物之母。 故常无欲,以观其妙,常有欲,以观其徼。 此两者,同出而异名,同谓之玄,玄之又玄,众妙之门。

;