最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java Poi-tl根據(jù)模板導(dǎo)出Word文件

 更新時(shí)間:2025年03月13日 10:10:28   作者:桃花面包  
這篇文章主要為大家詳細(xì)介紹了Java如何使用Poi-tl根據(jù)模板實(shí)現(xiàn)導(dǎo)出Word文件,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

Poi-tl官網(wǎng):Poi-tl Documentation

最近又碰上了導(dǎo)出,真的服了,還是低代碼的導(dǎo)出,其中過程的曲折真的是一言難盡..........平臺各種適配,依賴沖突,真的是崩潰.......

簡單說一下為什么使用Poi-tl,最開始想用的是poi實(shí)現(xiàn),但是結(jié)果就是poi不好控制圖片的位置,因?yàn)閳D片插入之后是“浮于文字上方”,單純的插入圖片會(huì)占行數(shù),為了方便控制格式后續(xù)就采用了poi-tl但是他同樣也不支持插入圖片之后將圖片設(shè)置為“浮于文字上方”,也是找了一些博客參考,最終實(shí)現(xiàn)了想要的效果

參考博客:poi-tl導(dǎo)出word實(shí)現(xiàn)圖片環(huán)繞方式為浮于在文字上方辦法

老樣子上效果圖:

實(shí)現(xiàn)步驟

1.準(zhǔn)備模板

2.添加依賴

        <dependency>
            <groupId>com.deepoove</groupId>
            <artifactId>poi-tl</artifactId>
            <version>1.10.0-beta</version>
        </dependency>
 
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>5.2.3</version>
        </dependency>
 
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>5.2.3</version>
        </dependency>
 
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml-schemas</artifactId>
            <version>4.1.2</version>
        </dependency>

3.代碼實(shí)現(xiàn)

package com.example.demo;
 
import cn.hutool.core.util.URLUtil;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.config.ConfigureBuilder;
import com.deepoove.poi.data.PictureRenderData;
import com.deepoove.poi.data.Pictures;
import com.deepoove.poi.plugin.table.LoopRowTableRenderPolicy;
import com.example.controller.MyPictureRenderPolicy;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
 
import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
 
public class StudentCardExporter001 {
 
