您现在的位置是:首页 > 编程 > 

【java spring boot使用easypoi实现word文档占位符替换文字和图片、Excel图片贴到对应单元格】

2025-07-20 01:38:11
最近接到一个任务,写两个导出工具:1.word文档导出,将数据和图片放入到word中,将多个word合并为一个导出。2.Excel文档导出,将二维码信息和图片按照模板放入到Excel中,按9个一页排版数据导出 这里word数据插入

最近接到一个任务,写两个导出工具:1.word文档导出,将数据和图片放入到word中,将多个word合并为一个导出。2.Excel文档导出,将二维码信息和图片按照模板放入到Excel中,按9个一页排版数据导出
这里word数据插入我选择使用占位符替换内容

word文档占位符文字和图片的替换

先看效果。如下图所示:

一、引入依赖

<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>4.1.2</version>
</dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>4.1.2</version>
</dependency>

二、word导出工具

1.定义一个用来导出数据的实体类TicketProject

这里偷懒了,用@Builder方便造数据

import lombok.Builder;
import lombok.Data;

import java.io.Serializable;

@Builder
@Data
public class TicketProject implements Serializable {
    private static final long serialVersionUID = 1L;

    /**
     * 序列码 Vvji6o9m
     */
    private String evaluationCode;
    /**
     * 二维码文件地址 https://www.hjhrcloud/e/
     */
    private String evaluationQrcode;
    /**
     * 项目名称
     */
    private String evaluationProjectame;
    /**
     * 票种角(领导班子、外部董事、中层)
     */
    private String ticketame;
    /**
     * 描述 请扫一扫二维码或在手机和电脑浏览器上输入网址进行打分
     */
    private String describe;

    /**
     * 简介(一页一码使用:欢迎参加202年×××民主测评。。。)
     */
    private String information;
	/**
	 * 指导语
	 */
	private String guide;
	/**
	 * 注意事项
	 */
	private String attention;

    /**
     * 日期
     */
    private String createdDate;
}

2.word导出工具类 ExportUtils
import com.nnmzkj.common.utils.UUIDUtils;
import com.nnmzkj.evaluation.model.TicketProject;
import lombok.SneakyThrows;
import org.apache.poi.openxml4j.excepti.InvalidFormatException;
import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.Document;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlOpti;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBody;

import javax.servlet.http.HttpServletRespe;
import java.io.*;
import java.util.*;

/**
 * 测评文件导出工具类
 */
public class ExportUtils {
    //占位符数组
    private static String[] PLACEHOLDER = {${evaluationProjectame}, ${ticketame}, ${guide}, ${attention}, ${evaluationCode}, ${createdDate}, ${quickMark}};
    //图片占位符单独处理
    private static String[] PICTURE_PLACEHOLDER = {${quickMark}};
    
    private static int WIDTH = 100; //100%
    private static int HEIGHT = 100; //100%

