转自:http://www.blogjava.net/lonsy/archive/2009/01/09/250713.html

Jacob项目的官方地址: Http://sourceforge.net/projects/jacob-project/
官方介绍:
    JACOB is a JAVA-COM Bridge that allows you to call COM Automation components from Java. It uses JNI to make native calls to the COM libraries. JACOB runs on x86 and x64 environments supporting 32 bit and 64 bit JVMs
它是一个使用jni来调用com组件及其库文件的工具。这里仅介绍处理word文档。

首先要部署其dll文件。jacob-1.14.3-x86.dll 或 jacob-1.14.3-x64.dll,下载的文件解压后即可看到。我是直接将dll文件放在windows\system32目录下的,方便,当然也有其他做法。
其次,就是把其jar文件路径加入Windows路径中。
接着就可以在你的Java程序中调用了。我总结下大概有下面几个阶段:

1. 初始化相关参数,代码如下:

// 打开Word应用程序
ActiveXComponent app = new ActiveXComponent("Word.Application");
// 设置word不可见
app.setProperty("Visible", new Variant(false));
// 打开word文件
Dispatch word = app.getProperty("Documents").toDispatch();
Dispatch doc = Dispatch.invoke(word, "Open", Dispatch.Method, new Object[] {"File Name", new Variant(false), new Variant(false) }, new int[1]).toDispatch();
//获取指针
Dispatch cursor = app.getProperty("Selection").toDispatch();

如上,我们打开了一个名为File Name的word文件,你可能会觉得最后那句看起来很繁琐,是的,有更好的代替方式,如下:

Dispatch doc = Dispatch.call(word, "Open", new Variant(false), new Variant(false)).toDisptach();

这正是Jacob给我们提供的两种调用方式。

2. 处理word文档,如果你先前有VBA相关开发经验,那就简单了。没有的也没事,打开office程序目录下的2052\VBAWD10.chm,这里有Word的对象模型的所有记录。
接着讲述下Jacob中两种最常用的类型:
Variant:这是一种可变的类型,用于Jacob中几乎所有函数的返回值,并可转换为其他任何类型,包括Java基本类型。当然,应该按需要与规则来。
Dispatch:Object represents MS level dispatch object. Each instance of this points at some data structure on the MS windows side.就是说可以代表所有对象模型。
有所了解后我们来看对模型的处理方式。
当我们获得一个模型后,如前面打开的doc文档,均已转换成一个Dispatch对象。只有转换后才能读取、设置其属性,或者调用其方法,如下:

//获取其属性,表格的集合
Dispatch tables = Dispatch.get(doc, "Tables").toDispatch();
//调用方法取得其中的第一张表格
Dispatch table = Dispatch.call(this.tables, "Item", new Variant(0)).toDispatch();
//修改此表格第一行第一列的单元格
Dispatch cell = Dispatch.call(table,"Cell", Integer.toString(1), Integer.toString(1)).toDispatch();
Dispatch.call(cell, "Select");
Dispatch.put(cursor, "Text", "New String");

这就是简单的处理,更多的还是多了解了解对象模型吧

3. 关闭文档及进程

//关闭文档且不保存
Dispatch.call(doc, "Close", new Variant(false));
//退出进程对象
app.invoke("Quit", new Variant[] {});

更多请参看下载文件中的API帮助文档..

下面是我写的类,用于封装其功能。(注意,这个类并没有涉及多个word文档线程的处理)

import com.jacob.com.*;
import com.jacob.activeX.*;

/**
 *
 * @author Lonsy
 */
public class WordHandle {
    
