化身天使的博客

18.java word,pdf等操作

Poi

依赖

<poi.version>5.2.5</poi.version>

		<dependency>
			<groupId>org.apache.poi</groupId>
			<artifactId>poi</artifactId>
			<version>${poi.version}</version>
		</dependency>
		<dependency>
			<groupId>org.apache.poi</groupId>
			<artifactId>poi-ooxml</artifactId>
			<version>${poi.version}</version>
		</dependency>

word读取,简单替换

package com.chiyi.poi.word;

import org.apache.poi.xwpf.usermodel.*;
import com.itextpdf.text.Document;
import com.itextpdf.text.pdf.PdfWriter;

import java.io.*;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author wakeleo
 * @description 按照模板, 替换word文档
 */
public class DocPoi {
    private String srcPath = "C:\\Users\\young\\Desktop\\二检合一证书报告模板.docx";  // 模板路径
    private String outPath = "C:\\Users\\young\\Desktop\\123.docx";  // 输出路径
    private String outPathPdf = "C:\\Users\\young\\Desktop\\123.aspose";
    private Map param;
    private XWPFDocument docTemplate;
    private Pattern pattern = Pattern.compile("\\$\\{(.+?)}");  // 查找 ${}

    public DocPoi() {

    }

    public DocPoi(Map param) {
        this.param = param;
    }

    public DocPoi(String srcPath, Map param) {
        this.srcPath = srcPath;
        this.param = param;
    }

    // 0 读取表格
    private XWPFDocument getDoc() {
        try (InputStream fis = new FileInputStream(srcPath);) {
            return new XWPFDocument(fis);
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("读取文件错误:" + e.getMessage());
        }
        return null;
    }

    //1.1 读取段落
    private void readParagraph(XWPFParagraph paragraph) {
        for (XWPFRun run : paragraph.getRuns()) {  // 获取一个run
            String text = run.toString();
//            String value = replaceColumn(text, table);
//            if (value != null) {
//                run.setText(value, 0);  // 替换 原本的run
//            }
        }
    }

    // 1.2 读取表格
    private void readTable(XWPFTable table) {
        for (XWPFTableRow row : table.getRows()) {             //获取一行
            for (XWPFTableCell cell : row.getTableCells()) {  // 获取一个单元格
                //如果包含子表格,递归
                if (cell.getTables() != null && cell.getTables().size() > 0) {
                    List<XWPFTable> childTables = cell.getTables();
                    for (XWPFTable childTable : childTables) {
                        readTable(childTable);
                    }
                }

                for (XWPFParagraph paragraph : cell.getParagraphs()) {  // 如果是段落, 读取段落
                    readParagraph(paragraph);
                }
            }
        }
    }

    // 1.3 替换字段
    private String replaceColumn(String text, XWPFTable table) {
        if (text.contains("${")) {
            Matcher matcher = pattern.matcher(text);
            if (matcher.find()) {
                String key = matcher.group(1);
                if (text.endsWith("List}")) {
//                    replaceList(table, key);
                } else {
                    String value = param.get(key).toString();  // 要替换的内容
                    if (value != null) {
                        return text.replace("${" + key + "}", value);
                    }
                }
            }
        }
        return null;
    }

    //2. word文档读取
    public Boolean geneDoc() {
        return geneDoc(srcPath, param);
    }

    public Boolean geneDoc(String srcPath, Map param) {
        docTemplate = getDoc();  // 读取word
        if (docTemplate == null) {
            return false;
        }
        System.out.println("=================1. 读取段落================");
        List<XWPFParagraph> paragraphList = docTemplate.getParagraphs(); // 获取所有段落
        for (XWPFParagraph paragraph : paragraphList) {
            readParagraph(paragraph, null);
        }
        System.out.println("============2. 读取word中的表格========");
        List<XWPFTable> tableList = docTemplate.getTables(); //获取所有表格
        for (XWPFTable table : tableList) {
            readTable(table);
        }
        //修改,写入
        try (FileOutputStream fos = new FileOutputStream(outPath)) {
            docTemplate.write(fos);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("写入错误" + e.getMessage());
        }

        return false;
    }