    /**
     * 一页一码word导出
     * @param dtos 二维码数据列表
     * @param respe
     */
    @SneakyThrows
    public static void UniqueCodeWordExport(List<TicketProject> dtos, HttpServletRespe respe) {
        //生成文档的名称列表
        List<String> fileameList = new ArrayList<>();
        for (TicketProject dto : dtos) {
            String filePath = template/UniqueCodeWordTemplate.docx; //模板地址
            InputStream fis = Thread.currentThread().getContextClassLoader().getResourceAsStream(filePath);
            XWPFDocument doc = new XWPFDocument(fis);
            Iterator<XWPFParagraph> itPara = doc.getParagraphsIterator();
            while (itPara.hat()) {
                XWPFParagraph paragraph = (XWPFParagraph) itPara.next();
                List<String> placeholderList = Arrays.asList(PLACEHOLDER);
                placeholderList.forEach(s->{
                    List<XWPFRun> runs=paragraph.getRuns();
                    //文字替换
                    for (int i = 0; i < runs.size(); i) {
                        //获取字符
                        String text = runs.get(i).getText(runs.get(i).getTextPosition());
                        if (text != null && text.contains($)) {
                            //包含占位符的字符缓存
                            StringBuilder cache = new StringBuilder(text);
                            //记录run结束的角标,开始的角标为i
                            int endIndex = 0;
                            boolean contains = text.contains(});
                            //同一个run中是否包含完成占位符
                            if (!contains) {
                                int j = i  1 ;
                                for (; j < runs.size(); j) {
                                    String text1 = runs.get(j).getText(runs.get(j).getTextPosition());
                                    if (text1 == null) {
                                        continue;
                                    }
                                    cache.append(text1);
                                    if (text1.contains(})) {
                                        endIndex = j;
                                        break;
                                    }
                                }
                            }
                            if (contains || endIndex != 0) {
                                //处理替换
                                String key = cache.toString(); //这里是完整的占位符
                                if (key.contains(s)) {
                                    if (key.contains(PICTURE_PLACEHOLDER[0])) { //替换图片
                                        InputStream in = null;

                                        String evaluationQrcode = dto.getEvaluationQrcode();
                                        String type = evaluationQrcode.substring(evaluationQrcode.lastIndexOf(.)  1); //二维码图片后缀
                                        //创建Random类对象
                                        Random random = new Random();
                                        //产生随机数
                                        int number = random.nextInt(999)  1;
                                        try {
                                            if (endIndex == 0) {
                                                paragraph.removeRun(endIndex); //endIndex为0时,直接删掉run
                                            }else {
                                                for (int j = endIndex; j > i; j--) {
                                                    //角标移除后,runs会同步变动,直接继续处理i就可以
                                                    paragraph.removeRun(j);
                                                }
                                            }
                                            //重新创建一个run,用来放二维码图片
                                            XWPFRun run = paragraph.createRun();

                                            in = new FileInputStream(evaluationQrcode);//设置图片路径
                                            run.addPicture(in, getPictureType(type), quickMark  number,
                                                    Units.toEMU(WIDTH), Units.toEMU(HEIGHT)); //图片写入
                                            break;
                                        } catch (InvalidFormatException | IOException e) {
                                            e.printStackTrace();
                                        } finally {
                                            try {
                                                if (in != null) {
                                                    in.close();
                                                }
                                            } catch (IOException e) {
                                                e.printStackTrace();
                                            }
                                        }
                                    }else { //文字替换
                                        /**
                                         * 参数0表示生成的文字是要从哪一个地方开始放置,设置文字从位置0开始
                                         * 就可以把原来的文字全部替换掉了
                                         */
                                        runs.get(i).setText(getValue(dto, s), 0);
                                        for (int j = endIndex; j > i; j--) {
                                            //角标移除后,runs会同步变动,直接继续处理i就可以
                                            paragraph.removeRun(j);
                                        }
                                        break;
                                    }
                                    
                                }
                            }
                        }
                    }
                });
            }
            