    //运行时的Word程序
    private ActiveXComponent app;

//word对象
    private Dispatch words;

//当前的word文档
    private Dispatch doc;

//当前光标位置
    private Dispatch cursor;

//当前文档是否只读
    private boolean readOnly;

//当前文档中所有表格
    private Dispatch tables;

//当前所在表格
    private Dispatch table;

private int count;

public WordHandle()
    {
        this.app = new ActiveXComponent("Word.Application");
        this.app.setProperty("Visible", new Variant(false));    // 设置word不可见
        words = this.app.getProperty("Documents").toDispatch();
        this.doc = null;
        this.cursor = null;
        this.readOnly = true;
        this.count = 0;
    }

/**
     * 打开word文件
     * @param fileName 文件名,使用绝对路径
     * @param readOnly 是否只读
     * @return
     * @throws java.lang.Exception
     */
    public boolean open(String fileName, boolean readOnly) throws Exception
    {
        if (doc != null)
        {
            System.out.println("当前文件未关闭");
            return false;
        }
        this.doc = Dispatch.invoke(this.words, "Open", Dispatch.Method, new Object[] {fileName, new Variant(false), new Variant(readOnly)}, new int[1]).toDispatch();
        this.cursor = app.getProperty("Selection").toDispatch();
        this.tables = Dispatch.get(this.doc,"Tables").toDispatch();
        this.readOnly = readOnly;
        this.count = Dispatch.get(Dispatch.get(this.doc, "Words").toDispatch(), "Count").getInt() - 1;
        System.out.println("打开文件" + fileName + (readOnly ? " ReadOnly" : " Writable"));
        return true;
    }

/**
     * 建立新的Word文件
     * @return
     * @throws java.lang.Exception
     */
    public boolean newFile() throws Exception
    {
        if (doc != null)
        {
            System.out.println("当前文件未关闭");
            return false;
        }
        this.doc = Dispatch.call(this.words, "Add").toDispatch();
        this.readOnly = false;
        this.cursor = app.getProperty("Selection").toDispatch();
        this.tables = Dispatch.get(this.doc,"Tables").toDispatch();
        System.out.println("新建word文档");
        return true;
    }

/**
     * 关闭当前文件,并不保存
     * @return
     */
    public boolean close()
    {
        String fileName = null;
        if (this.doc != null)
        {
            try
            {
                fileName = Dispatch.get(this.doc, "Name").getString();
                Dispatch.call(this.doc, "Close", new Variant(false));
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
            finally
            {
                this.doc = null;
            }
        }
        System.out.println("关闭文件 " + fileName);
        return true;
    }

/**
     * 退出
     * @return
     */
    public boolean quit()
    {
        try
        {
            this.app.invoke("Quit", new Variant[] {});
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        System.out.println("退出word");
        return true;
    }

/**
     * 另存为
     * @param fileName 目标文件名,为绝对路径
     * @return
     */
    public boolean saveAs(String fileName) throws Exception
    {
        if (this.doc == null)
        {
            System.out.println("当前无文件");
            return false;
        }
        else
        {
            Dispatch.call(this.doc, "SaveAs", fileName);
            System.out.println("另存为" + fileName);
            return true;
        }
    }

/**
     * 保存
     * @return
     */
    public boolean save() throws Exception
    {
        if (this.doc == null)
        {
            System.out.println("当前无文档,无法保存");
            return false;
        }
        else
        {
            if (this.readOnly)
            {
                System.out.println("只读文档,保存失败");
                return false;
            }
            Dispatch.call(this.doc, "Save");
            System.out.println("保存完成");
            return true;
        }
    }

/**
     * 将光标或选定内容向右移动
     * @param step
     * @return
     */
    public boolean moveRight(int steps) throws Exception
    {
        //int start = Dispatch.get(this.cursor, "Start").getInt();
        //Dispatch.put(this.cursor, "Start", start + steps);
        for (int i=0; i<steps; i++)
        {
            Dispatch.call(cursor, "MoveRight");
        }
        return true;
    }

/**
     * 将光标或选定内容向左移动
     * @param step
     * @return
     */
    public boolean moveLeft(int steps) throws Exception
    {
        for (int i=0; i<steps; i++)
        {
            Dispatch.call(cursor, "MoveLeft");
        }
        return true;
    }

/**
     * 从当前位置起查找指定内容,并将光标移到相应位置上
     * @param str
     * @return 光标位置,未找到则为0
     * @throws java.lang.Exception
     */
    public int search(String str) throws Exception
    {
        // 从cursor所在位置开始查询
        Dispatch find = Dispatch.call(this.cursor, "Find").toDispatch();
        // 设置要查找的内容
        Dispatch.put(find, "Text", str);
        // 向前查找
        Dispatch.put(find, "Forward", "True");
        // 设置格式
        Dispatch.put(find, "Format", "True");
        // 大小写匹配
        Dispatch.put(find, "MatchCase", "True");
        // 全字匹配
        Dispatch.put(find, "MatchWholeWord", "True");
        // 查找
        if (!Dispatch.call(find,"Execute").getBoolean())
            return 0;
        else
        {
            return Dispatch.get(this.cursor, "Start").getInt();
        }
    }

/**
     * 从当前位置起查找指定内容,并只将光标开始处移到相应位置上
     * @param str
     * @return 光标位置,未找到则为0
     * @throws java.lang.Exception
     */
    public int searchOnly(String str) throws Exception
    {
        // 从cursor所在位置开始查询
        Dispatch find = Dispatch.call(this.cursor, "Find").toDispatch();
        // 设置要查找的内容
        Dispatch.put(find, "Text", str);
        // 向前查找
        Dispatch.put(find, "Forward", "True");
        // 大小写匹配
        Dispatch.put(find, "MatchCase", "True");
        // 全字匹配
        Dispatch.put(find, "MatchWholeWord", "True");
        if (!Dispatch.call(find,"Execute").getBoolean())
            return 0;
        else
        {
            int start = Dispatch.get(this.cursor, "Start").getInt();
            Dispatch.put(this.cursor, "End", this.count);
            //System.out.println(start);
            return start;
        }
    }

public String getBetween(int start, int end) throws Exception
    {
        Dispatch range = Dispatch.get(this.cursor, "Range").toDispatch();
        Dispatch.call(range,"SetRange", start, end);
        return Dispatch.get(range, "Text").getString();
    }

public String getLineAfter(int start) throws Exception
    {
        Dispatch.put(this.cursor, "Start", start);
        int length = Dispatch.call(this.cursor, "EndKey").getInt() + start;
        return getBetween(start, length);
    }

public String getLine(int position) throws Exception
    {
        Dispatch.put(this.cursor, "Start", position);
        Dispatch.call(this.cursor, "SelectRow");
        int start = Dispatch.get(this.cursor, "Start").getInt();
        int end = Dispatch.get(this.cursor, "End").getInt();
        return getBetween(start, start + end);
    }

public boolean gotoPage(int index) throws Exception
    {
        Dispatch.invoke(this.cursor, "Goto", Dispatch.Method, new Object[] {1, 2, String.valueOf(index)}, new int[1]);
        //Dispatch.call(this.cursor, "GoTo", "wdGoToLine", "wdGoToNext", String.valueOf(index), null);
        return true;
    }

public int getCurrentCursor() throws Exception
    {
        return Dispatch.get(this.cursor, "Start").getInt();
    }

public boolean setCursorMode() throws Exception
    {
        Dispatch.put(this.cursor, "End", Dispatch.get(this.cursor, "Start").getInt());
        return true;
    }

public boolean gotoHome() throws Exception
    {
        Dispatch.put(this.cursor, "Start", 0);
        return true;
    }

/**
     * 在光标后指定便宜插入字符串,并将光标移到新位置
     * @param str
     * @return
     * @throws java.lang.Exception
     */
    public boolean insert(int steps, String str) throws Exception
    {
        int start = Dispatch.get(this.cursor, "Start").getInt() + steps;
        Dispatch.put(this.cursor, "Start", start);
        Dispatch.call(this.cursor, "InsertBefore", str);
        this.getCount();
        Dispatch.put(this.cursor, "Start", start + str.length());
        //System.out.println(Dispatch.get(this.cursor, "Start").getInt() + "   " + (Dispatch.get(this.cursor, "Start").getInt()+Dispatch.get(this.cursor, "End").getInt()));
        return true;
    }

/**
     * 用指定的字符串替代当前选定的内容
     * @param str
     * @return
     * @throws java.lang.Exception
     */
    public boolean replace(String str) throws Exception
    {
        Dispatch.put(this.cursor, "Text", str);
        return true;
    }

/**
     * 获取当前文档中的表格数
     * @return
     * @throws java.lang.Exception
     */
    public int getTableNum() throws Exception
    {
        return Dispatch.get(this.tables, "Count").getInt();
    }
    
    /**
     * 设定当前工作表格
     * @param index
     * @return
     * @throws java.lang.Exception
     */
    public boolean setCurrentTable(int index) throws Exception
    {
        this.table = Dispatch.call(this.tables, "Item", new Variant(index)).toDispatch();
        Dispatch.call(this.table, "Select");
        return true;
    }
    
    /**
     * 获取指定单元格的内容
     * @param row
     * @param col
     * @return
     * @throws java.lang.Exception
     */
    public String getCell(int row, int col) throws Exception
    {
        Dispatch cell = Dispatch.call(table, "Cell", Integer.toString(row), Integer.toString(col)).toDispatch();
        Dispatch.call(cell,"Select");
        String tmp = Dispatch.get(this.cursor, "Text").getString();
        //System.out.println(".." + tmp);
        if (tmp.length() > 2)
        {
            return tmp.substring(0, tmp.length() - 2);
        }
        else
            return "";
    }

/**
     * 用指定的字符串代替当前表格中指定的单元格
     * @param row
     * @param col
     * @param str
     * @return
     * @throws java.lang.Exception
     */
    public boolean replaceCell(int row, int col, String str) throws Exception
    {
        Dispatch cell = Dispatch.call(table,"Cell", Integer.toString(row), Integer.toString(col)).toDispatch();
        Dispatch.call(cell, "Select");
        Dispatch.put(this.cursor, "Text", str);
        return true;
    }
}

使用Jacob与Word文件交互的更多相关文章

  1. Java文件操作系列[3]——使用jacob操作word文档

    Java对word文档的操作需要通过第三方组件实现,例如jacob.iText.POI和java2word等.jacob组件的功能最强大,可以操作word,Excel等格式的文件.该组件调用的的是操作 ...

  2. 【jacob word】使用jacob,合并多个word为一个word文件

    将几个word文件合并到一个word文件,使用注意点: 1.后面附项目运用的jar包jacob-1.9, 2.并且jacob运用中,需要将附件内的jacob.dll放到windows/system32 ...

  3. 【文件】使用jacob将word转换成pdf格式

    使用jacob将word转换成pdf格式   1.需要安装word2007或以上版本,若安装07版本学确保该版本已安装2downbank0204MicrosoftSaveasPDF_ XPS,否则安装 ...

  4. 利用模板导出文件(二)之jacob利用word模板导出word文件(Java2word)

    https://blog.csdn.net/Fishroad/article/details/47951061?locationNum=2&fps=1 先下载jacob.jar包.解压后将ja ...

  5. 采用jacob实现word转pdf

    网络上已经有很多这方面的内容,在用之前也是参考了好多别人的文章,下面记录下我自己的整合过程.整个过程都比较简单: 开发环境:win8 64位系统,在2008下面部署也是一样的. 文档要求jdk的版本要 ...

  6. jacob操作word

    http://wang-ping001.iteye.com/blog/1452057 ————————————————————————————————————————————————————————— ...

  7. java生成带html样式的word文件

    参考:http://blog.csdn.net/xiexl/article/details/6652230 最近在项目中需要将通过富文本编辑器处理过的文字转换为Word,查了很久,大家通常的解决办法是 ...

  8. jacob 给word加印的功能

    花了两天时间,参考了一些资料,总算是处理好了这样一个技术点. 关键的心得如下: 使用jacob,重点不是jacob本身,而是office的一些API资料.比如需要知道光标的移动, 包括上下左右的mov ...

  9. jacob 操作word

    1. 首先下载jacob-1.18.zip,解压后有两个文件jacob.jar 和 jacob.dll.需要把jacob.jar放到你工程的classpath中并且把jacob.dll放到jdk的bi ...

随机推荐

  1. 推荐一个数据相关的网站tushare

    推荐一个网站:tushare 使用方法如下: pip install tushare 我是使用pycharm直接安装的 抓取了浦发和光大的股票数据,并通过csv进行保存,和通过plt进行图片打印 im ...

  2. 【LOJ】#2010. 「SCOI2015」小凸解密码

    题解 断环为链,把链复制两份 用set维护一下全是0的区间,然后查找x + n / 2附近的区间,附近各一个过不去,最后弃疗了改为查附近的两个,然后过掉了= = 熟练掌握stl的应用,你值得拥有(雾 ...

  3. jquery放大镜非常漂亮噢

    这个放大镜的代码挺简单滴效果也不错. <script> //QQ:496928838 微凉 $(function(){ $("#demo").enlarge( { // ...

  4. Java String、StringBuilder和StringBuffer

    转载: Java String.StringBuilder和StringBuffer 概览 在Android/Java开发中,用来处理字符串常用的类有3种: String.StringBuilder. ...

  5. office2016破解激活安装

    昨天一室友装office2016不会激活,[嘲讽脸]真的是笨啊.我这是在一个社区论坛里面找到的. 在网上找了教程,有些没用的,所以记录安装教程以便之后查看.以下的安装激活亲测有效(2017-4-28) ...

  6. Python并发编程-生产消费模型

    生产消费模型初步 #产生两个子进程,Queue可以在子进程之间传递消息 from multiprocessing import Queue,Process import random import t ...

  7. python中if和elif的区别

    多个if语句是每次单独判断 比如: 例子一: a = 5 if a < 6: #条件1 print(1) if a < 7: #条件2 print(2) else: print(3) 条件 ...

  8. 【面试总结-编程】多行两列数据,实现同key的value求和并输出

    一个文件,两列,多行. 第一列是字母,第二列是数字,同列数据之间通过空格分割. 统计首列字母相同的第二列之和. 样例输入: A 5 B 6 OO 7 A 6 A 2 OO 2 输出: A:13 B:6 ...

  9. Tsinsen 拉拉队排练

    建回文树,然后判断长度奇偶性,统计下来排序即可. 题目链接:http://www.tsinsen.com/ViewGProblem.page?gpid=A1255 By:大奕哥 #include< ...

  10. HTTP状态码,400,404,500,503

    HTTP状态码(HTTP Status Code) 一些常见的状态码为: 200 - 服务器成功返回网页 400 服务器不理解请求的语法 404 - 请求的网页不存在 503 - 服务不可用 所有状态 ...