热门标签 | HotTags
当前位置:  开发笔记 > 运维 > 正文

javapoi设置生成的word的图片为上下型环绕以及其位置的实现

这篇文章主要介绍了javapoi设置生成的word的图片为上下型环绕以及其位置的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

问题描述

在使用poi-tl word模版工具时,发现生成的文档中,图片格式为嵌入型,有的图片甚至被表格遮挡一半。而自己想要的图片格式为上下型环绕,并且图片需要居中。

问题分析

poi-tl渲染图片,使用的是org.apache.poi.xwpf.usermodel.XWPFRun的addPicture方法,该方法中有一段代码:CTInline inline = drawing.addNewInline();意思就是默认将图片转为inline类型,即行内元素。

然后我们把生成的嵌入型图片的文档转换成xml文件,然后再新建一个文档,插入图片后,设置图片为上下型环绕,保存为另一个xml,比较下两个xml的区别。嵌入型图片的xml是:


上下型环绕的图片的xml是

我们看到两种格式的图片标签分别为inline和anchor。所以如果我们想把图片设置为上下型环绕,需要重写poi的addPicture方法,把图片转为anchor类型。

我们仿照org.apache.poi.xwpf.usermodel.XWPFRun的addPicture方法,将CTInline inline = drawing.addNewInline();换成 CTAnchor anchor = drawing.addNewAnchor();,然后对比着xml,依次对anchor的字段进行赋值。结果发现生成的word无法正常打开,查了很多资料,都说poi的CTAnchor有问题,使用后无法正常打开生成的word。

此路不通,那我们就尝试另一种思路,我们不通过CTAnchor来生成anchor标签,而是直接使用xml,将xml赋给poi的drawing。具体的处理方式在后面。

xml标签和图片格式解析

在word中,在图片上右键,选择大小和位置,就可以看到如下界面:


图中的上下型对应的是xml中的标签,不同环绕方式该标签值不一样。如果需要其他格式,可以设置好后,把文档保存为xml,找到对应的标签。

图中的距正文上下左右距离,对应的是中的disT、disB、disL、disR属性。


图中位置一栏,水平对齐方式居中、相对于栏对应的是xml中的center

垂直-绝对位置0.1cm,下侧段落对应的是xml中的36195

我们可以根据不同的需要来设置不同的xml。

我使用的xml是

 String xml = "" +
        "" +
        "" +
        "center" +
        "" +
        "" +
        "0" +
        "" +
        "" +
        "" +
        "" +
        "" +
        "" +
        "" +
        "" +
        "" +
        "" +
        "" +
        "" +
        "" +
        "" +
        "" +
        "" +
        "" +
        "" +
        "" +
        "" +
        "" +
        "" +
        "" +
        "" +
        "" +
        "" +
        "" +
        "" +
        "" +
        "" +
        "" +
        "" +
        "" +
        "" +
        "0" +
        "" +
        "" +
        "0" +
        "" +
        "";
        

其中width和height是图片的宽度和高度,relationId是图片的id。

解决方案

1,首先定义一个poi-tl的图片渲染器,使得其不再调用poi默认的图片渲染器,而是使用我们自己定义的。

public class MyPictureRenderPolicy extends AbstractRenderPolicy {
@Override
protected boolean validate(PictureRenderData data) {
  return (null != data.getData() || null != data.getPath());
}

@Override
public void doRender(RunTemplate runTemplate, PictureRenderData picture, XWPFTemplate template)
    throws Exception {
  XWPFRun run = runTemplate.getRun();
  MyPictureRenderPolicy.Helper.renderPicture(run, picture);
}

@Override
protected void afterRender(RenderContext context) {
  clearPlaceholder(context, false);
}

@Override
protected void doRenderException(RunTemplate runTemplate, PictureRenderData data, Exception e) {
  logger.info("Render picture " + runTemplate + " error: {}", e.getMessage());
  runTemplate.getRun().setText(data.getAltMeta(), 0);
}

public static class Helper {
  public static void renderPicture(XWPFRun run, PictureRenderData picture) throws Exception {
    int suggestFileType = suggestFileType(picture.getPath());
    InputStream ins = null == picture.getData() ? new FileInputStream(picture.getPath())
        : new ByteArrayInputStream(picture.getData());

    String relatiOnId= run.getDocument().addPictureData(ins, suggestFileType);
    long width = Units.toEMU(picture.getWidth());
    long height = Units.toEMU(picture.getHeight());
    CTDrawing drawing = run.getCTR().addNewDrawing();
    String xml = "" +
        "" +
        "" +
        "center" +
        "" +
        "" +
        "0" +
        "" +
        "" +
        "" +
        "" +
        "" +
        "" +
        "" +
        "" +
        "" +
        "" +
        "" +
        "" +
        "" +
        "" +
        "" +
        "" +
        "" +
        "" +
        "" +
        "" +
        "" +
        "" +
        "" +
        "" +
        "" +
        "" +
        "" +
        "" +
        "" +
        "" +
        "" +
        "" +
        "" +
        "" +
        "0" +
        "" +
        "" +
        "0" +
        "" +
        "";
    drawing.set(XmlToken.Factory.parse(xml, DEFAULT_XML_OPTIONS));
    CTPicture pic = getCTPictures(drawing).get(0);
    XWPFPicture xwpfPicture = new XWPFPicture(pic, run);
    run.getEmbeddedPictures().add(xwpfPicture);
  }