            String strUUID = UUIDUtils.getStrUUID();
            String fileame = strUUID.docx;
            fileameList.add(fileame);
            FileOutputStream outStream = null;
            outStream = new FileOutputStream(D:/file/evaluation/word/fileame); //单个文件保存路径
            doc.write(outStream);
            outStream.close();
        }
        //合并word
        if (fileameList.size() > 0) {
            String mainFileame = fileameList.get(0);
            FileInputStream fis = new FileInputStream(D:/file/evaluation/word/mainFileame);
            XWPFDocument doc = new XWPFDocument(fis);
            for (int i = 1; i < fileameList.size(); i) { //循环合并
                FileInputStream fisTail = new FileInputStream(D:/file/evaluation/word/fileameList.get(i));
                XWPFDocument docTail = new XWPFDocument(fisTail);
                doc = mergeWord(doc, docTail);
            }
            //TODO 以下写文件改为使用respe下载文件
            FileOutputStream outStream = null;
            outStream = new FileOutputStream(D:/file/evaluation/word/合并文件.docx);
            doc.write(outStream);
            outStream.close();
            
            //TODO 删除fileameList列表的文件
            
        }
    }

    private static String getValue(TicketProject dto, String s) {
        if (s.equals(${evaluationProjectame})) {
            return dto.getEvaluationProjectame();
        }else if (s.equals(${ticketame})) {
            return dto.getTicketame();
        }else if (s.equals(${guide})) {
            return dto.getGuide();
        }else if (s.equals(${attention})) { //注意事项
            return dto.getAttention();
        }else if (s.equals(${evaluationCode})) {
            return dto.getEvaluationCode();
        }else if (s.equals(${createdDate})) {
            return dto.getCreatedDate();
        }else return null;
    }
    /**
     * 根据图片类型,取得对应的图片类型代码 
     * @param picType
     * @return int
     */
    private static int getPictureType(String picType){
        int res = Document.PICTURE_TYPE_PICT;
        if(picType != null){
            if(picType.equalsIgnoreCase(png)){
                res = Document.PICTURE_TYPE_PG;
            }else if(picType.equalsIgnoreCase(dib)){
                res = Document.PICTURE_TYPE_DIB;
            }else if(picType.equalsIgnoreCase(emf)){
                res = Document.PICTURE_TYPE_EMF;
            }else if(picType.equalsIgnoreCase(jpg) || picType.equalsIgnoreCase(jpeg)){
                res = Document.PICTURE_TYPE_JPEG;
            }else if(picType.equalsIgnoreCase(wmf)){
                res = Document.PICTURE_TYPE_WMF;
            }
        }
        return res;
    }

    /**
     * 将两个word文档合并
     * @param document
     * @param doucDocument2
     * @return 合并后的文档
     */
    public static XWPFDocument mergeWord(XWPFDocument document,XWPFDocument doucDocument2) {
        XWPFParagraph p = document.createParagraph();
        //设置分页符
        p.setPageBreak(true);
        CTBody src1Body = document.getDocument().getBody();
        CTBody src2Body = doucDocument2.getDocument().getBody();
//      XWPFParagraph p2 = (); 
        XmlOpti optiOuter = new XmlOpti();
        optiOuter.setSaveOuter();
        String appendString = src2Body.xmlText(optiOuter);
        String srcString = src1Body.xmlText();
        String prefix = srcString.substring(0,srcString.indexOf(>)1);
        String mainPart = srcString.substring(srcString.indexOf(>)1,srcString.lastIndexOf(<));
        String sufix = srcString.substring( srcString.lastIndexOf(<) );
        String addPart = appendString.substring(appendString.indexOf(>)  1, appendString.lastIndexOf(<));
        CTBody makeBody = null;
        try {
            makeBody = CTBody.Factory.parse(prefixmainPartaddPartsufix);
        } catch (XmlException e) {
            e.printStackTrace();
        }
        src1Body.set(makeBody);
        return document;
    }

    
}

