`
alang
  • 浏览: 134357 次
  • 性别: Icon_minigender_1
  • 来自: 地球
文章分类
社区版块
存档分类
最新评论

Java 读写 Word doc 文件的方法(POI代码示例)

阅读更多

都说懒人推动社会进步。
我的出发点是,想做个自动生成工作日志的工具。思路是读取google日历中我每日的工作记录,填充生成公司规定格式的word文件,然后再调用邮件函数发送邮件到领导的信箱里面去。

这其中一环就是Java读写doc文件。网上找了不少资料,初步选用了Apache POI,可以读写整个Office系列的各种文档,并且不依赖Office的任何库,纯JAVA代码。直接读写doc的二进制文件,我最喜欢了。相对的有个Java com 桥的方法,用Java来操作com对象,后台运行隐藏的word程序,甚为不喜。

POI API Documentation 的文档写的太差了,没有例子,Apache 的 POI 项目主页也没有代码,直接说想看代码,请去svn下载代码,阅读他的单元测试用例,TestCase。
最后磕磕绊绊写了下面的一个测试的例子。基本可以看清这个POI的hwpf库,读写word doc 文件的方法。代码、注释都是原创,高手飘过去就行了。
import java.io.*;
import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.hwpf.usermodel.Paragraph;
import org.apache.poi.hwpf.usermodel.Range;
import org.apache.poi.hwpf.usermodel.Section;

public class Main {

  public static void main(String[] args) {
    try {
        //新建 HWPFDocument 对象,读入doc文件
        HWPFDocument doc = new HWPFDocument(new FileInputStream("c:\\test.doc"));
        //得到整个doc文档的Range,可以理解为文档对象
        Range r = doc.getRange();

        System.out.println("Example you supplied:");
        System.out.println("---------------------");

        String text = new String("");
        //得到整个文档里面的所有纯文字,包含回车换行。一段是一行
        text = r.text();
        //System.out.println(text);

        //得到整个文档的分节数。一般只有一节,排版很漂亮的word文档一般分为多节
        System.out.println("numSections: " + r.numSections());
        //得到倒数第一节的Section对象
        Section section = r.getSection(r.numSections() - 1);
        //得到该节里面的段落数
        System.out.println(section.numParagraphs());
        System.out.println("numParagraphs: " + section.numParagraphs());

        String searchText = "${Ryan}";
        String replacementText = "Apache Software Foundation";

        //循环得到每一段落的文字。这个跟Range.text()是不同的。
        for (int np = 0; np < section.numParagraphs(); np++) {
          Paragraph para = section.getParagraph(np);
          //得到该段落的文字
          text = para.text();
          //System.out.println(Integer.toString(np) + ":" + text);
          int offset = text.indexOf(searchText);
          if (offset >= 0) {
              System.out.println(Integer.toString(np) + ":" + para.text());
              //如果找到了,就进行文字的替换。replaceText只能针对段落
              para.replaceText(searchText, replacementText);
              break;
            }
        }
        
        //写入到新的doc文件
        OutputStream outdoc = new FileOutputStream("c:\\test2.doc");
        doc.write(outdoc);
        
        outdoc.flush();
        outdoc.close();

    } catch (Throwable t) {
        t.printStackTrace();
      }
    }
}
 

编译运行很顺利,但是悲剧的是,最后调用write方法写入的doc文件打不开了,报格式错误,用Notepad++打开这个doc文件对比原来的,发现文字确实替换成功了,但是文件的尾巴上少了一部分内容,二进制和assic混合的,格式看来是被破坏了。

忙活了半天,最后发现杯具了。应该是兼容性的问题。改天去他们的邮件列表问问。或者路过的看官知道的,指导一下我。

我在写这个文章的时候,又想到一个绝妙的注意。何必绕道这么远呢?
实施工作日志内容来源于google calendar,如果能够利用google app doc 自己本身的宏:google script,的功能,读取日历数据,形成doc文件,调用gmail发送到指定的信箱,不是齐活了吗?费不着用Java了。

其实在决定用java之前,想过用VB,这个做肯定不存在问题,VB操作com对象本身是轻车熟路,顶多再找个发邮件的库,实在不行了没人手工发送。方法还是很多的。

科技以懒人为本。

2
4
分享到:
评论
3 楼 aasddsasda 2014-01-20  
感谢博主分享,正在用poi做一个模板替换的功能,如果直接用range的replaceText替换中文会出错,分段落替换就不会有问题了
2 楼 sendreams 2014-01-19  
poi项目经过这么多年的发展,感觉还不是很给力,hwpf和xwpf分别处理doc和docx文档,这对开发者来说需要使用两套api。
1 楼 lord_is_layuping 2013-07-26  
poi真不让人省心

相关推荐

Global site tag (gtag.js) - Google Analytics