  public static List getCTPictures(XmlObject o) {
    List pictures = new ArrayList<>();
    XmlObject[] picts = o.selectPath("declare namespace pic='"
        + CTPicture.type.getName().getNamespaceURI() + "' .//pic:pic");
    for (XmlObject pict : picts) {
      if (pict instanceof XmlAnyTypeImpl) {
        // Pesky XmlBeans bug - see Bugzilla #49934
        try {
          pict = CTPicture.Factory.parse(pict.toString(),
              DEFAULT_XML_OPTIONS);
        } catch (XmlException e) {
          throw new POIXMLException(e);
        }
      }
      if (pict instanceof CTPicture) {
        pictures.add((CTPicture) pict);
      }
    }
    return pictures;
  }


  public static int suggestFileType(String imgFile) {
    int format = 0;
    if (imgFile.endsWith(".emf")) {
      format = XWPFDocument.PICTURE_TYPE_EMF;
    } else if (imgFile.endsWith(".wmf")) {
      format = XWPFDocument.PICTURE_TYPE_WMF;
    } else if (imgFile.endsWith(".pict")) {
      format = XWPFDocument.PICTURE_TYPE_PICT;
    } else if (imgFile.endsWith(".jpeg") || imgFile.endsWith(".jpg")) {
      format = XWPFDocument.PICTURE_TYPE_JPEG;
    } else if (imgFile.endsWith(".png")) {
      format = XWPFDocument.PICTURE_TYPE_PNG;
    } else if (imgFile.endsWith(".dib")) {
      format = XWPFDocument.PICTURE_TYPE_DIB;
    } else if (imgFile.endsWith(".gif")) {
      format = XWPFDocument.PICTURE_TYPE_GIF;
    } else if (imgFile.endsWith(".tiff")) {
      format = XWPFDocument.PICTURE_TYPE_TIFF;
    } else if (imgFile.endsWith(".eps")) {
      format = XWPFDocument.PICTURE_TYPE_EPS;
    } else if (imgFile.endsWith(".bmp")) {
      format = XWPFDocument.PICTURE_TYPE_BMP;
    } else if (imgFile.endsWith(".wpg")) {
      format = XWPFDocument.PICTURE_TYPE_WPG;
    } else {
      throw new RenderException(
          "Unsupported picture: " + imgFile + ". Expected emf|wmf|pict|jpeg|png|dib|gif|tiff|eps|bmp|wpg");
    }
    return format;
  }

}
}

然后在渲染模板的时候,配置我们自己定义的图片渲染器

 public static void main(String[] args) throws Exception{

  String path = "1.docx";
  InputStream templateFile = Demo.class.getClassLoader().getResourceAsStream(path);
  Map map = new HashMap();
  map.put("pic", new PictureRenderData(120, 80, ".png", Demo.class.getClassLoader().getResourceAsStream("1.png")));


  // 将数据整合到模板中去
  Configure.ConfigureBuilder builder = Configure.newBuilder();
  builder.supportGrammerRegexForAll();
  builder.addPlugin('@', new MyPictureRenderPolicy());
  XWPFTemplate template = XWPFTemplate.compile(templateFile, builder.build()).render(map);

  String docPath = "C:\\Users\\csdc01\\Desktop\\out.docx";
  FileOutputStream outputStream1 = new FileOutputStream(docPath);
  template.write(outputStream1);
  outputStream1.flush();
  outputStream1.close();
}