    public static void main(String[] args) {
        // 創(chuàng)建數(shù)據(jù)映射列表
        List<Map<String, Object>> sectionList = new ArrayList<>();
        HashMap<String, Object> sectionMap = new HashMap<>();
        sectionMap.put("zhenghao", "AS011");
        sectionMap.put("chexing", "C2");
        sectionMap.put("username", "楊無敵");
        sectionMap.put("sex", "男");
        sectionMap.put("birthday", "1983-12-06");
        sectionMap.put("deptname", "北京XXXXXXX");
        sectionMap.put("date", "2025-12-09");
        sectionMap.put("localPicture",  Pictures.ofLocal( "D:\\xiazai\\1212.jpg").size(45, 65).create());
 
 
        sectionList.add(sectionMap);
 
        // 這里可以設(shè)置多條數(shù)據(jù)
        /*sectionMap.put("zhenghao", "AS011");
        sectionMap.put("chexing", "C2");
        sectionMap.put("username", "光頭強(qiáng)");
        sectionMap.put("sex", "男");
        sectionMap.put("birthday", "1983-12-06");
        sectionMap.put("deptname", "北京XXXXXXX");
        sectionMap.put("date", "2025-12-09");
        sectionMap.put("localPicture",  Pictures.ofLocal( "D:\\xiazai\\1212.jpg").size(45, 65).create());
        sectionList.add(sectionMap);*/
 
        HashMap<String, Object> paramMap = new HashMap<>();
        paramMap.put("sectionName", sectionList);
        ArrayList<Object> titleList = new ArrayList<>();
        // 創(chuàng)建最終的數(shù)據(jù)映射
        for (int i = 0; i < 2; i++) {
 
 
            HashMap<String, Object> titleMap = new HashMap<>();
            titleMap.put("oneTitle", "                          1、駕駛車輛必須攜帶此證,以備檢查。");
            titleMap.put("tweTitle", "                          2、持證人必須遵守本公司車輛管理規(guī)定及《中華\n" +
                    "                             人民共和國道路交通安全法》。");
            titleMap.put("threeTitle", "                          3、遺失此證必須及時(shí)報(bào)告發(fā)證單位。");
            titleMap.put("fourTitle", "                          4、此證不得偽造、涂改,不得轉(zhuǎn)借他人;一經(jīng)發(fā)\n" +
                    "                             現(xiàn),立即取消其本人準(zhǔn)駕資格并收回其此證。\n");
 
            titleList.add(titleMap);
        }
        paramMap.put("attention", titleList);
        // 加載模板文件
        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        try {
            org.springframework.core.io.Resource[] resources = resolver.getResources("classpath:excelTemplate/model1.docx");
            if (resources.length == 0) {
                throw new IOException("Template file not found.");
            }
            InputStream inputStream = resources[0].getInputStream();
 
            ConfigureBuilder builder = Configure.builder();
            builder.addPlugin('%', new MyPictureRenderPolicy());
 
            // 編譯并渲染模板
            XWPFTemplate template = XWPFTemplate.compile(inputStream, builder.build()).render(paramMap);
//            XWPFTemplate compile = XWPFTemplate.compile(inputStream, builder.build()).render(paramMap);
 
            // 輸出生成的文檔
            try (FileOutputStream out = new FileOutputStream("D:\\xiazai\\1209.docx")) {
                template.write(out);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

自定義MyPictureRenderPolicy

package com.example.controller;
 
import com.deepoove.poi.data.PictureRenderData;
import com.deepoove.poi.data.PictureType;
import com.deepoove.poi.data.Pictures;
import com.deepoove.poi.data.style.PictureStyle;
import com.deepoove.poi.exception.RenderException;
import com.deepoove.poi.policy.AbstractRenderPolicy;
import com.deepoove.poi.render.RenderContext;
import com.deepoove.poi.util.BufferedImageUtils;
import com.deepoove.poi.util.SVGConvertor;
import com.deepoove.poi.util.UnitUtils;
import com.deepoove.poi.xwpf.BodyContainer;
import com.deepoove.poi.xwpf.BodyContainerFactory;
import com.deepoove.poi.xwpf.WidthScalePattern;
import com.deepoove.poi.xwpf.XWPFRunWrapper;
import com.example.demo.ExportUtil;
import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.IBodyElement;
import org.apache.poi.xwpf.usermodel.ParagraphAlignment;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.openxmlformats.schemas.drawingml.x2006.main.CTGraphicalObject;
import org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTAnchor;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTDrawing;
 
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.function.Supplier;
 
public class MyPictureRenderPolicy extends AbstractRenderPolicy<Object> {
 
    @Override
    protected boolean validate(Object data) {
        if (null == data) {
            return false;
        } else if (data instanceof PictureRenderData) {
            return null != ((PictureRenderData) data).getPictureSupplier();
        } else {
            return true;
        }
    }
 
    @Override
    public void doRender(RenderContext<Object> context) throws Exception {
        MyPictureRenderPolicy.Helper.renderPicture(context.getRun(), wrapper(context.getData()));
    }
 
    @Override
    protected void afterRender(RenderContext<Object> context) {
        this.clearPlaceholder(context, false);
    }
 
    @Override
    protected void reThrowException(RenderContext<Object> context, Exception e) {
        this.logger.info("Render picture " + context.getEleTemplate() + " error: {}", e.getMessage());
        String alt = "";
        if (context.getData() instanceof PictureRenderData) {
            alt = ((PictureRenderData) context.getData()).getAltMeta();
        }
 
        context.getRun().setText(alt, 0);
    }
 
    private static PictureRenderData wrapper(Object object) {
        return object instanceof PictureRenderData ? (PictureRenderData) object : Pictures.of(object.toString()).fitSize().create();
    }
 
 
    public static class Helper {
        public static void renderPicture(XWPFRun run, PictureRenderData picture) throws Exception {
            Supplier<byte[]> supplier = picture.getPictureSupplier();
            byte[] imageBytes = (byte[]) supplier.get();
            if (null == imageBytes) {
                throw new IllegalStateException("Can't read picture byte arrays!");
            } else {
                PictureType pictureType = picture.getPictureType();
                if (null == pictureType) {
                    pictureType = PictureType.suggestFileType(imageBytes);
                }
 
                if (null == pictureType) {
                    throw new RenderException("PictureRenderData must set picture type!");
                } else {
                    PictureStyle style = picture.getPictureStyle();
                    if (null == style) {
                        style = new PictureStyle();
                    }
 
                    int width = style.getWidth();
                    int height = style.getHeight();
                    if (pictureType == PictureType.SVG) {
                        imageBytes = SVGConvertor.toPng(imageBytes, (float) width, (float) height);
                        pictureType = PictureType.PNG;
                    }
 
                    if (!isSetSize(style)) {
                        BufferedImage original = BufferedImageUtils.readBufferedImage(imageBytes);
                        width = original.getWidth();
                        height = original.getHeight();
                        if (style.getScalePattern() == WidthScalePattern.FIT) {
                            BodyContainer bodyContainer = BodyContainerFactory.getBodyContainer(((IBodyElement) run.getParent()).getBody());
                            int pageWidth = UnitUtils.twips2Pixel(bodyContainer.elementPageWidth((IBodyElement) run.getParent()));
                            if (width > pageWidth) {
                                double ratio = (double) pageWidth / (double) width;
                                width = pageWidth;
                                height = (int) ((double) height * ratio);
                            }
                        }
                    }
 
                    InputStream stream = new ByteArrayInputStream(imageBytes);
                    Throwable var25 = null;
 
                    try {
                        PictureStyle.PictureAlign align = style.getAlign();
                        if (null != align && run.getParent() instanceof XWPFParagraph) {
                            ((XWPFParagraph) run.getParent()).setAlignment(ParagraphAlignment.valueOf(align.ordinal() + 1));
                        }
 
                        XWPFRunWrapper wrapper = new XWPFRunWrapper(run, false);
                        wrapper.addPicture(stream, pictureType.type(), "Generated", Units.pixelToEMU(width), Units.pixelToEMU(height));
 
                        CTDrawing drawing = run.getCTR().getDrawingArray(0);
                        CTGraphicalObject graphicalobject = drawing.getInlineArray(0).getGraphic();
                        //拿到新插入的圖片替換添加CTAnchor 設(shè)置浮動(dòng)屬性 刪除inline屬性
                        CTAnchor anchor = ExportUtil.getAnchorWithGraphic(graphicalobject, "Generated",
                                Units.toEMU(width), Units.toEMU(height),//圖片大小
                                Units.toEMU(180), Units.toEMU(-60), false);//相對當(dāng)前段落位置 需要計(jì)算段落已有內(nèi)容的左偏移
 
                        drawing.setAnchorArray(new CTAnchor[]{anchor});//添加浮動(dòng)屬性
                        drawing.removeInline(0);//刪除行內(nèi)屬性
                    } catch (Throwable var20) {
                        var25 = var20;
                        throw var20;
                    } finally {
                        if (stream != null) {
                            if (var25 != null) {
                                try {
                                    stream.close();
                                } catch (Throwable var19) {
                                    var25.addSuppressed(var19);
                                }
                            } else {
                                stream.close();
                            }
                        }
 
                    }
 
                }
            }
        }
 
    }
 
    private static boolean isSetSize(PictureStyle style) {
        return (style.getWidth() != 0 || style.getHeight() != 0) && style.getScalePattern() == WidthScalePattern.NONE;
    }
 
}

圖片處理

package com.example.demo;
 
import org.apache.xmlbeans.XmlException;
import org.openxmlformats.schemas.drawingml.x2006.main.CTGraphicalObject;
import org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTAnchor;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTDrawing;
 
import java.math.BigInteger;
 
public class ExportUtil {
 
 
    /**
     * @param ctGraphicalObject 圖片數(shù)據(jù)
     * @param deskFileName      圖片描述
     * @param width             寬
     * @param height            高
     * @param leftOffset        水平偏移 left
     * @param topOffset         垂直偏移 top
     * @param behind            文字上方,文字下方
     * @return
     * @throws Exception
     */
    public static CTAnchor getAnchorWithGraphic(CTGraphicalObject ctGraphicalObject,
                                                String deskFileName, int width, int height,
                                                int leftOffset, int topOffset, boolean behind) {
        String anchorXML =
                "<wp:anchor xmlns:wp=\"http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing\" "
                        + "simplePos=\"0\" relativeHeight=\"0\" behindDoc=\"" + ((behind) ? 1 : 0) + "\" locked=\"0\" layoutInCell=\"1\" allowOverlap=\"1\">"
                        + "<wp:simplePos x=\"0\" y=\"0\"/>"
                        + "<wp:positionH relativeFrom=\"character\">"
                        + "<wp:posOffset>" + leftOffset + "</wp:posOffset>"
                        + "</wp:positionH>"
                        + "<wp:positionV relativeFrom=\"paragraph\">"
                        + "<wp:posOffset>" + topOffset + "</wp:posOffset>"
                        + "</wp:positionV>"
                        + "<wp:extent cx=\"" + width + "\" cy=\"" + height + "\"/>"
                        + "<wp:effectExtent l=\"0\" t=\"0\" r=\"0\" b=\"0\"/>"
                        + "<wp:wrapNone/>"
                        + "<wp:docPr id=\"1\" name=\"Drawing 0\" descr=\"" + deskFileName + "\"/><wp:cNvGraphicFramePr/>"
                        + "</wp:anchor>";
 
        CTDrawing drawing = null;
        try {
            drawing = CTDrawing.Factory.parse(anchorXML);
        } catch (XmlException e) {
            e.printStackTrace();
        }
        CTAnchor anchor = drawing.getAnchorArray(0);
        anchor.setGraphic(ctGraphicalObject);
 
        // 減少左偏移量以使圖片更靠前
        leftOffset = Math.max(0, leftOffset - 500); // 根據(jù)需要調(diào)整減去的值
 
        anchor.getPositionH().setPosOffset(leftOffset);
        anchor.getPositionV().setPosOffset(topOffset);
 
        return anchor;
    }
 
 
}

到此這篇關(guān)于Java Poi-tl根據(jù)模板導(dǎo)出Word文件的文章就介紹到這了,更多相關(guān)Java Poi-tl導(dǎo)出Word內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 在Spring中使用Knife4j進(jìn)行API文檔生成與管理的操作方法

    在Spring中使用Knife4j進(jìn)行API文檔生成與管理的操作方法

    Knife4j 是為Java MVC 框架(如Spring Boot、Spring MVC等)集成 Swagger 生成 API 文檔的增強(qiáng)解決方案,它基于 Swagger 的核心功能,通過定制化的前端界面和一些額外的特性,本文介紹了在Spring中使用Knife4j進(jìn)行API文檔生成與管理的操作方法,需要的朋友可以參考下
    2024-12-12
  • SpringBoot@Profile注解和Spring?EL(多環(huán)境注入)

    SpringBoot@Profile注解和Spring?EL(多環(huán)境注入)

    為了方便, Spring還提供了 Profile機(jī)制, 使我們可以很方便地實(shí)現(xiàn)各個(gè)環(huán)境之間的切換,在使用DI來依賴注入的時(shí)候,能夠根據(jù)@profile標(biāo)明的環(huán)境,將注入符合當(dāng)前運(yùn)行環(huán)境的相應(yīng)的bean,本文通過示例代碼介紹SpringBoot@Profile注解和Spring?EL,需要的朋友可以參考下
    2024-02-02
  • SpringBoot實(shí)現(xiàn)配置文件自動(dòng)加載和刷新的示例詳解

    SpringBoot實(shí)現(xiàn)配置文件自動(dòng)加載和刷新的示例詳解

    在使用Spring Boot開發(fā)應(yīng)用程序時(shí),配置文件是非常重要的組成部分,在不同的環(huán)境中,我們可能需要使用不同的配置文件,當(dāng)我們更改配置文件時(shí),我們希望應(yīng)用程序能夠自動(dòng)加載和刷新配置文件,本文我們將探討Spring Boot如何實(shí)現(xiàn)配置文件的自動(dòng)加載和刷新
    2023-08-08
  • Springboot如何配置多個(gè)Redis數(shù)據(jù)源(非集群)

    Springboot如何配置多個(gè)Redis數(shù)據(jù)源(非集群)

    這篇文章主要介紹了Springboot如何配置多個(gè)Redis數(shù)據(jù)源(非集群)方式,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-03-03
  • spring boot--從controller到DAO操作

    spring boot--從controller到DAO操作

    這篇文章主要介紹了spring boot--從controller到DAO操作,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • 圖書管理系統(tǒng)java代碼實(shí)現(xiàn)

    圖書管理系統(tǒng)java代碼實(shí)現(xiàn)

    這篇文章主要為大家詳細(xì)介紹了java代碼實(shí)現(xiàn)的圖書管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-01-01
  • spring依賴注入深入理解

    spring依賴注入深入理解

    這篇文章主要介紹了spring依賴注入深入理解,列舉了最常見的注入方式,有感興趣的同學(xué)可以研究下
    2021-03-03
  • 如何調(diào)試報(bào)表插件

    如何調(diào)試報(bào)表插件

    在項(xiàng)目開發(fā)過程中插件調(diào)試非常的麻煩,需要修改里面的代碼,編譯出class,需要重新打包插件。然后把之前的刪除,重新安裝最新的。調(diào)試過程比較繁瑣,而且不能調(diào)試,十分的不方便,這篇文章主要介紹的是調(diào)試報(bào)表插件的方法,需要的朋友可以參考下
    2015-07-07
  • Java異常詳解_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    Java異常詳解_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    異常是Java語言中的一部分,它代表程序中由各種原因引起的“不正?!币蛩亍O旅嫱ㄟ^本文給大家介紹java異常的相關(guān)知識,感興趣的朋友一起看看吧
    2017-06-06
  • 解決IDEA刪除子模塊并重建后MAVEN無法識別的問題

    解決IDEA刪除子模塊并重建后MAVEN無法識別的問題

    這篇文章主要介紹了解決IDEA刪除子模塊并重建后MAVEN無法識別的問題,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-02-02

最新評論

邳州市| 长兴县| 自治县| 永登县| 大连市| 汕尾市| 镇沅| 长垣县| 凤庆县| 镇远县| 新竹市| 宜昌市| 永德县| 武鸣县| 东山县| 呼伦贝尔市| 开江县| 柞水县| 高淳县| 九寨沟县| 昌宁县| 黄梅县| 庆云县| 偏关县| 定南县| 涿州市| 津市市| 天全县| 禄丰县| 绍兴县| 宁都县| 剑川县| 石屏县| 房产| 毕节市| 吉水县| 许昌县| 郓城县| 阿拉善右旗| 南溪县| 虞城县|