使用POI读写word docx文件

Android如何读写word文件 - 使用Apache POI 组件读写doc和docx文件 最近在项目中要生成Word的doc和docx文件,一番百度google之后,发现通过java语言实现的主流是Apache的POI组件。除了POI,这里还有另一种实现,不过我没有去研究,有兴趣的同学可以研究研究。 关于POI可以访问Apache POI的官网获取详细的信息。 进入主题! 由于项目中只是用到了doc和docx的组件,下面也只是介绍这两个组件的使用 一、在Android S... 阅读详情

POI在读写word docx文件时是通过xwpf模块来进行的,其核心是XWPFDocument。一个XWPFDocument代表一个docx文档,其可以用来读docx文档,也可以用来写docx文档。XWPFDocument中主要包含下面这几种对象:

XWPFParagraph:代表一个段落。

XWPFRun:代表具有相同属性的一段文本。

XWPFTable:代表一个表格。

XWPFTableRow:表格的一行。

XWPFTableCell:表格对应的一个单元格。

1.读docx文件

跟读doc文件一样,POI在读docx文件的时候也有两种方式,通过XWPFWordExtractor和通过XWPFDocument。在XWPFWordExtractor读取信息时其内部还是通过XWPFDocument来获取的。

1.1通过XWPFWordExtractor读

在使用XWPFWordExtractor读取docx文档的内容时,我们只能获取到其文本,而不能获取到其文本对应的属性值。下面是一段使用XWPFWordExtractor来读取docx文档内容的示例代码:

    public class XwpfTest {

       /**
        * 通过XWPFWordExtractor访问XWPFDocument的内容
        * @throws Exception
        */
       @Test
       public void testReadByExtractor() throws Exception {
          InputStream is = new FileInputStream("D:\\test.docx");
          XWPFDocument doc = new XWPFDocument(is);
          XWPFWordExtractor extractor = new XWPFWordExtractor(doc);
          String text = extractor.getText();
          System.out.println(text);
          CoreProperties coreProps = extractor.getCoreProperties();
          this.printCoreProperties(coreProps);
          this.close(is);
       }

       /**
        * 输出CoreProperties信息
        * @param coreProps
        */
       private void printCoreProperties(CoreProperties coreProps) {
          System.out.println(coreProps.getCategory());   //分类
          System.out.println(coreProps.getCreator()); //创建者
          System.out.println(coreProps.getCreated()); //创建时间
          System.out.println(coreProps.getTitle());   //标题
       }

       /**
        * 关闭输入流
        * @param is
        */
       private void close(InputStream is) {
          if (is != null) {
             try {
                is.close();
             } catch (IOException e) {
                e.printStackTrace();
             }
          }
       }

    }

1.2 通过XWPFDocument读

在通过XWPFDocument读取docx文档时,我们就可以获取到文本比较精确的属性信息了。比如我们可以获取到某一个XWPFParagraph、XWPFRun或者是某一个XWPFTable,包括它们对应的属性信息。下面是一个使用XWPFDocument读取docx文档的示例:

    public class XwpfTest {

       /**
        * 通过XWPFDocument对内容进行访问。对于XWPF文档而言,用这种方式进行读操作更佳。
        * @throws Exception
        */
       @Test
       public void testReadByDoc() throws Exception {
          InputStream is = new FileInputStream("D:\\table.docx");
          XWPFDocument doc = new XWPFDocument(is);
          List<XWPFParagraph> paras = doc.getParagraphs();
          for (XWPFParagraph para : paras) {
             //当前段落的属性
    //       CTPPr pr = para.getCTP().getPPr();
             System.out.println(para.getText());
          }
          //获取文档中所有的表格
          List<XWPFTable> tables = doc.getTables();
          List<XWPFTableRow> rows;
          List<XWPFTableCell> cells;
          for (XWPFTable table : tables) {
             //表格属性
    //       CTTblPr pr = table.getCTTbl().getTblPr();
             //获取表格对应的行
             rows = table.getRows();
             for (XWPFTableRow row : rows) {
                //获取行对应的单元格
                cells = row.getTableCells();
                for (XWPFTableCell cell : cells) {
                    System.out.println(cell.getText());;
                }
             }
          }
          this.close(is);
       }

       /**
        * 关闭输入流
        * @param is
        */
       private void close(InputStream is) {
          if (is != null) {
             try {
                is.close();
             } catch (IOException e) {
                e.printStackTrace();
             }
          }
       }

    }

2.写docx文件

2.1直接通过XWPFDocument生成