main方法调用代码如下:

    
    public static void main(String[] args) throws Exception {
        String line = System.getProperty(line.separator);
        List<TicketProject> entitys = new ArrayList<>();
        entitys.add(TicketProject
                .builder()
                .evaluationCode(Vvji6o9m)
                .evaluationProjectame(202年×××民主测评)
                .ticketame(领导班子)
                .describe(请扫一扫二维码或在手机和电脑浏览器上输入网址进行打分)
                .guide(欢迎参加202年×××民主测评,本次测评采用匿名方式,不收集任何个人信息,目的在于合理、真实评价有关人员的素质能力和实际工作情况。请结合现场述职及书面述职的情况,根据您日常工作中的观察、了解和所掌握的情况,做出客观评价。)
                .attention(1.请务必在限定的时间内完成评价并提交,评价通道将于2022年12月1日关闭; line
                            2.中途因故退出,可用同一手机再次扫码进入考评系统; line
                            .评价一经提交无法进行修改; line
                            4.如果您遇到任何问题,请与党委组织部联系,非常感谢您的支持!)
                .evaluationQrcode(D:/file/evaluation/1682057427848.jpg) //图片地址
                .createdDate(202年0月09日)
                .build());

        entitys.add(TicketProject
                .builder()
                .evaluationCode(Vvji6678o)
                .evaluationProjectame(202年×××民主测评)
                .ticketame(领导班子)
                .describe(请扫一扫二维码或在手机和电脑浏览器上输入网址进行打分)
                .guide(欢迎参加202年×××民主测评,本次测评采用匿名方式,不收集任何个人信息,目的在于合理、真实评价有关人员的素质能力和实际工作情况。请结合现场述职及书面述职的情况,根据您日常工作中的观察、了解和所掌握的情况,做出客观评价。)
                .attention(1.请务必在限定的时间内完成评价并提交,评价通道将于202年月01日关闭; line
                            2.中途因故退出,可用同一手机再次扫码进入考评系统; line
                            .评价一经提交无法进行修改; line
                            4.如果您遇到任何问题,请与党委组织部联系,非常感谢您的支持!)
                .evaluationQrcode(D:/file/evaluation/1682057427848.jpg)
                .createdDate(202年0月11日)
                .build());
        
        //合并导出word文档
        UniqueCodeWordExport(entitys, null);
    }
.导出模板

来看下模板中的站位符,如下图所示:


在模板提前设置好格式和样式,数据替换占位符之后就不需要再设置样式了。

图片替换占位符比较特殊,不能像文字那样,直接替换掉占位符就可以。需要先清掉图片占位符,重新创建一个run再将图片放进去。

Excel图片插入到对应单元格

同样,先看导出效果图,如下图所示:


这里没有在程序里面设置单元格格式,可以根据自己的需求进行调整。