    public static void main(String[] args) throws IOException {
        Map map = new HashMap<>();
        map.put("method", "teeeeeeeeeeeeeeeee");
        map.put("cerNum", "teeeeeeeeeeeeeeeee");
        DocPoi docPoi = new DocPoi(map);
        docPoi.geneDoc();

    }
}

xdocreport

使用 freemarker

依赖

<xdocreport.version>2.0.2</xdocreport.version>

		<dependency>
			<groupId>fr.opensagres.xdocreport</groupId>
			<artifactId>fr.opensagres.xdocreport.core</artifactId>
			<version>${xdocreport.version}</version>
		</dependency>
		<dependency>
			<groupId>fr.opensagres.xdocreport</groupId>
			<artifactId>fr.opensagres.xdocreport.document</artifactId>
			<version>${xdocreport.version}</version>
		</dependency>
		<dependency>
			<groupId>fr.opensagres.xdocreport</groupId>
			<artifactId>fr.opensagres.xdocreport.template</artifactId>
			<version>${xdocreport.version}</version>
		</dependency>
		<dependency>
			<groupId>fr.opensagres.xdocreport</groupId>
			<artifactId>fr.opensagres.xdocreport.document.docx</artifactId>
			<version>${xdocreport.version}</version>
		</dependency>

		<dependency>
			<groupId>fr.opensagres.xdocreport</groupId>
			<artifactId>fr.opensagres.poi.xwpf.converter.pdf</artifactId>
			<version>${xdocreport.version}</version>
		</dependency>

		<dependency>
			<groupId>fr.opensagres.xdocreport</groupId>
			<artifactId>fr.opensagres.xdocreport.template.freemarker</artifactId>
			<version>${xdocreport.version}</version>
		</dependency>

word模板填充

使用 xdocreport

package com.chiyi.poi.word;

import fr.opensagres.xdocreport.core.XDocReportException;
import fr.opensagres.xdocreport.document.IXDocReport;
import fr.opensagres.xdocreport.document.registry.XDocReportRegistry;
import fr.opensagres.xdocreport.template.IContext;
import fr.opensagres.xdocreport.template.TemplateEngineKind;
import fr.opensagres.xdocreport.template.formatter.FieldsMetadata;
import lombok.Data;
import org.apache.poi.xwpf.usermodel.*;

import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

/**
 * @author wakeleo
 * @description 按照模板, 填充 word 文档, 
 * 一对一替换: ${} , 
 * 一对多 替换 ${abc.id}  原数据类似 list<User>
 * 一对多,多列动态表格, 需要用到域设置
 *    - 格式  ${abc.id}
 *    - wps中,选中内容 -> 插入->文档部件->域 -> 邮件合并 -> 把这个追加到结尾 ${abc.id}
 * 
 */
public class DocFill {
    private String srcPath = "C:\\Users\\young\\Desktop\\二检合一证书报告模板.docx";  // 模板路径
    private String outPath; 
    private String srcSuffix = ".docx";
    private Map param;
    private XWPFDocument doc;
    private Pattern pattern = Pattern.compile("\\$\\{(.+?)}");  // 查找 ${}

    public DocFill() {

    }

    public DocFill(Map param) {
        this.param = param;
    }

    public DocFill(String srcPath, Map param) {
        this.srcPath = srcPath;
        this.param = param;
    }
    public void setOutPath(){
        srcSuffix= srcPath.substring(srcPath.indexOf("."));
        outPath=srcPath.replace("."+srcSuffix, "_new."+srcSuffix);
    }

    /**
     * 定义实体类
     * 用于动态表格
     * 模板中相关字段 属性需要 设置为域
     */
    @Data
    class ZhunBeiJieDuanList {
        String createTime;
        String content;
    }


    //2.生成 word