源码:https://github.com/ksyzz/poi-tl-demo.git

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


推荐阅读
  • 本文详细介绍了如何在Linux系统上安装和配置Smokeping,以实现对网络链路质量的实时监控。通过详细的步骤和必要的依赖包安装,确保用户能够顺利完成部署并优化其网络性能监控。 ... [详细]
  • 本文详细介绍了 Java 中 org.apache.xmlbeans.SchemaType 类的 getBaseEnumType() 方法,提供了多个代码示例,并解释了其在不同场景下的使用方法。 ... [详细]
  • 本文详细介绍了如何在ECharts中使用线性渐变色,通过echarts.graphic.LinearGradient方法实现。文章不仅提供了完整的代码示例,还解释了各个参数的具体含义及其应用场景。 ... [详细]
  • 构建基于BERT的中文NL2SQL模型:一个简明的基准
    本文探讨了将自然语言转换为SQL语句(NL2SQL)的任务,这是人工智能领域中一项非常实用的研究方向。文章介绍了笔者在公司举办的首届中文NL2SQL挑战赛中的实践,该比赛提供了金融和通用领域的表格数据,并标注了对应的自然语言与SQL语句对,旨在训练准确的NL2SQL模型。 ... [详细]
  • 本文详细介绍了 Dockerfile 的编写方法及其在网络配置中的应用,涵盖基础指令、镜像构建与发布流程,并深入探讨了 Docker 的默认网络、容器互联及自定义网络的实现。 ... [详细]
  • 数据库内核开发入门 | 搭建研发环境的初步指南
    本课程将带你从零开始,逐步掌握数据库内核开发的基础知识和实践技能,重点介绍如何搭建OceanBase的开发环境。 ... [详细]
  • 本文介绍如何使用 Sortable.js 库实现元素的拖拽和位置交换功能。Sortable.js 是一个轻量级、无依赖的 JavaScript 库,支持拖拽排序、动画效果和多种插件扩展。通过简单的配置和事件处理,可以轻松实现复杂的功能。 ... [详细]
  • 探讨一个显示数字的故障计算器,它支持两种操作:将当前数字乘以2或减去1。本文将详细介绍如何用最少的操作次数将初始值X转换为目标值Y。 ... [详细]
  • 本文详细介绍了Java编程语言中的核心概念和常见面试问题,包括集合类、数据结构、线程处理、Java虚拟机(JVM)、HTTP协议以及Git操作等方面的内容。通过深入分析每个主题,帮助读者更好地理解Java的关键特性和最佳实践。 ... [详细]
  • XNA 3.0 游戏编程:从 XML 文件加载数据
    本文介绍如何在 XNA 3.0 游戏项目中从 XML 文件加载数据。我们将探讨如何将 XML 数据序列化为二进制文件,并通过内容管道加载到游戏中。此外,还会涉及自定义类型读取器和写入器的实现。 ... [详细]
  • Android LED 数字字体的应用与实现
    本文介绍了一种适用于 Android 应用的 LED 数字字体(digital font),并详细描述了其在 UI 设计中的应用场景及其实现方法。这种字体常用于视频、广告倒计时等场景,能够增强视觉效果。 ... [详细]
  • RecyclerView初步学习(一)
    RecyclerView初步学习(一)ReCyclerView提供了一种插件式的编程模式,除了提供ViewHolder缓存模式,还可以自定义动画,分割符,布局样式,相比于传统的ListVi ... [详细]
  • 扫描线三巨头 hdu1928hdu 1255  hdu 1542 [POJ 1151]
    学习链接:http:blog.csdn.netlwt36articledetails48908031学习扫描线主要学习的是一种扫描的思想,后期可以求解很 ... [详细]
  • This document outlines the recommended naming conventions for HTML attributes in Fast Components, focusing on readability and consistency with existing standards. ... [详细]
  • 在现代网络环境中,两台计算机之间的文件传输需求日益增长。传统的FTP和SSH方式虽然有效,但其配置复杂、步骤繁琐,难以满足快速且安全的传输需求。本文将介绍一种基于Go语言开发的新一代文件传输工具——Croc,它不仅简化了操作流程,还提供了强大的加密和跨平台支持。 ... [详细]
author-avatar
进出口产地
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有