1.Excel导出处理方法
	private static String[] VOTE_ROLE = {领导班子, 外部董事, 中层};

	/**
     * 一页一码excel导出
     * @param dtos 二维码数据列表
     * @param respe
     */
    public static void UniqueCodeExcelExport(List<TicketProject> dtos, HttpServletRespe respe) {
        String filePath = template/UniqueCodeExcelTemplate.xls; //模板地址
        InputStream fis = Thread.currentThread().getContextClassLoader().getResourceAsStream(filePath);
        try {
            if (dtos == null || dtos.size() < 1) {
                throw new RuntimeException(没有可导出的数据);
            }
            //根据票种角进行分组
            Map<String, List<TicketProject>> TicketameGroupList = dtos.stream().filter(item-> StringUtils.isotBlank(item.getTicketame())).collect(Collectors.groupingBy(TicketProject::getTicketame));
            HSSFWorkbook workbook = new HSSFWorkbook(fis);
            HSSFSheet sheet = workbook.getSheetAt(0);
            int excelPage = 0;
            for (String s : VOTE_ROLE) {
                excelPage; //第一页,遍历到下一个类型时,换下一页
                List<TicketProject> ticketProjects = TicketameGroupList.get(s); //获取某一个类型的所有数据
                
                if (ticketProjects != null && ticketProjects.size() > 0) {
                    int currentPage;
                    //手工分页,一行条,一行数据为一页
                    int totalRecord = ticketProjects.size();
                    int totalPage = totalRecord % ;
                    if (totalPage > 0) {
                        totalPage = totalRecord /   1;
                    } else {
                        totalPage = totalRecord / ;
                    }
                    int currentRow = 0; //每一行二维码的起始位置
                    for (int i=1; i<=totalPage; i) { //页数(list的页数,每条一页)
                        currentPage = i;
                        int fromIndex =  * (currentPage - 1);
                        int toIndex = Math.min( * currentPage, totalRecord);
                        //9条数据换下一页
                        int Cumulative = currentPage % ;
                        if (Cumulative == 0) {
                            excelPage;
                        }
                        if(currentPage != 1 && ((currentPage-1) % )==0){ //第四行数据开始1
                            currentRow; //加上分类那一行,纠正行数
                        }
                        int rowum = (excelPage-1)*22;//每一页开始的行数
                        
                        List<TicketProject> page = ticketProjects.subList(fromIndex, toIndex);
                        //首行为分类
                        if (currentPage == 1 || Cumulative == 0) {
                            Row row1 = sheet.getRow(rowum);
                            Cell row1cell = row1.createCell(0);
                            row1cell.setCellValue(page.get(0).getTicketame());
                        }
                        //计算行数
                        if (currentPage == 1){
                            currentRow = rowum;
                        }
                        if (currentPage != 1) {
                            currentRow = 7;
                        }
                        for (int j=0; j<page.size(); j) {
                            TicketProject ticketProject = page.get(j);
                            //计算cellum 方法比较笨,但是实用
                            int cellum;
                            if (j==0) {
                                cellum = 1;
                            }else if (j==1) {
                                cellum = 4;
                            }else {
                                cellum = 7;
                            }

                            //第二行二维码
                            String url = ticketProject.getEvaluationQrcode(); //图片路径
                            String type = url.substring(url.lastIndexOf(.)  1); //二维码图片后缀
                            InputStream in = new FileInputStream(url);
                            byte[] btImg = null;
                            try {
                                btImg = readInputStream(in);// 得到图片的二进制数据
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                            HSSFPatriarch patriarch = sheet.createDrawingPatriarch();
                            /**
                             * dx1:左边偏移量
                             * dy1:顶部偏移量
                             */
                            HSSFClientAnchor anchor = new HSSFClientAnchor(50, 10, 0, 0, (short) cellum, currentRow1, (short) (cellum1), currentRow2);
                            assert btImg != null;
                            Picture picture = patriarch.createPicture(anchor, workbook.addPicture(btImg, getPictureType(type)));
                            picture.resize(0.95,0.95); //设置了图片大小,就不能跟随单元格变化了(不设置这个设置不了偏移量),没有到解决方案
                            
                            //第三行
                            Row row = sheet.getRow(currentRow2);
                            Cell rowcell = row.createCell(cellum);
                            rowcell.setCellValue(ticketProject.getTicketame());
                            //第四行
                            Row row4 = sheet.getRow(currentRow);
                            Cell row4cell = row4.createCell(cellum);
                            row4cell.setCellValue(ticketProject.getEvaluationProjectame());
                            //第五行
                            Row row5 = sheet.getRow(currentRow4);
                            Cell row5cell = row5.createCell(cellum);
                            row5cell.setCellValue(序列码:ticketProject.getEvaluationCode());
                            //第六行
                            Row row6 = sheet.getRow(currentRow5);
                            Cell row6cell = row6.createCell(cellum);
                            row6cell.setCellValue(ticketProject.getDescribe());
                        }
                    }
                }
            }

            String strUUID = UUIDUtils.getStrUUID();
            String fileame = strUUID.xls;
            FileOutputStream outStream = null;
            outStream = new FileOutputStream(D:/file/evaluation/excel/fileame); //单个文件保存路径
            workbook.write(outStream);
            outStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        
    }
    
	/**
     * 从输入流中获取字节流数据
     *
     * @param inStream 输入流
     * @return
     * @throws Exception
     */
    public static byte[] readInputStream(InputStream inStream) throws Exception {
        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
        byte[] buffer = new byte[10240];
        int len = 0;
        while ((len = inStream.read(buffer)) != -1) {
            outStream.write(buffer, 0, len);
        }
        inStream.close();
        return outStream.toByteArray();
    }
方法调用
public static void main(String[] args) throws Exception {
        String line = System.getProperty(line.separator);
        List<TicketProject> entitys = new ArrayList<>();
        entitys.add(TicketProject
                .builder()
                .evaluationCode(Vvji6o9m)
                .evaluationProjectame(202年×××民主测评)
                .ticketame(领导班子)
                .describe(请扫一扫二维码或在手机和电脑浏览器上输入网址进行打分)
                .guide(欢迎参加202年×××民主测评,本次测评采用匿名方式,不收集任何个人信息,目的在于合理、真实评价有关人员的素质能力和实际工作情况。请结合现场述职及书面述职的情况,根据您日常工作中的观察、了解和所掌握的情况,做出客观评价。)
                .attention(1.请务必在限定的时间内完成评价并提交,评价通道将于2022年12月1日关闭; line
                            2.中途因故退出,可用同一手机再次扫码进入考评系统; line
                            .评价一经提交无法进行修改; line
                            4.如果您遇到任何问题,请与党委组织部联系,非常感谢您的支持!)
                .evaluationQrcode(D:/file/evaluation/1682057427848.jpg)
                .createdDate(202年0月09日)
                .build());

        entitys.add(TicketProject
                .builder()
                .evaluationCode(Vvji6678o)
                .evaluationProjectame(202年×××民主测评)
                .ticketame(领导班子)
                .describe(请扫一扫二维码或在手机和电脑浏览器上输入网址进行打分)
                .guide(欢迎参加202年×××民主测评,本次测评采用匿名方式,不收集任何个人信息,目的在于合理、真实评价有关人员的素质能力和实际工作情况。请结合现场述职及书面述职的情况,根据您日常工作中的观察、了解和所掌握的情况,做出客观评价。)
                .attention(1.请务必在限定的时间内完成评价并提交,评价通道将于202年月01日关闭; line
                            2.中途因故退出,可用同一手机再次扫码进入考评系统; line
                            .评价一经提交无法进行修改; line
                            4.如果您遇到任何问题,请与党委组织部联系,非常感谢您的支持!)
                .evaluationQrcode(D:/file/evaluation/1682057427848.jpg)
                .createdDate(202年0月11日)
                .build());

        entitys.add(TicketProject
                .builder()
                .evaluationCode(Vvji25n11)
                .evaluationProjectame(202年×××民主测评)
                .ticketame(领导班子)
                .describe(请扫一扫二维码或在手机和电脑浏览器上输入网址进行打分)
                .guide(欢迎参加202年×××民主测评,本次测评采用匿名方式,不收集任何个人信息,目的在于合理、真实评价有关人员的素质能力和实际工作情况。请结合现场述职及书面述职的情况,根据您日常工作中的观察、了解和所掌握的情况,做出客观评价。)
                .attention(1.请务必在限定的时间内完成评价并提交,评价通道将于202年月01日关闭; line
                            2.中途因故退出,可用同一手机再次扫码进入考评系统; line
                            .评价一经提交无法进行修改; line
                            4.如果您遇到任何问题,请与党委组织部联系,非常感谢您的支持!)
                .evaluationQrcode(D:/file/evaluation/168228606868.jpg)
                .createdDate(202年0月11日)
                .build());

        entitys.add(TicketProject
                .builder()
                .evaluationCode(Vbime1877a)
                .evaluationProjectame(202年×××民主测评)
                .ticketame(领导班子)
                .describe(请扫一扫二维码或在手机和电脑浏览器上输入网址进行打分)
                .guide(欢迎参加202年×××民主测评,本次测评采用匿名方式,不收集任何个人信息,目的在于合理、真实评价有关人员的素质能力和实际工作情况。请结合现场述职及书面述职的情况,根据您日常工作中的观察、了解和所掌握的情况,做出客观评价。)
                .attention(1.请务必在限定的时间内完成评价并提交,评价通道将于202年月01日关闭; line
                            2.中途因故退出,可用同一手机再次扫码进入考评系统; line
                            .评价一经提交无法进行修改; line
                            4.如果您遇到任何问题,请与党委组织部联系,非常感谢您的支持!)
                .evaluationQrcode(D:/file/evaluation/168228606868.jpg)
                .createdDate(202年0月11日)
                .build());

        entitys.add(TicketProject
                .builder()
                .evaluationCode(Vbime182a)
                .evaluationProjectame(202年×××民主测评)
                .ticketame(外部董事)
                .describe(请扫一扫二维码或在手机和电脑浏览器上输入网址进行打分)
                .guide(欢迎参加202年×××民主测评,本次测评采用匿名方式,不收集任何个人信息,目的在于合理、真实评价有关人员的素质能力和实际工作情况。请结合现场述职及书面述职的情况,根据您日常工作中的观察、了解和所掌握的情况,做出客观评价。)
                .attention(1.请务必在限定的时间内完成评价并提交,评价通道将于202年月01日关闭; line
                            2.中途因故退出,可用同一手机再次扫码进入考评系统; line
                            .评价一经提交无法进行修改; line
                            4.如果您遇到任何问题,请与党委组织部联系,非常感谢您的支持!)
                .evaluationQrcode(D:/file/evaluation/168228606868.jpg)
                .createdDate(202年0月11日)
                .build());
        
        entitys.add(TicketProject
                .builder()
                .evaluationCode(Vbime182a)
                .evaluationProjectame(202年×××民主测评)
                .ticketame(外部董事)
                .describe(请扫一扫二维码或在手机和电脑浏览器上输入网址进行打分)
                .guide(欢迎参加202年×××民主测评,本次测评采用匿名方式,不收集任何个人信息,目的在于合理、真实评价有关人员的素质能力和实际工作情况。请结合现场述职及书面述职的情况,根据您日常工作中的观察、了解和所掌握的情况,做出客观评价。)
                .attention(1.请务必在限定的时间内完成评价并提交,评价通道将于202年月01日关闭; line
                            2.中途因故退出,可用同一手机再次扫码进入考评系统; line
                            .评价一经提交无法进行修改; line
                            4.如果您遇到任何问题,请与党委组织部联系,非常感谢您的支持!)
                .evaluationQrcode(D:/file/evaluation/168228606868.jpg)
                .createdDate(202年0月11日)
                .build());
        //加测试数据
        List<TicketProject> list = new ArrayList<>(entitys);
        entitys.addAll(list);
        entitys.addAll(list);
        entitys.addAll(list);
        entitys.addAll(list);
        entitys.addAll(list);
        
        //excel导出
        UniqueCodeExcelExport(entitys, null);
    }

懒人造数据,不要吐槽我!

Excel导出有要求,9条数据为一页,一行三条数据。同一个分类的数据,分页之后要在前面加上分类名称,所以中间计算开始行数的时候,要加上这一行。

.Excel模板

不想在代码里面设置格式样式,提前画好直接取模板用就好

因为在做这两个工具的时候了很多网上的代码,感觉都不完整,而且都没有能达到我想要的效果。
在这里发出来记录一下,也分享给大家,希望对你有用!

#感谢您对电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格的认可,转载请说明来源于"电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格

本文地址:http://www.dnpztj.cn/biancheng/1099020.html

相关标签:无
上传时间: 2025-07-15 10:34:14
留言与评论(共有 11 条评论)
本站网友 激光去斑
27分钟前 发表
0); for (int j = endIndex; j > i; j--) { //角标移除后,runs会同步变动,直接继续处理i就可以 paragraph.removeRun(j); } break; } } } } } }); } String strUUID = UUIDUtils.getStrUUID(); String fileame = strUUID.docx; fileameList.add(fileame); FileOutputStream outStream = null; outStream = new FileOutputStream(D
本站网友 宁德二手房网
10分钟前 发表
) */ private String information; /** * 指导语 */ private String guide; /** * 注意事项 */ private String attention; /** * 日期 */ private String createdDate; } 2.word导出工具类 ExportUtils import com.nnmzkj.common.utils.UUIDUtils; import com.nnmzkj.evaluation.model.TicketProject; import lombok.SneakyThrows; import org.apache.poi.openxml4j.excepti.InvalidFormatException; import org.apache.poi.util.Units; import org.apache.poi.xwpf.usermodel.Document; import org.apache.poi.xwpf.usermodel.XWPFDocument; import org.apache.poi.xwpf.usermodel.XWPFParagraph; import org.apache.poi.xwpf.usermodel.XWPFRun; import org.apache.xmlbeans.XmlException; import org.apache.xmlbeans.XmlOpti; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBody; import javax.servlet.http.HttpServletRespe; import java.io.*; import java.util.*; /** * 测评文件导出工具类 */ public class ExportUtils { //占位符数组 private static String[] PLACEHOLDER = {${evaluationProjectame}
本站网友 企业宣传片拍摄
9分钟前 发表
了解和所掌握的情况,做出客观评价
本站网友 苏州硬盘数据恢复
23分钟前 发表
getTicketame)); HSSFWorkbook workbook = new HSSFWorkbook(fis); HSSFSheet sheet = workbook.getSheetAt(0); int excelPage = 0; for (String s
本站网友 吴菲菲
6分钟前 发表
请结合现场述职及书面述职的情况,根据您日常工作中的观察
本站网友 李子彬
26分钟前 发表
顶部偏移量 */ HSSFClientAnchor anchor = new HSSFClientAnchor(50
本站网友 windows虚机
17分钟前 发表
dtos) { String filePath = template/UniqueCodeWordTemplate.docx; //模板地址 InputStream fis = Thread.currentThread().getContextClassLoader().getResourceAsStream(filePath); XWPFDocument doc = new XWPFDocument(fis); Iterator<XWPFParagraph> itPara = doc.getParagraphsIterator(); while (itPara.hat()) { XWPFParagraph paragraph = (XWPFParagraph) itPara.next(); List<String> placeholderList = Arrays.asList(PLACEHOLDER); placeholderList.forEach(s->{ List<XWPFRun> runs=paragraph.getRuns(); //文字替换 for (int i = 0; i < runs.size(); i) { //获取字符 String text = runs.get(i).getText(runs.get(i).getTextPosition()); if (text != null && text.contains($)) { //包含占位符的字符缓存 StringBuilder cache = new StringBuilder(text); //记录run结束的角标,开始的角标为i int endIndex = 0; boolean contains = text.contains(}); //同一个run中是否包含完成占位符 if (!contains) { int j = i  1 ; for (; j < runs.size(); j) { String text1 = runs.get(j).getText(runs.get(j).getTextPosition()); if (text1 == null) { continue; } cache.append(text1); if (text1.contains(})) { endIndex = j; break; } } } if (contains || endIndex != 0) { //处理替换 String key = cache.toString(); //这里是完整的占位符 if (key.contains(s)) { if (key.contains(PICTURE_PLACEHOLDER[0])) { //替换图片 InputStream in = null; String evaluationQrcode = dto.getEvaluationQrcode(); String type = evaluationQrcode.substring(evaluationQrcode.lastIndexOf(.)  1); //二维码图片后缀 //创建Random类对象 Random random = new Random(); //产生随机数 int number = random.nextInt(999)  1; try { if (endIndex == 0) { paragraph.removeRun(endIndex); //endIndex为0时,直接删掉run }else { for (int j = endIndex; j > i; j--) { //角标移除后,runs会同步变动,直接继续处理i就可以 paragraph.removeRun(j); } } //重新创建一个run,用来放二维码图片 XWPFRun run = paragraph.createRun(); in = new FileInputStream(evaluationQrcode);//设置图片路径 run.addPicture(in
本站网友 分公司管理制度
7分钟前 发表
.Excel模板 不想在代码里面设置格式样式,提前画好直接取模板用就好 因为在做这两个工具的时候了很多网上的代码,感觉都不完整,而且都没有能达到我想要的效果
本站网友 暴风影音3
16分钟前 发表
totalRecord); //9条数据换下一页 int Cumulative = currentPage % ; if (Cumulative == 0) { excelPage; } if(currentPage != 1 && ((currentPage-1) % )==0){ //第四行数据开始1 currentRow; //加上分类那一行,纠正行数 } int rowum = (excelPage-1)*22;//每一页开始的行数 List<TicketProject> page = ticketProjects.subList(fromIndex
本站网友 代办股份转让
25分钟前 发表
真实评价有关人员的素质能力和实际工作情况