    public void geneDoc(String srcPath, Map param) throws IOException, XDocReportException {
        FileInputStream ins = new FileInputStream(srcPath);
        //注册xdocreport实例并加载FreeMarker模板引擎
        IXDocReport report = XDocReportRegistry.getRegistry().loadReport(ins, TemplateEngineKind.Freemarker);
        //创建xdocreport上下文对象,用于存放具体数据
        IContext context = report.createContext();
        // 将map填充到 context, 其中列表要特殊处理,
        param.forEach((k, v) -> {
            String key = String.valueOf(k);
            if (key.endsWith("List")) {
                List<Map> coList = (List) v;
                if ("zhunBeiJieDuanList".equals(key)) {
                    List<ZhunBeiJieDuanList> zhunBeiJieDuanList = (List<ZhunBeiJieDuanList>) v;
                    context.put(key, zhunBeiJieDuanList);
                } else if ("xxx".equals(key)) {
                }
            } else {
                context.put(key, v);
            }
        });

        //创建字段元数据
        FieldsMetadata fm = report.createFieldsMetadata();
        //Word模板中的表格数据对应的集合类型
        fm.load("zhunBeiJieDuanList", ZhunBeiJieDuanList.class, true);
        fm.load("jieGuoBiDuiList", JieGuoBiDuiList.class, true);
        //创建输出流
        FileOutputStream out = new FileOutputStream(new File(outPath));
        //写入
        report.process(context, out);
    }

    public void geneDoc() throws IOException, XDocReportException {
        geneDoc(srcPath, param);
    }
    
    //3. 测试
    public static void main(String[] args) throws IOException, XDocReportException {
        Map map = new HashMap<>();
        map.put("cerNum", "teeeeeeeeeeeeeeeee");
        map.put("zhunBeiJieDuanList", new ArrayList() {{
            add(new HashMap() {{
                put("createTime", "2024-01-23 10:30:58");
                put("content", "开始");
            }});
            add(new HashMap() {{
                put("createTime", "2024-01-23 10:36:35");
                put("content", "完结");
            }});
        }});

        // 调用
        DocFill docPoi = new DocFill(map);   
        docPoi.geneDoc(); //生成 word

    }
}

aspose-words

可以转很多,图片, pdf,epub,html之类的

word转pdf

