欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java使用poi-tl設(shè)置word圖片環(huán)繞方式為浮于在文字上方

 更新時(shí)間:2025年03月13日 09:43:21   作者:Eugene Jou  
POI-TL 是一個(gè)基于 Apache POI 的 Java 庫(kù),專注于在 Microsoft Word 文檔(.docx 格式)中進(jìn)行模板填充和動(dòng)態(tài)內(nèi)容生成,下面我們看看如何使用poi-tl設(shè)置word圖片環(huán)繞方式為浮于在文字上方吧

poi-tl簡(jiǎn)介

poi-tl(poi template language)是Word模板引擎,基于Microsoft Word模板和數(shù)據(jù)生成新的文檔。

文檔地址:http://deepoove.com/poi-tl/1.7.x/

因?yàn)閜oi-tl暫時(shí)不支持設(shè)置圖片環(huán)繞方式,但是可以自定義圖片渲染插件

廢話少說(shuō),直接上代碼

首先自定義一個(gè)圖片渲染插件

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 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(270), Units.toEMU(-70), false);//相對(duì)當(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;
    }

}

浮于文字上方的核心代碼提取出來(lái)放到了工具類里面

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=\"column\">"
                        + "<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);
        return anchor;
    }


}

在使用poi-tl導(dǎo)出word時(shí)

ConfigureBuilder builder = Configure.builder();
builder.addPlugin('%',new MyPictureRenderPolicy());//把插件注冊(cè)為新標(biāo)簽類型
XWPFTemplate template = XWPFTemplate.compile(templateIs,builder.build()).render(exportBO);

這樣就能把模板里所有前綴為%的圖片標(biāo)簽渲染為浮于文字上方

到此這篇關(guān)于Java使用poi-tl設(shè)置word圖片環(huán)繞方式為浮于在文字上方的文章就介紹到這了,更多相關(guān)Java poi-tl設(shè)置word圖片環(huán)繞方式內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • JAVA 日常開(kāi)發(fā)中Websocket示例詳解

    JAVA 日常開(kāi)發(fā)中Websocket示例詳解

    JAVA |日常開(kāi)發(fā)中Websocket詳解,WebSocket是一種在單個(gè)TCP連接上進(jìn)行全雙工通信的協(xié)議,它在Web應(yīng)用中實(shí)現(xiàn)了客戶端與服務(wù)器之間的實(shí)時(shí)數(shù)據(jù)傳輸,本文將詳細(xì)介紹Java開(kāi)發(fā)中WebSocket的使用,包括基本概念、Java API、使用示例以及注意事項(xiàng),感興趣的朋友一起看看吧
    2024-12-12
  • OpenTelemetry初識(shí)及調(diào)用鏈Trace詳解

    OpenTelemetry初識(shí)及調(diào)用鏈Trace詳解

    這篇文章主要為為大家介紹了OpenTelemetry初識(shí)及調(diào)用鏈Trace詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • Spring Boot 2.0.0 終于正式發(fā)布-重大修訂版本

    Spring Boot 2.0.0 終于正式發(fā)布-重大修訂版本

    北京時(shí)間 2018 年 3 月 1 日早上,如約發(fā)布的 Spring Boot 2.0 在同步至 Maven 倉(cāng)庫(kù)時(shí)出現(xiàn)問(wèn)題,導(dǎo)致在 GitHub 上發(fā)布的 v2.0.0.RELEASE 被撤回
    2018-03-03
  • Spring使用ThreadPoolTaskExecutor自定義線程池及異步調(diào)用方式

    Spring使用ThreadPoolTaskExecutor自定義線程池及異步調(diào)用方式

    這篇文章主要介紹了Spring使用ThreadPoolTaskExecutor自定義線程池及異步調(diào)用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-02-02
  • Java調(diào)用opencv實(shí)現(xiàn)圖片矯正功能

    Java調(diào)用opencv實(shí)現(xiàn)圖片矯正功能

    這篇文章主要為大家詳細(xì)介紹了Java如何調(diào)用opencv實(shí)現(xiàn)圖片矯正功能,文中的示例代碼簡(jiǎn)潔易懂,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-09-09
  • Java切割字符串的踩坑實(shí)戰(zhàn)記錄

    Java切割字符串的踩坑實(shí)戰(zhàn)記錄

    最近在項(xiàng)目中使用了java中的分割字符串,踩了一個(gè)坑,充分了展示了自己對(duì)java底層的認(rèn)知有很多的不足和欠缺,下面這篇文章主要給大家介紹了關(guān)于Java切割字符串的踩坑實(shí)戰(zhàn)記錄,需要的朋友可以參考下
    2022-11-11
  • SpringBoot2.7.14整合redis7的詳細(xì)過(guò)程

    SpringBoot2.7.14整合redis7的詳細(xì)過(guò)程

    這篇文章主要介紹了SpringBoot2.7.14整合redis7的詳細(xì)過(guò)程,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2023-10-10
  • Java算法比賽常用方法實(shí)例總結(jié)

    Java算法比賽常用方法實(shí)例總結(jié)

    這篇文章主要給大家介紹了關(guān)于Java算法比賽常用方法實(shí)例總結(jié)的相關(guān)資料,文中給出了詳細(xì)的實(shí)例介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)java算法具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2023-05-05
  • Java中的包(package)是什么和使用方法

    Java中的包(package)是什么和使用方法

    包是Java中一種強(qiáng)大的組織代碼的工具,它們幫助開(kāi)發(fā)者將代碼分組,防止命名沖突,并通過(guò)控制訪問(wèn)級(jí)別來(lái)增強(qiáng)代碼的安全性,這篇文章主要介紹了Java中的包(package)是什么和如何使用它們,需要的朋友可以參考下
    2024-07-07
  • JAVA實(shí)現(xiàn)簡(jiǎn)單搶紅包算法(模擬真實(shí)搶紅包)

    JAVA實(shí)現(xiàn)簡(jiǎn)單搶紅包算法(模擬真實(shí)搶紅包)

    這篇文章主要介紹了JAVA實(shí)現(xiàn)簡(jiǎn)單搶紅包算法(模擬真實(shí)搶紅包)的實(shí)例代碼,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2016-12-12

最新評(píng)論