在使用XWPFDocument写docx文件时不需要像使用HWPFDocument写doc文件那样必须从一个doc文件开始,我们可以直接new一个空的XWPFDocument,之后再往这个XWPFDocument里面填充内容,然后再把它写入到对应的输出流中。下面是使用XWPFDocument生成docx文件的示例代码:

    public class XwpfTest {

       /**
        * 基本的写操作
        * @throws Exception
        */
       @Test
       public void testSimpleWrite() throws Exception {
          //新建一个文档
          XWPFDocument doc = new XWPFDocument();
          //创建一个段落
          XWPFParagraph para = doc.createParagraph();

          //一个XWPFRun代表具有相同属性的一个区域。
          XWPFRun run = para.createRun();
          run.setBold(true); //加粗
          run.setText("加粗的内容");
          run = para.createRun();
          run.setColor("FF0000");
          run.setText("红色的字。");
          OutputStream os = new FileOutputStream("D:\\simpleWrite.docx");
          //把doc输出到输出流
          doc.write(os);
          this.close(os);
       }

       /***
        * 写一个表格
        * @throws Exception
        */
       @Test
       public void testWriteTable() throws Exception {
          XWPFDocument doc = new XWPFDocument();
          //创建一个5行5列的表格
          XWPFTable table = doc.createTable(5, 5);
          //这里增加的列原本初始化创建的那5行在通过getTableCells()方法获取时获取不到,但通过row新增的就可以。
    //    table.addNewCol(); //给表格增加一列,变成6列
          table.createRow(); //给表格新增一行,变成6行
          List<XWPFTableRow> rows = table.getRows();
          //表格属性
          CTTblPr tablePr = table.getCTTbl().addNewTblPr();
          //表格宽度
          CTTblWidth width = tablePr.addNewTblW();
          width.setW(BigInteger.valueOf(8000));
          XWPFTableRow row;
          List<XWPFTableCell> cells;
          XWPFTableCell cell;
          int rowSize = rows.size();
          int cellSize;
          for (int i=0; i<rowSize; i++) {
             row = rows.get(i);
             //新增单元格
             row.addNewTableCell();
             //设置行的高度
             row.setHeight(500);
             //行属性
    //       CTTrPr rowPr = row.getCtRow().addNewTrPr();
             //这种方式是可以获取到新增的cell的。
    //       List<CTTc> list = row.getCtRow().getTcList();
             cells = row.getTableCells();
             cellSize = cells.size();
             for (int j=0; j<cellSize; j++) {
                cell = cells.get(j);
                if ((i+j)%2==0) {
                    //设置单元格的颜色
                    cell.setColor("ff0000"); //红色
                } else {
                    cell.setColor("0000ff"); //蓝色
                }
                //单元格属性
                CTTcPr cellPr = cell.getCTTc().addNewTcPr();
                cellPr.addNewVAlign().setVal(STVerticalJc.CENTER);
                if (j == 3) {
                    //设置宽度
                    cellPr.addNewTcW().setW(BigInteger.valueOf(3000));
                }
                cell.setText(i + ", " + j);
             }
          }
          //文件不存在时会自动创建
          OutputStream os = new FileOutputStream("D:\\table.docx");
          //写入文件
          doc.write(os);
          this.close(os);
       }

       /**
        * 关闭输出流
        * @param os
        */
       private void close(OutputStream os) {
          if (os != null) {
             try {
                os.close();
             } catch (IOException e) {
                e.printStackTrace();
             }
          }
       }

    }

2.2以docx文件作为模板

当然,我们也可以像写doc文件那样,先以一个docx文件作为模板,然后建立基于该docx文件的XWPFDocument对象,再把里面一些变化的信息在运行时进行替换,之后将XWPFDocument进行输出就可以了。所不同的是XWPFDocument中没有像HWPFDocument中那样的Range可以用来直接替换内容。而且底层的XWPFParagraph和XWPFRun也不支持直接将文本进行替换。倒是XWPFRun提供了一个设置文本的方法,不过新的文本不会替换旧的文本,而是会追加到原来的文本之后。现在的一个做法是先找出含有需要替换的变量的XWPFRun,然后将其移除,之后在原来的位置新增一个XWPFRun,其对应的文本是替换变量之后的文本。不过你设置的那个的变量的位置不一定就在一个XWPFRun里面,它有可能会被拆分到两个甚至更多的XWPFRun中,所以不是很有必要的话还是不推荐使用这种方式。

假设我们有一个docx文件,其内容是这样的:
这里写图片描述