参考: [https://blog.csdn.net/qq_35222232/article/details/129163200]

  • 下载jar和 license
链接:https://pan.baidu.com/s/1m3fQRDsj8clJofpOeGOl-w?pwd=aspo 
提取码:aspo
  • 把两个jar文件放到 resource 目录下的lib目录,(lib不存在自己新建)
  • 把 license.xml文件放到 resource目录下
  • win可能要管理员运行idea

pom.xml

		<dependency>
			<groupId>com.aspose</groupId>
			<artifactId>aspose-words</artifactId>
			<version>15.12.0</version>
			<scope>system</scope>
			<systemPath>${project.basedir}/src/main/resources/lib/aspose-words-15.12.0-jdk16.jar</systemPath>
		</dependency>

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <includeSystemScope>true</includeSystemScope>  <!-- 在这个位置,这个选项打包时把本地system的jar也包括进来 -->
            </configuration>
        </plugin>
    <plugins>
<build>

实现


import com.aspose.words.Document;
import com.aspose.words.License;
import com.aspose.words.SaveFormat;
import org.springframework.core.io.ClassPathResource;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * @Description: word转pdf
 * @Version: 1.0
 */
public class WordToPdf {
    private static String pdfPath = "C:\\Users\\young\\Desktop\\123.pdf";
    private static String wordPath = "C:\\Users\\young\\Desktop\\123.docx";
    private static boolean license = false;
    public static void main(String[] args) {
        WordToPdf wordToPdf = new WordToPdf();
        try {
            wordToPdf.wordToPdf(wordPath, pdfPath);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public String wordToPdf(String wordPath,String pdfPath) throws Exception {
        FileOutputStream os = null;
        try {
            //凭证 不然切换后有水印
            InputStream is = new ClassPathResource("/license.xml").getInputStream();
            License aposeLic = new License();
            aposeLic.setLicense(is);
            license = true;
            if (!license) {
                System.out.println("License验证不通过...");
                return null;
            }
            //生成一个空的PDF文件
            File file = new File(pdfPath);
            os = new FileOutputStream(file);
            //要转换的word文件
            Document doc = new Document(wordPath);
            doc.save(os, SaveFormat.PDF);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }


        return null;
    }

}


itextPdf

pdf加水印

pom.xml

		<dependency>
			<groupId>com.itextpdf</groupId>
			<artifactId>itextpdf</artifactId>
			<version>5.5.13.2</version>
		</dependency>
		<dependency>
			<groupId>com.itextpdf</groupId>
			<artifactId>itext-asian</artifactId>
			<version>5.2.0</version>
		</dependency>

实现

  • 可添加文字水印或图片水印
package com.chiyi.poi.aspose;

import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * pdf加水印
 * @Author: wakeleo
 * @Description: 分为图片水印和文字水印
 * @Version: 1.0
*/
public class PdfAddSign {
    private static final String signPicPath = "C:\\Users\\young\\Desktop\\未命名文件.png"; // 水印图片路径
    private static final String SIGNTEXT = "水印文字"; // 水印文字
    private static PdfContentByte under;
    /**
     * 0.1 图片水印
     */
    private static void pictureMark(PdfStamper stamp,int pageSize) throws DocumentException, IOException {
        //水印图片
        Image image = Image.getInstance(signPicPath);
        for (int i = 1; i <= pageSize; i++) {
            under = stamp.getUnderContent(i);// 获取指定页
            image.setAbsolutePosition(100, 210);//设置水印位置
            under.addImage(image);  // 添加水印
        }
    }
    /**
     * 0.2 文字水印
     */
    public static void textMark(PdfStamper stamp,int pageSize)throws Exception {
        PdfGState gs = new PdfGState();
        BaseFont font =  BaseFont.createFont("STSong-Light","UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
        gs.setFillOpacity(0.4f);// 设置透明度
        for (int i = 1; i < pageSize; i++) {
            under = stamp.getOverContent(i);
            under.beginText();
            under.setGState(gs);
            under.setColorFill(BaseColor.DARK_GRAY); //水印颜色
            under.setFontAndSize(font, 26); //字体和大小
            under.showTextAligned(Element.ALIGN_CENTER,SIGNTEXT, 300, 300, 15); //居中,内容,坐标,角度,
            under.endText();
        }
        System.out.println("PDF水印添加完成!");
    }
    /**
     * 1. 添加水印
     * @param srcFile File, 原pdf 
     * @param markType String,文字水印或图片水印
     * @return 添加水印后的pdf路径
     */
    private static String addTextMark(File srcFile,String markType) {
        PdfReader reader = null;
        PdfStamper stamp = null;
        try {
            File outFile = new File(srcFile.getParent(), "new_"+srcFile.getName());

            // 获取pdfReader对象
            reader = new PdfReader(srcFile.toString());
            stamp = new PdfStamper(reader, new FileOutputStream(outFile));
            PdfContentByte under;

            // 获取pdf总页数
            int pageSize = reader.getNumberOfPages();
            if (pageSize == 0) {
                return null;
            }
            // 添加水印
            if (markType.equals("text")) {
                textMark(stamp,pageSize);
            }else if(markType.equals("picture")){
                pictureMark(stamp,pageSize);
            }
            return outFile.toString();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (stamp != null) {
                    stamp.close();
                }
                if (reader != null) {
                    reader.close();//关闭
                }
            } catch (Exception ex) {
                ex.printStackTrace();
            }
            //删除生成的无水印pdf
//            if (srcFile != null && srcFile.exists() && srcFile.isFile()) {
//                srcFile.delete();
//            }
        }
        return null;
    }
    public static void main(String[] args) {
        System.out.println(addTextMark(new File("C:\\Users\\young\\Desktop\\abc.pdf"),"text"));
    }
}

posted @ 2024-01-25 19:38  化身天使  阅读(81)  评论(0)    收藏  举报