Apache POI对Word的处理

2024-08-27 16:58
文章标签 处理 apache word poi

本文主要是介绍Apache POI对Word的处理,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

写在前面

当我们对docx进行内容上的修改时,可以在修改后对docx文件用压缩包软件进行解压,然后在解压出来的文件夹里的word文件夹下的document.xml文件进行查看对比(毕竟docx是采用ooxml标准,所以内容及其属性都是以xml的形式来写)。

解压后的文件结构大致如下:

├── [Content_Types].xml
├── _rels
├── _xmlsignatures (该文件夹会在有数字签名的情况下生成)
│   ├── _rels
│   │   └── origin.sigs.rels
│   ├── origin.sigs
│   └── sig1.xml
├── docProps
│   ├── app.xml
│   └── core.xml
└── word├── _rels│   └── document.xml.rels├── document.xml├── fontTable.xml├── settings.xml├── styles.xml├── theme│   └── theme1.xml└── webSettings.xml

代码部分是groovy,与Java差别不大,很容易进行改写。

操作

1.添加图片

1.1 常规

Apache POI官方提供了一些简单的samples,包含了图片和图表的添加等。

def addImage(String doc, String img, int width, int height) {//判断图片格式int format = adjustImageFormat(img)if (format != -1) {//针对已存在的文件,应使用            //XWPFDocument document = new XWPFDocument(new FileInputStream(doc))XWPFDocument document = new XWPFDocument()XWPFParagraph paragraph = document.createParagraph()XWPFRun run = paragraph.createRun()//获取图片文件,路径,格式和大小run.addPicture(new FileInputStream(img), format, img, Units.toEMU(width), Units.toEMU(height))FileOutputStream outputStream = new FileOutputStream(doc)document.write(outputStream)}}/*** 判断图片格式* @param imgFile* @return*/private int adjustImageFormat(String imgFile) {int formatif (imgFile.endsWith(".emf")) format = XWPFDocument.PICTURE_TYPE_EMFelse if (imgFile.endsWith(".wmf")) format = XWPFDocument.PICTURE_TYPE_WMFelse if (imgFile.endsWith(".pict")) format = XWPFDocument.PICTURE_TYPE_PICTelse if (imgFile.endsWith(".jpeg") || imgFile.endsWith(".jpg")) format = XWPFDocument.PICTURE_TYPE_JPEGelse if (imgFile.endsWith(".png")) format = XWPFDocument.PICTURE_TYPE_PNGelse if (imgFile.endsWith(".dib")) format = XWPFDocument.PICTURE_TYPE_DIBelse if (imgFile.endsWith(".gif")) format = XWPFDocument.PICTURE_TYPE_GIFelse if (imgFile.endsWith(".tiff")) format = XWPFDocument.PICTURE_TYPE_TIFFelse if (imgFile.endsWith(".eps")) format = XWPFDocument.PICTURE_TYPE_EPSelse if (imgFile.endsWith(".bmp")) format = XWPFDocument.PICTURE_TYPE_BMPelse if (imgFile.endsWith(".wpg")) format = XWPFDocument.PICTURE_TYPE_WPGelse {System.err.println("Unsupported picture: " + imgFile +". Expected emf|wmf|pict|jpeg|png|dib|gif|tiff|eps|bmp|wpg")return -1}return format}

从目前来看,图片的添加似乎只能进行常规性的操作,就是在文字的后面追加。而对于我们想让图片对文字进行环绕的相关操作(比方说 衬于文字下方 )是没有的。

1.2 图片属性添加

在一开始的时候我们说过,当我们对word的内容进行修改的时候,它是在对document.xml里的相关内容进行修改,那么我们要如何看懂里面的内容呢?可以通过officeopenxml 网站进行了解和学习。

以我们这一节为例,我们需要了解在docx下插入图片后,对其进行相关的调整,那么就应该参考这里 DrawingML Overview

我们新建一个docx文档,然后插入图片,保存后我们可以看到其document.xml里的内容是这样(只截取主要部分):

<w:drawing><wp:inline distB="0" distL="0" distR="0" distT="0"><wp:extent cx="5270500" cy="7058025"/><wp:effectExtent b="3175" l="0" r="0" t="0"/><wp:docPr id="1" name="图片 1"/><wp:cNvGraphicFramePr><a:graphicFrameLocks noChangeAspect="1" xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"/></wp:cNvGraphicFramePr><a:graphic xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"><a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/picture"><pic:pic xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture"><pic:nvPicPr><pic:cNvPr id="1" name="D59B2F44-A382-4B8D-94E7-8457E3581342.jpg"/><pic:cNvPicPr/></pic:nvPicPr><pic:blipFill><a:blip cstate="print" r:embed="rId4"><a:extLst><a:ext uri="{28A0092B-C50C-407E-A947-70E740481C1C}"><a14:useLocalDpi val="0" xmlns:a14="http://schemas.microsoft.com/office/drawing/2010/main"/></a:ext></a:extLst></a:blip><a:stretch><a:fillRect/></a:stretch></pic:blipFill><pic:spPr><a:xfrm><a:off x="0" y="0"/><a:ext cx="5270500" cy="7058025"/></a:xfrm><a:prstGeom prst="rect"><a:avLst/></a:prstGeom></pic:spPr></pic:pic></a:graphicData></a:graphic></wp:inline></w:drawing>

然后我们把图片的 环绕文字 设置为 浮于文字之上 ,变化后的document.xml为:

<w:drawing><wp:anchor allowOverlap="1" behindDoc="0" distB="0" distL="114300" distR="114300" distT="0" layoutInCell="1" locked="0" relativeHeight="251658240" simplePos="0"><wp:simplePos x="0" y="0"/><wp:positionH relativeFrom="column"><wp:posOffset>1905</wp:posOffset></wp:positionH><wp:positionV relativeFrom="paragraph"><wp:posOffset>40005</wp:posOffset></wp:positionV><wp:extent cx="5270500" cy="7058025"/><wp:effectExtent b="3175" l="0" r="0" t="0"/><wp:wrapNone/><wp:docPr id="1" name="图片 1"/><wp:cNvGraphicFramePr><a:graphicFrameLocks noChangeAspect="1" xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"/></wp:cNvGraphicFramePr><a:graphic xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"><a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/picture"><pic:pic xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture"><pic:nvPicPr><pic:cNvPr id="1" name="D59B2F44-A382-4B8D-94E7-8457E3581342.jpg"/><pic:cNvPicPr/></pic:nvPicPr><pic:blipFill><a:blip cstate="print" r:embed="rId4"><a:extLst><a:ext uri="{28A0092B-C50C-407E-A947-70E740481C1C}"><a14:useLocalDpi val="0" xmlns:a14="http://schemas.microsoft.com/office/drawing/2010/main"/></a:ext></a:extLst></a:blip><a:stretch><a:fillRect/></a:stretch></pic:blipFill><pic:spPr><a:xfrm><a:off x="0" y="0"/><a:ext cx="5270500" cy="7058025"/></a:xfrm><a:prstGeom prst="rect"><a:avLst/></a:prstGeom></pic:spPr></pic:pic></a:graphicData></a:graphic><wp14:sizeRelH relativeFrom="page"><wp14:pctWidth>0</wp14:pctWidth></wp14:sizeRelH><wp14:sizeRelV relativeFrom="page"><wp14:pctHeight>0</wp14:pctHeight></wp14:sizeRelV></wp:anchor></w:drawing>

通过对比,我们主要看到的一个变化是从< wp:inline >标签替换为< wp:anchor >标签开始,这是图片从内联到浮动的一个标志。然后是对anchor的属性以及它的下级标签等进行一些相关的设置,具体的内容参考 Positioning within a Word Processing Document 。当我们从内联切换到浮动后,对图片进行 浮在文字上 的设置主要是anchor标签下的behindDoc属性设为false,同时出现一个< wp:wrapNone/>的空标签。

以上主要是对从ooxml的角度来看当图片改变时在docx文档上的变化。那么目前我们要怎么通过Apache POI来处理?由于Apache POI应该只是进行了常规性的操作,所以我们需要自己尝试来编写一些规则,可以参考Stack Overflow上的这个问题Wrap Text in Apache POI(docx)? 进行处理。

1.3 参考

关于图片对文字的环绕请参考 :Positioning within a Word Processing Document - Floating Pictures - Text Wrapping

关于图片位置的确定请参考 :Positioning within a Word Processing Document - Floating Pictures - Positioning

1.4 其它

  1. 关于CTAnchor missing dependency CTPosH的问题
    使用Groovy编译的过程中报出以下的错误:
Error:Groovyc: While compiling signer-office_main: 
java.lang.RuntimeException: java.lang.NoClassDefFoundError: 
Unable to load class org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTAnchor 
due to missing dependency 
org/openxmlformats/schemas/drawingml/x2006/wordprocessingDrawing/CTPosH

原因在于poi-schema库下缺乏了CTPosH这个类,因为这是一个精简版的jar,只包含一些典型的类,所以体积比较小。因此为了解决这个问题,我们需要使用完整的schema的jar包: I’m using the poi-ooxml-schemas jar, but my code is failing with “java.lang.NoClassDefFoundError: org/openxmlformats/schemas/something


2. 安全

2.1 签名

 def addSignature(String doc) {//pfx证书密码def password = pfxPassoword.toCharArray()File file = new File(pfxPath)KeyStore keystore = KeyStore.getInstance("PKCS12")FileInputStream fis = new FileInputStream(file)keystore.load(fis, password)fis.close()//获取别名Enumeration enumas = keystore.aliases()String alias = nullwhile (enumas.hasMoreElements()) {alias = (String) enumas.nextElement()}//准备密钥对Key key = keystore.getKey(alias, password)KeyPair keyPair = nullif (key instanceof PrivateKey) {Certificate cert = keystore.getCertificate(alias)PublicKey publicKey = cert.getPublicKey()keyPair = new KeyPair(publicKey, (PrivateKey) key)}//签名配置SignatureConfig signatureConfig = new SignatureConfig()signatureConfig.setKey(keyPair.getPrivate())X509Certificate x509 = (X509Certificate) keystore.getCertificate(alias)signatureConfig.setSigningCertificateChain(Collections.singletonList(x509))//打开文件OPCPackage opcPackage = OPCPackage.open(new File(doc), PackageAccess.READ_WRITE)signatureConfig.setOpcPackage(opcPackage)//装载签名配置SignatureInfo si = new SignatureInfo()si.setSignatureConfig(signatureConfig)//调用签名方法si.confirmSignature()//关闭文件opcPackage.close()}

2.2 验签

  boolean verify(String file) {boolean result = falseInputStream inputStream = FileMagic.prepareToCheckMagic(new FileInputStream(file))if (FileMagic.valueOf(inputStream) == FileMagic.OLE2) {System.out.println("Unsupport doc format")} else if (FileMagic.valueOf(inputStream) == FileMagic.OOXML) {try {OPCPackage opcPackage = OPCPackage.open(file, PackageAccess.READ)SignatureConfig signatureConfig = new SignatureConfig()signatureConfig.setOpcPackage(opcPackage)SignatureInfo signatureInfo = new SignatureInfo()signatureInfo.setSignatureConfig(signatureConfig)result = signatureInfo.verifySignature()} catch (InvalidFormatException e) {e.printStackTrace()}}return result}

2.3 获取证书信息

在Apache POI 4.0.0版本里对读取签名文档里的证书信息做了进一步的完善和调整。
4.0.0版本所搭配的ooxml-schemas版本应为1.4

    def poi_version = "4.0.0"compile "org.apache.poi:poi:${poi_version}"compile "org.apache.poi:poi-ooxml:${poi_version}"compile "org.apache.poi:ooxml-schemas:1.4"

在获取证书的时候要注意两个点:

  1. 设置signatureConfig.setUpdateConfigOnValidate(true)
  2. 调用si.verifySignature()
    执行完以上两步后,SignatureConfig的实例就会被更新,我们就可以获取到如签署时间,签名证书等其他信息
            OPCPackage opcPackage = OPCPackage.open(new ByteArrayInputStream(docx))SignatureConfig signatureConfig = new SignatureConfig()signatureConfig.setUpdateConfigOnValidate(true)signatureConfig.setOpcPackage(opcPackage)SignatureInfo si = new SignatureInfo()si.setSignatureConfig(signatureConfig)si.verifySignature()Date signDate = signatureConfig.executionTime//读取签名证书信息for (X509Certificate x509Certificate : signatureConfig.signingCertificateChain) {......}

2.3 参考

Apache POI - Encryption support

Extract configuration while verifying XML signatures

这篇关于Apache POI对Word的处理的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1112254

相关文章

利用Go语言开发文件操作工具轻松处理所有文件

《利用Go语言开发文件操作工具轻松处理所有文件》在后端开发中,文件操作是一个非常常见但又容易出错的场景,本文小编要向大家介绍一个强大的Go语言文件操作工具库,它能帮你轻松处理各种文件操作场景... 目录为什么需要这个工具?核心功能详解1. 文件/目录存javascript在性检查2. 批量创建目录3. 文件

Java使用多线程处理未知任务数的方案介绍

《Java使用多线程处理未知任务数的方案介绍》这篇文章主要为大家详细介绍了Java如何使用多线程实现处理未知任务数,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 知道任务个数,你可以定义好线程数规则,生成线程数去跑代码说明:1.虚拟线程池:使用 Executors.newVir

一文带你深入了解Python中的GeneratorExit异常处理

《一文带你深入了解Python中的GeneratorExit异常处理》GeneratorExit是Python内置的异常,当生成器或协程被强制关闭时,Python解释器会向其发送这个异常,下面我们来看... 目录GeneratorExit:协程世界的死亡通知书什么是GeneratorExit实际中的问题案例

Java利用poi实现word表格转excel

《Java利用poi实现word表格转excel》这篇文章主要为大家详细介绍了Java如何利用poi实现word表格转excel,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 一、每行对象类需要针对不同的表格进行对应的创建。package org.example.wordToEx

最新Spring Security实战教程之表单登录定制到处理逻辑的深度改造(最新推荐)

《最新SpringSecurity实战教程之表单登录定制到处理逻辑的深度改造(最新推荐)》本章节介绍了如何通过SpringSecurity实现从配置自定义登录页面、表单登录处理逻辑的配置,并简单模拟... 目录前言改造准备开始登录页改造自定义用户名密码登陆成功失败跳转问题自定义登出前后端分离适配方案结语前言

Python如何在Word中生成多种不同类型的图表

《Python如何在Word中生成多种不同类型的图表》Word文档中插入图表不仅能直观呈现数据,还能提升文档的可读性和专业性,本文将介绍如何使用Python在Word文档中创建和自定义各种图表,需要的... 目录在Word中创建柱形图在Word中创建条形图在Word中创建折线图在Word中创建饼图在Word

Python批量调整Word文档中的字体、段落间距及格式

《Python批量调整Word文档中的字体、段落间距及格式》这篇文章主要为大家详细介绍了如何使用Python的docx库来批量处理Word文档,包括设置首行缩进、字体、字号、行间距、段落对齐方式等,需... 目录关键代码一级标题设置  正文设置完整代码运行结果最近关于批处理格式的问题我查了很多资料,但是都没

使用Apache POI在Java中实现Excel单元格的合并

《使用ApachePOI在Java中实现Excel单元格的合并》在日常工作中,Excel是一个不可或缺的工具,尤其是在处理大量数据时,本文将介绍如何使用ApachePOI库在Java中实现Excel... 目录工具类介绍工具类代码调用示例依赖配置总结在日常工作中,Excel 是一个不可或缺的工http://

Gin框架中的GET和POST表单处理的实现

《Gin框架中的GET和POST表单处理的实现》Gin框架提供了简单而强大的机制来处理GET和POST表单提交的数据,通过c.Query、c.PostForm、c.Bind和c.Request.For... 目录一、GET表单处理二、POST表单处理1. 使用c.PostForm获取表单字段:2. 绑定到结

mysql8.0无备份通过idb文件恢复数据的方法、idb文件修复和tablespace id不一致处理

《mysql8.0无备份通过idb文件恢复数据的方法、idb文件修复和tablespaceid不一致处理》文章描述了公司服务器断电后数据库故障的过程,作者通过查看错误日志、重新初始化数据目录、恢复备... 周末突然接到一位一年多没联系的妹妹打来电话,“刘哥,快来救救我”,我脑海瞬间冒出妙瓦底,电信火苲马扁.