之后我们以该文件作为模板,利用相关数据把里面的变量进行替换,然后把替换后的文档输出到另一个docx文件中。具体做法如下:

    public class XwpfTest {

       /**
        * 用一个docx文档作为模板,然后替换其中的内容,再写入目标文档中。
        * @throws Exception
        */
       @Test
       public void testTemplateWrite() throws Exception {
          Map<String, Object> params = new HashMap<String, Object>();
          params.put("reportDate", "2014-02-28");
          params.put("appleAmt", "100.00");
          params.put("bananaAmt", "200.00");
          params.put("totalAmt", "300.00");
          String filePath = "D:\\word\\template.docx";
          InputStream is = new FileInputStream(filePath);
          XWPFDocument doc = new XWPFDocument(is);
          //替换段落里面的变量
          this.replaceInPara(doc, params);
          //替换表格里面的变量
          this.replaceInTable(doc, params);
          OutputStream os = new FileOutputStream("D:\\word\\write.docx");
          doc.write(os);
          this.close(os);
          this.close(is);
       }

       /**
        * 替换段落里面的变量
        * @param doc 要替换的文档
        * @param params 参数
        */
       private void replaceInPara(XWPFDocument doc, Map<String, Object> params) {
          Iterator<XWPFParagraph> iterator = doc.getParagraphsIterator();
          XWPFParagraph para;
          while (iterator.hasNext()) {
             para = iterator.next();
             this.replaceInPara(para, params);
          }
       }

       /**
        * 替换段落里面的变量
        * @param para 要替换的段落
        * @param params 参数
        */
       private void replaceInPara(XWPFParagraph para, Map<String, Object> params) {
          List<XWPFRun> runs;
          Matcher matcher;
          if (this.matcher(para.getParagraphText()).find()) {
             runs = para.getRuns();
             for (int i=0; i<runs.size(); i++) {
                XWPFRun run = runs.get(i);
                String runText = run.toString();
                matcher = this.matcher(runText);
                if (matcher.find()) {
                    while ((matcher = this.matcher(runText)).find()) {
                       runText = matcher.replaceFirst(String.valueOf(params.get(matcher.group(1))));
                    }
                    //直接调用XWPFRun的setText()方法设置文本时,在底层会重新创建一个XWPFRun,把文本附加在当前文本后面,
                    //所以我们不能直接设值,需要先删除当前run,然后再自己手动插入一个新的run。
                    para.removeRun(i);
                    para.insertNewRun(i).setText(runText);
                }
             }
          }
       }

       /**
        * 替换表格里面的变量
        * @param doc 要替换的文档
        * @param params 参数
        */
       private void replaceInTable(XWPFDocument doc, Map<String, Object> params) {
          Iterator<XWPFTable> iterator = doc.getTablesIterator();
          XWPFTable table;
          List<XWPFTableRow> rows;
          List<XWPFTableCell> cells;
          List<XWPFParagraph> paras;
          while (iterator.hasNext()) {
             table = iterator.next();
             rows = table.getRows();
             for (XWPFTableRow row : rows) {
                cells = row.getTableCells();
                for (XWPFTableCell cell : cells) {
                    paras = cell.getParagraphs();
                    for (XWPFParagraph para : paras) {
                       this.replaceInPara(para, params);
                    }
                }
             }
          }
       }

       /**
        * 正则匹配字符串
        * @param str
        * @return
        */
       private Matcher matcher(String str) {
          Pattern pattern = Pattern.compile("\\$\\{(.+?)\\}", Pattern.CASE_INSENSITIVE);
          Matcher matcher = pattern.matcher(str);
          return matcher;
       }

       /**
        * 关闭输入流
        * @param is
        */
       private void close(InputStream is) {
          if (is != null) {
             try {
                is.close();
             } catch (IOException e) {
                e.printStackTrace();
             }
          }
       }

       /**
        * 关闭输出流
        * @param os
        */
       private void close(OutputStream os) {
          if (os != null) {
             try {
                os.close();
             } catch (IOException e) {
                e.printStackTrace();
             }
          }
       }

    }

经过上面的代码所示的过程处理后,我们替换变量后新输出来的docx文件的内容是这样的:
这里写图片描述

QTableView为例:Qt模型视图委托(MVD)(Model-View-Delegate) QT中的MVD(模型-视图-委托)模式是一种类似于MVC的设计模式,将数据、界面和交互逻辑分离。模型负责数据管理,视图负责显示界面,而委托则嵌入在视图中处理数据的显示和编辑。QT提供了多种视图组件(如QListView、QTreeView、QTableView)和模型类(如QStandardItemModel、QAbstractItemModel),支持数据的多样化呈现。委托(Delegate)通过定制显示和编辑行为增强了视图的灵活性。该模式适用于各类数据结构展示(列表、表格、树形),能够高效处理数据与界面 阅读详情

相关推荐

STM32H743 ADC多通道采样实战:CubeMX配置+DMA传输避坑指南

本文详细介绍了STM32H743 ADC多通道采样的实战配置,包括CubeMX参数设置、DMA传输优化及常见问题解决方案。重点解析了ADC模块的核心特性、多通道采样序列配置、Cache一致性处理等关键技术,帮助开发者高效实现稳定可靠的模拟信号采集系统。

weixin_29175469的博客 611

POI读写Word docx文件

使用POI读写word docx文件 目录 1     读docx文件 1.1     通过XWPFWordExtractor读 1.2     通过XWPFDocument读 2     写docx文件 2.1     直接通过XWPFDocument生成 2.2     以docx文件作为模板          POI在读写word docx文件时是通过xwpf模块来进行...

Elim的博客 1120

WRF-BEM相关参数说明

本参数适用于WRF-BEM模拟武汉市气候。

m0_60013472的博客 1895

POI读取doc、docx文件

1.明确几个概念: Range:它表示一个范围,这个范围可以是整个文档,也可以是里面的某一小节(Section),也可以是某一个段落(Paragraph),还可以是拥有共同属性的一段文本(CharacterRun)。 Section:word文档的一个小节,一个word文档可以由多个小节构成。Paragraph:word文档的一个段落,一个小节可以由多个段落构成。 CharacterRun:具有相...

阿劼 5856

MATLAB打开.m文件乱码解决办法

Matlab打开.m文件出现中文乱码问题,是因为Matlab存在两种编码格式:GBK和UTF-8,而不同版本的Matlab编码格式可能不统一,因此在不同版本的Matlab打开文件,由于编码格式的改变,会导致注释乱码。 1.查看你的Matlab的文件编码方式,在Matlab的命令行窗口输入feature('locale') ,如下图,可以看到默认编码为GBK,那问题就变成了将Matlab的文件编码方式GBK修改成UTF-8; 2.找到你的Matlab安装目录bin文件夹下的lcdata_utf.

zhugby的博客 4万+

(付费请教,防遗忘记录)为什么EDEM bondV1 V2添加后还是没有胶结?????

最近用到了EDEM的胶结功能,在添加了bond V1和V2后,我发现无论颗粒半径设置为多少,接触半径设置为多少,胶结键的参数设置为多少,bond generated数量均为0!!!在后处理中bond中的力也通通为0!!我跟我的同门百思不得其解!!!!最终付费请教了一个大牛,解决了这个问题!!!!答案在文末

zheaa的博客 3099

【用POI读取doc或者docx内容】

用Java 获取doc 或docx内容

weixin_45430750的博客 1771

DDD系列 - 第12讲 如何在DDD中实现Query服务(轻量化CQRS)

轻量化CQRS、整合Repository和DAO的优势。

罗小爬的技术宝书 265

使用POI读写word docx文件(笔记记录)

转载学习

Fiang-As-Dre的博客 2030

25、压电泵致动器变形计算与测量及转弯腔射流特性的有限元分析

本文围绕压电泵致动器的变形计算与测量以及转弯腔射流特性的有限元分析展开研究。通过建立有限元模型和抛物线拟合方法,对压电泵致动器的位移和变形体积进行了详细计算,并探讨了其对传感器性能的影响。同时,利用ANSYS软件对转弯腔在不同角速率输入下的射流特性进行了仿真分析,揭示了流场分布随角速率变化的规律。研究成果为压电流体角速率传感器的设计优化提供了理论依据和技术支持。

ooo22的博客 125

硬件工程师入门基础知识(一)基础元器件认识(二)

我们的电路输入一般是只有两种状态,0V 或者是其它的高电平(1.8V,3.3V,5V 等),截止状态一般不用怎么考虑,因为如果让三极管的 Vbe=0,自然就截止了,重要的是饱和状态如何保证。也就是说只要 Rb

小幽余生不加糖 1万+

docx poi 原理_使用POI读写word docx文件

目录1读docx文件1.1通过XWPFWordExtractor读1.2通过XWPFDocument读2写docx文件2.1直接通过XWPFDocument生成2.2以docx文件作为模板POI在读写word docx文件时是通过xwpf模块来进行的,其核心是XWPFDocument。一个XWPFDocument代表一个docx文档,其可...

weixin_34861192的博客 673

【2024-06-21】网易互娱秋招实习笔试三道编程题解

恭喜发现宝藏!搜索公众号【TechGuide】回复公司名,解锁更多新鲜好文和互联网大厂的笔经面经。作者@TechGuide【全网同名】

试问道几许 1055

使用POI读写word docx文件【docx总结的不错】

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_34066347的博客 649

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

使用POI读写Word文件(兼容doc与docx版本)

调用示例:   File wordFile = new File("D:\\temp.doc"); //读取Word文档中所有文本内容,以字符串形式返回 System.out.println(WordFileUtil.extractTextFromWordFile(wordFile));   工具类源码:   Word2003版本工具类:   /** * Word2...

chong0660的专栏 2421

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

上一篇: POI批量替换world文档XWPFParagraph.getRuns 出现分段混乱(附源码)
下一篇: NOPI读取Word模板并保存
.NET跨平台
博客等级 码龄15年 6066粉丝 738原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值