JACob实现java与com组件的相互操作

软件的互操作性是一个我们经常面临的问题,如果
Java 可以自由的调用其他语言和平台的成熟代码,可以充分利用您的 Java 技能,大大提高您的生产力。现有的 Java COM 互操作技术有很多种实现,JACOB 开源项目提供了一个简单方便的通用调用框架,本文就结合一个实例来介绍 JACOB 项目的使用和优点。

我们在实现复杂软件或者进行集成环境的测试时,往往要与各种应用程序打交道。理想情况下,如果能用一种编程语言实现所有功能是很令人憧憬的,但由于遗留代码、语言的能力和厂商的互操作性的策略不同,这往往是一个不现实的目标。比如您可以使用
C#,C++ 或 VB 等语言方便的操作 Outlook 邮箱,但是如果您是一个 Java 程序员,事情就不那么简单了。如果我们可以在 Java 中调用 COM 组件,就可以充分利用您的 Java 技能和现有的成熟 COM 工具包,大大简化应用开发的过程。

COM 组件提供了一种与其他语言的互操作方式,叫做自动化(Automation)。现有的 Java COM 互操作的解决方案有很多种,由于设计目的的不同,在性能、易用性等方面都有很大的区别。本文介绍的 JACOB 开源项目,致力于简化 Java 操作 COM 组件,提供了一个虚拟机独立的自动化服务器实现,由于其通用性设计,您可以非常简单地完成对现有应用的集成。

JACOB 项目的由来

首先,我们将了解 JACOB 项目的基本情况,探讨在什么样的情况下选择它来完成您的任务

有关自动化的更多细节,您可以参考相关文档和书籍,我们仅做简单介绍。调用 COM 中暴露出来的方法,主要有两种机制:早期绑定和晚期绑定。

早期绑定显式的声明对象、数据类型等,编译器获取了足够的信息在编译期进行链接和优化,这样通常可以获得更好的性能,通过这种机制实现 Bridge 调用可以参考 IBM 的 RJCB 项目,它提供了一套高性能的解决方案。当然您需要了解更多 COM 组件的细节,虽然框架为您完成了大部分的生成 Bridge 代码的工作,但是总体来说,编码工作量还是偏大,编码难度也比较高,而且 RJCB 仅支持那些提供早期绑定的 vtable 接口的 COM API。

而晚期绑定方式是通过 IDispatch接口来实现,类似 Java 的反射机制,您可以按照名称或者 ID 进行方法调用,这种设计主要目的是支持脚本语言操作 COM,因为脚本是解释执行的,通常都不支持指针也就没有
C++ 中的 vtable 机制,无法实现早期绑定。这种方式的缺点是在一定程度上性能较差,由于是在运行时按照名字或者 ID 进行对象的调用,只有运行时才确切知道调用的是哪个对象,哪个方法,这样必然带来一定的开销和延迟。但是这种方式的优点也是非常明显的,简单、灵活,您可以不必关注动态链接库的细节,可以非常快地完成代码开发工作。

JACOB 开源项目提供的是一个 JVM 独立的自动化服务器实现,其核心是基于 JNI 技术实现的 Variant, Dispatch 等接口,设计参考了 Microsoft VJ++ 内置的通用自动化服务器,但是 Microsoft 的实现仅仅支持自身的 JVM。通过 JACOB,您可以方便地在 Java 语言中进行晚期绑定方式的调用。

下图是一个对 JACOB 结构的简单说明

实际案列,java操作Word文档,包括word文档的创建、写入文本、插入表格、打印等一系列操作,环境准备,下载jacob类库,我们可以通过下面两种方式获取:

我的资源中:http://download.csdn.net/detail/harderxin/8240309

官方网站:http://danadler.com/jacob/

下载后我们需要两个文件,一个是jacob.jar,另一个是一个dll文件,根据你的操作系统来决定,32位操作系统(jacob-1.17-M2-x86.dll),64位操作系统(jacob-1.17-M2-x64.dll),新建java项目工程,将jacob.jar加入到工程中;

下面一步很重要,就是将jacob-1.14.3-x86.dll设置到系统的环境变量中,我们也可以将其放到当前jdk的bin目录下面:

如果没有设置上面那个dll文件,那么程序运行会抛出下面的异常信息:

下面,我们来编写我们的程序,主要是用到jacob中的几个主要的API:ActiveXComponent、Dispatch、Variant

package com.xin.test;

import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.Dispatch;
import com.jacob.com.Variant;

public class MSWordManager {
	 // word文档
    private Dispatch doc; 

    // word运行程序对象
    private ActiveXComponent word; 

    // 所有word文档集合
    private Dispatch documents; 

    // 选定的范围或插入点
    private Dispatch selection; 

    private boolean saveOnExit = true; 

    /** *//**
     *
     * @param visible 为true表示word应用程序可见
     */
    public MSWordManager(boolean visible) {
            if (word == null) {
                    word = new ActiveXComponent("Word.Application");
                    word.setProperty("Visible", new Variant(visible));
            }
            if (documents == null)
                    documents = word.getProperty("Documents").toDispatch();
    } 

    /** *//**
     * 设置退出时参数
     *
     * @param saveOnExit boolean true-退出时保存文件,false-退出时不保存文件
     */
    public void setSaveOnExit(boolean saveOnExit) {
            this.saveOnExit = saveOnExit;
    } 

    /** *//**
     * 创建一个新的word文档
     *
     */
    public void createNewDocument() {
            doc = Dispatch.call(documents, "Add").toDispatch();
            selection = Dispatch.get(word, "Selection").toDispatch();
    } 

    /** *//**
     * 打开一个已存在的文档
     *
     * @param docPath
     */
    public void openDocument(String docPath) {
            closeDocument();
            doc = Dispatch.call(documents, "Open", docPath).toDispatch();
            selection = Dispatch.get(word, "Selection").toDispatch();
    } 

    /** *//**
     * 把选定的内容或插入点向上移动
     *
     * @param pos 移动的距离
     */
    public void moveUp(int pos) {
            if (selection == null)
                    selection = Dispatch.get(word, "Selection").toDispatch();
            for (int i = 0; i <pos; i++)
                    Dispatch.call(selection, "MoveUp"); 

    } 

    /** *//**
     * 把选定的内容或者插入点向下移动
     *
     * @param pos 移动的距离
     */
    public void moveDown(int pos) {
            if (selection == null)
                    selection = Dispatch.get(word, "Selection").toDispatch();
            for (int i = 0; i<pos; i++)
                    Dispatch.call(selection, "MoveDown");
    } 

    /** *//**
     * 把选定的内容或者插入点向左移动
     *
     * @param pos 移动的距离
     */
    public void moveLeft(int pos) {
            if (selection == null)
                    selection = Dispatch.get(word, "Selection").toDispatch();
            for (int i = 0; i<pos; i++) {
                    Dispatch.call(selection, "MoveLeft");
            }
    } 

    /** *//**
     * 把选定的内容或者插入点向右移动
     *
     * @param pos 移动的距离
     */
    public void moveRight(int pos) {
            if (selection == null)
                    selection = Dispatch.get(word, "Selection").toDispatch();
            for (int i = 0; i<pos; i++)
                    Dispatch.call(selection, "MoveRight");
    } 

    /** *//**
     * 把插入点移动到文件首位置
     *
     */
    public void moveStart() {
            if (selection == null)
                    selection = Dispatch.get(word, "Selection").toDispatch();
            Dispatch.call(selection, "HomeKey", new Variant(6));
    } 

    public void moveEnd() {
            if (selection == null)
                    selection = Dispatch.get(word, "Selection").toDispatch();
            Dispatch.call(selection, "EndKey", new Variant(6));
    } 

    /** *//**
     * 从选定内容或插入点开始查找文本
     *
     * @param toFindText 要查找的文本
     * @return boolean true-查找到并选中该文本,false-未查找到文本
     */
    public boolean find(String toFindText) {
            if (toFindText == null || toFindText.equals(""))
                    return false;
            // 从selection所在位置开始查询
            Dispatch find = word.call(selection, "Find").toDispatch();
            // 设置要查找的内容
            Dispatch.put(find, "Text", toFindText);
            // 向前查找
            Dispatch.put(find, "Forward", "True");
            // 设置格式
            Dispatch.put(find, "Format", "True");
            // 大小写匹配
            Dispatch.put(find, "MatchCase", "True");
            // 全字匹配
            Dispatch.put(find, "MatchWholeWord", "True");
            // 查找并选中
            return Dispatch.call(find, "Execute").getBoolean();
    } 

    /** *//**
     * 把选定选定内容设定为替换文本
     *
     * @param toFindText 查找字符串
     * @param newText 要替换的内容
     * @return
     */
    public boolean replaceText(String toFindText, String newText) {
            if (!find(toFindText))
                    return false;
            Dispatch.put(selection, "Text", newText);
            return true;
    } 

    /** *//**
     * 全局替换文本
     *
     * @param toFindText 查找字符串
     * @param newText 要替换的内容
     */
    public void replaceAllText(String toFindText, String newText) {
            while (find(toFindText)) {
                    Dispatch.put(selection, "Text", newText);
                    Dispatch.call(selection, "MoveRight");
            }
    } 

    /** *//**
     * 在当前插入点插入字符串
     *
     * @param newText 要插入的新字符串
     */
    public void insertText(String newText) {
            Dispatch.put(selection, "Text", newText);
    } 

    /** *//**
     *
     * @param toFindText 要查找的字符串
     * @param imagePath 图片路径
     * @return
     */
    public boolean replaceImage(String toFindText, String imagePath) {
            if (!find(toFindText))
                    return false;
            Dispatch.call(Dispatch.get(selection, "InLineShapes").toDispatch(),
                            "AddPicture", imagePath);
            return true;
    } 

    /** *//**
     * 全局替换图片
     *
     * @param toFindText 查找字符串
     * @param imagePath 图片路径
     */
    public void replaceAllImage(String toFindText, String imagePath) {
            while (find(toFindText)) {
                    Dispatch.call(Dispatch.get(selection, "InLineShapes").toDispatch(),
                                    "AddPicture", imagePath);
                    Dispatch.call(selection, "MoveRight");
            }
    } 

    /** *//**
     * 在当前插入点插入图片
     *
     * @param imagePath 图片路径
     */
    public void insertImage(String imagePath) {
            Dispatch.call(Dispatch.get(selection, "InLineShapes").toDispatch(),
                            "AddPicture", imagePath);
    } 

    /** *//**
     * 合并单元格
     *
     * @param tableIndex
     * @param fstCellRowIdx
     * @param fstCellColIdx
     * @param secCellRowIdx
     * @param secCellColIdx
     */
    public void mergeCell(int tableIndex, int fstCellRowIdx, int fstCellColIdx,
                    int secCellRowIdx, int secCellColIdx) {
            // 所有表格
            Dispatch tables = Dispatch.get(doc, "Tables").toDispatch();
            // 要填充的表格
            Dispatch table = Dispatch.call(tables, "Item", new Variant(tableIndex))
                            .toDispatch();
            Dispatch fstCell = Dispatch.call(table, "Cell",
                            new Variant(fstCellRowIdx), new Variant(fstCellColIdx))
                            .toDispatch();
            Dispatch secCell = Dispatch.call(table, "Cell",
                            new Variant(secCellRowIdx), new Variant(secCellColIdx))
                            .toDispatch();
            Dispatch.call(fstCell, "Merge", secCell);
    } 

    /** *//**
     * 在指定的单元格里填写数据
     *
     * @param tableIndex
     * @param cellRowIdx
     * @param cellColIdx
     * @param txt
     */
    public void putTxtToCell(int tableIndex, int cellRowIdx, int cellColIdx,
                    String txt) {
            // 所有表格
            Dispatch tables = Dispatch.get(doc, "Tables").toDispatch();
            // 要填充的表格
            Dispatch table = Dispatch.call(tables, "Item", new Variant(tableIndex))
                            .toDispatch();
            Dispatch cell = Dispatch.call(table, "Cell", new Variant(cellRowIdx),
                            new Variant(cellColIdx)).toDispatch();
            Dispatch.call(cell, "Select");
            Dispatch.put(selection, "Text", txt);
    } 

    /** *//**
     * 在当前文档拷贝数据
     *
     * @param pos
     */
    public void copy(String toCopyText) {
            moveStart();
            if (this.find(toCopyText)) {
                    Dispatch textRange = Dispatch.get(selection, "Range").toDispatch();
                    Dispatch.call(textRange, "Copy");
            }
    } 

    /** *//**
     * 在当前文档粘帖剪贴板数据
     *
     * @param pos
     */
    public void paste(String pos) {
            moveStart();
            if (this.find(pos)) {
                    Dispatch textRange = Dispatch.get(selection, "Range").toDispatch();
                    Dispatch.call(textRange, "Paste");
            }
    } 

    /** *//**
     * 在当前文档指定的位置拷贝表格
     *
     * @param pos 当前文档指定的位置
     * @param tableIndex 被拷贝的表格在word文档中所处的位置
     */
    public void copyTable(String pos,int tableIndex) {
            Dispatch tables = Dispatch.get(doc, "Tables").toDispatch();
            Dispatch table = Dispatch.call(tables, "Item", new Variant(tableIndex))
                            .toDispatch();
            Dispatch range = Dispatch.get(table, "Range").toDispatch();
            Dispatch.call(range, "Copy");
            if (this.find(pos)) {
                    Dispatch textRange = Dispatch.get(selection, "Range").toDispatch();
                    Dispatch.call(textRange, "Paste");
            }
    } 

    /** *//**
     * 在当前文档末尾拷贝来自另一个文档中的段落
     *
     * @param anotherDocPath 另一个文档的磁盘路径
     * @param tableIndex 被拷贝的段落在另一格文档中的序号(从1开始)
     */
    public void copyParagraphFromAnotherDoc(String anotherDocPath,
                    int paragraphIndex) {
            Dispatch wordContent = Dispatch.get(doc, "Content").toDispatch(); // 取得当前文档的内容
            Dispatch.call(wordContent, "InsertAfter", "$selection$");// 插入特殊符定位插入点
            copyParagraphFromAnotherDoc(anotherDocPath, paragraphIndex,
                            "$selection$");
    } 

    /** *//**
     * 在当前文档指定的位置拷贝来自另一个文档中的段落
     *
     * @param anotherDocPath 另一个文档的磁盘路径
     * @param tableIndex 被拷贝的段落在另一格文档中的序号(从1开始)
     * @param pos 当前文档指定的位置
     */
    public void copyParagraphFromAnotherDoc(String anotherDocPath,
                    int paragraphIndex, String pos) {
            Dispatch doc2 = null;
            try {
                    doc2 = Dispatch.call(documents, "Open", anotherDocPath)
                                    .toDispatch();
                    Dispatch paragraphs = Dispatch.get(doc2, "Paragraphs").toDispatch(); 

                    Dispatch paragraph = Dispatch.call(paragraphs, "Item",
                                    new Variant(paragraphIndex)).toDispatch();
                    Dispatch range = Dispatch.get(paragraph, "Range").toDispatch();
                    Dispatch.call(range, "Copy");
                    if (this.find(pos)) {
                            Dispatch textRange = Dispatch.get(selection, "Range")
                                            .toDispatch();
                            Dispatch.call(textRange, "Paste");
                    }
            } catch (Exception e) {
                    e.printStackTrace();
            } finally {
                    if (doc2 != null) {
                            Dispatch.call(doc2, "Close", new Variant(saveOnExit));
                            doc2 = null;
                    }
            }
    } 

    /** *//**
     * 在当前文档指定的位置拷贝来自另一个文档中的表格
     *
     * @param anotherDocPath 另一个文档的磁盘路径
     * @param tableIndex 被拷贝的表格在另一格文档中的序号(从1开始)
     * @param pos 当前文档指定的位置
     */
    public void copyTableFromAnotherDoc(String anotherDocPath, int tableIndex,
                    String pos) {
            Dispatch doc2 = null;
            try {
                    doc2 = Dispatch.call(documents, "Open", anotherDocPath)
                                    .toDispatch();
                    Dispatch tables = Dispatch.get(doc2, "Tables").toDispatch();
                    Dispatch table = Dispatch.call(tables, "Item",
                                    new Variant(tableIndex)).toDispatch();
                    Dispatch range = Dispatch.get(table, "Range").toDispatch();
                    Dispatch.call(range, "Copy");
                    if (this.find(pos)) {
                            Dispatch textRange = Dispatch.get(selection, "Range")
                                            .toDispatch();
                            Dispatch.call(textRange, "Paste");
                    }
            } catch (Exception e) {
                    e.printStackTrace();
            } finally {
                    if (doc2 != null) {
                            Dispatch.call(doc2, "Close", new Variant(saveOnExit));
                            doc2 = null;
                    }
            }
    } 

    /** *//**
     * 在当前文档指定的位置拷贝来自另一个文档中的图片
     *
     * @param anotherDocPath 另一个文档的磁盘路径
     * @param shapeIndex 被拷贝的图片在另一格文档中的位置
     * @param pos 当前文档指定的位置
     */
    public void copyImageFromAnotherDoc(String anotherDocPath, int shapeIndex,
                    String pos) {
            Dispatch doc2 = null;
            try {
                    doc2 = Dispatch.call(documents, "Open", anotherDocPath)
                                    .toDispatch();
                    Dispatch shapes = Dispatch.get(doc2, "InLineShapes").toDispatch();
                    Dispatch shape = Dispatch.call(shapes, "Item",
                                    new Variant(shapeIndex)).toDispatch();
                    Dispatch imageRange = Dispatch.get(shape, "Range").toDispatch();
                    Dispatch.call(imageRange, "Copy");
                    if (this.find(pos)) {
                            Dispatch textRange = Dispatch.get(selection, "Range")
                                            .toDispatch();
                            Dispatch.call(textRange, "Paste");
                    }
            } catch (Exception e) {
                    e.printStackTrace();
            } finally {
                    if (doc2 != null) {
                            Dispatch.call(doc2, "Close", new Variant(saveOnExit));
                            doc2 = null;
                    }
            }
    } 

    /** *//**
     * 创建表格
     *
     * @param pos    位置
     * @param cols 列数
     * @param rows 行数
     */
    public void createTable(int numCols, int numRows){//(String pos, int numCols, int numRows) {
//            if (!find(pos)) {
                    Dispatch tables = Dispatch.get(doc, "Tables").toDispatch();
                    Dispatch range = Dispatch.get(selection, "Range").toDispatch();
                    Dispatch newTable = Dispatch.call(tables, "Add", range,
                                    new Variant(numRows), new Variant(numCols)).toDispatch();
                    Dispatch.call(selection, "MoveRight");
                    moveEnd();
//            }
    } 

    /** *//**
     * 在指定行前面增加行
     *
     * @param tableIndex word文件中的第N张表(从1开始)
     * @param rowIndex 指定行的序号(从1开始)
     */
    public void addTableRow(int tableIndex, int rowIndex) {
            // 所有表格
            Dispatch tables = Dispatch.get(doc, "Tables").toDispatch();
            // 要填充的表格
            Dispatch table = Dispatch.call(tables, "Item", new Variant(tableIndex))
                            .toDispatch();
            // 表格的所有行
            Dispatch rows = Dispatch.get(table, "Rows").toDispatch();
            Dispatch row = Dispatch.call(rows, "Item", new Variant(rowIndex))
                            .toDispatch();
            Dispatch.call(rows, "Add", new Variant(row));
    } 

    /** *//**
     * 在第1行前增加一行
     *
     * @param tableIndex word文档中的第N张表(从1开始)
     */
    public void addFirstTableRow(int tableIndex) {
            // 所有表格
            Dispatch tables = Dispatch.get(doc, "Tables").toDispatch();
            // 要填充的表格
            Dispatch table = Dispatch.call(tables, "Item", new Variant(tableIndex))
                            .toDispatch();
            // 表格的所有行
            Dispatch rows = Dispatch.get(table, "Rows").toDispatch();
            Dispatch row = Dispatch.get(rows, "First").toDispatch();
            Dispatch.call(rows, "Add", new Variant(row));
    } 

    /** *//**
     * 在最后1行前增加一行
     *
     * @param tableIndex
     *                        word文档中的第N张表(从1开始)
     */
    public void addLastTableRow(int tableIndex) {
            // 所有表格
            Dispatch tables = Dispatch.get(doc, "Tables").toDispatch();
            // 要填充的表格
            Dispatch table = Dispatch.call(tables, "Item", new Variant(tableIndex))
                            .toDispatch();
            // 表格的所有行
            Dispatch rows = Dispatch.get(table, "Rows").toDispatch();
            Dispatch row = Dispatch.get(rows, "Last").toDispatch();
            Dispatch.call(rows, "Add", new Variant(row));
    } 

    /** *//**
     * 增加一行
     *
     * @param tableIndex word文档中的第N张表(从1开始)
     */
    public void addRow(int tableIndex) {
            Dispatch tables = Dispatch.get(doc, "Tables").toDispatch();
            // 要填充的表格
            Dispatch table = Dispatch.call(tables, "Item", new Variant(tableIndex))
                            .toDispatch();
            // 表格的所有行
            Dispatch rows = Dispatch.get(table, "Rows").toDispatch();
            Dispatch.call(rows, "Add");
    } 

    /** *//**
     * 增加一列
     *
     * @param tableIndex word文档中的第N张表(从1开始)
     */
    public void addCol(int tableIndex) {
            // 所有表格
            Dispatch tables = Dispatch.get(doc, "Tables").toDispatch();
            // 要填充的表格
            Dispatch table = Dispatch.call(tables, "Item", new Variant(tableIndex))
                            .toDispatch();
            // 表格的所有行
            Dispatch cols = Dispatch.get(table, "Columns").toDispatch();
            Dispatch.call(cols, "Add").toDispatch();
            Dispatch.call(cols, "AutoFit");
    } 

    /** *//**
     * 在指定列前面增加表格的列
     *
     * @param tableIndex word文档中的第N张表(从1开始)
     * @param colIndex    指定列的序号 (从1开始)
     */
    public void addTableCol(int tableIndex, int colIndex) {
            // 所有表格
            Dispatch tables = Dispatch.get(doc, "Tables").toDispatch();
            // 要填充的表格
            Dispatch table = Dispatch.call(tables, "Item", new Variant(tableIndex))
                            .toDispatch();
            // 表格的所有行
            Dispatch cols = Dispatch.get(table, "Columns").toDispatch();
            System.out.println(Dispatch.get(cols, "Count"));
            Dispatch col = Dispatch.call(cols, "Item", new Variant(colIndex))
                            .toDispatch();
            // Dispatch col = Dispatch.get(cols, "First").toDispatch();
            Dispatch.call(cols, "Add", col).toDispatch();
            Dispatch.call(cols, "AutoFit");
    } 

    /** *//**
     * 在第1列前增加一列
     *
     * @param tableIndex word文档中的第N张表(从1开始)
     */
    public void addFirstTableCol(int tableIndex) {
            Dispatch tables = Dispatch.get(doc, "Tables").toDispatch();
            // 要填充的表格
            Dispatch table = Dispatch.call(tables, "Item", new Variant(tableIndex))
                            .toDispatch();
            // 表格的所有行
            Dispatch cols = Dispatch.get(table, "Columns").toDispatch();
            Dispatch col = Dispatch.get(cols, "First").toDispatch();
            Dispatch.call(cols, "Add", col).toDispatch();
            Dispatch.call(cols, "AutoFit");
    } 

    /** *//**
     * 在最后一列前增加一列
     *
     * @param tableIndex word文档中的第N张表(从1开始)
     */
    public void addLastTableCol(int tableIndex) {
            Dispatch tables = Dispatch.get(doc, "Tables").toDispatch();
            // 要填充的表格
            Dispatch table = Dispatch.call(tables, "Item", new Variant(tableIndex))
                            .toDispatch();
            // 表格的所有行
            Dispatch cols = Dispatch.get(table, "Columns").toDispatch();
            Dispatch col = Dispatch.get(cols, "Last").toDispatch();
            Dispatch.call(cols, "Add", col).toDispatch();
            Dispatch.call(cols, "AutoFit");
    } 

    /** *//**
     * 自动调整表格
     *
     */
    public void autoFitTable() {
            Dispatch tables = Dispatch.get(doc, "Tables").toDispatch();
            int count = Dispatch.get(tables, "Count").toInt();
            for (int i = 0; i<count; i++) {
                    Dispatch table = Dispatch.call(tables, "Item", new Variant(i + 1))
                                    .toDispatch();
                    Dispatch cols = Dispatch.get(table, "Columns").toDispatch();
                    Dispatch.call(cols, "AutoFit");
            }
    } 

    /** *//**
     * 调用word里的宏以调整表格的宽度,其中宏保存在document下
     *
     */
    public void callWordMacro() {
            Dispatch tables = Dispatch.get(doc, "Tables").toDispatch();
            int count = Dispatch.get(tables, "Count").toInt();
            Variant vMacroName = new Variant("Normal.NewMacros.tableFit");
            Variant vParam = new Variant("param1");
            Variant para[] = new Variant[] { vMacroName };
            for (int i = 0; i<para.length; i++) {
                    Dispatch table = Dispatch.call(tables, "Item", new Variant(i + 1))
                                    .toDispatch();
                    Dispatch.call(table, "Select");
                    Dispatch.call(word, "Run", "tableFitContent");
            }
    } 

    /** *//**
     * 设置当前选定内容的字体
     *
     * @param boldSize
     * @param italicSize
     * @param underLineSize 下划线
     * @param colorSize 字体颜色
     * @param size 字体大小
     * @param name 字体名称
     */
    public void setFont(boolean bold, boolean italic, boolean underLine,
                    String colorSize, String size, String name) {
            Dispatch font = Dispatch.get(selection, "Font").toDispatch();
            Dispatch.put(font, "Name", new Variant(name));
            Dispatch.put(font, "Bold", new Variant(bold));
            Dispatch.put(font, "Italic", new Variant(italic));
            Dispatch.put(font, "Underline", new Variant(underLine));
            Dispatch.put(font, "Color", colorSize);
            Dispatch.put(font, "Size", size);
    } 

    /** *//**
     * 文件保存或另存为
     *
     * @param savePath 保存或另存为路径
     */
    public void save(String savePath) {
            Dispatch.call(
                            (Dispatch) Dispatch.call(word, "WordBasic").getDispatch(),
                            "FileSaveAs", savePath);
    } 

    /** *//**
     * 关闭当前word文档
     *
     */
    public void closeDocument() {
            if (doc != null) {
                    Dispatch.call(doc, "Save");
                    Dispatch.call(doc, "Close", new Variant(saveOnExit));
                    doc = null;
            }
    } 

    /** *//**
     * 关闭全部应用
     *
     */
    public void close() {
            closeDocument();
            if (word != null) {
                    Dispatch.call(word, "Quit");
                    word = null;
            }
            selection = null;
            documents = null;
    } 

    /** *//**
     * 打印当前word文档
     *
     */
    public void printFile() {
            if (doc != null) {
                    Dispatch.call(doc, "PrintOut");
            }
    }
}

创建测试程序:

/**
 * 使用jacob对office操作
 * @author dell
 *
 */
public class Client {
	public static void main(String[] args) {
		MSWordManager manager = new MSWordManager(true);
		// 生成一个MSwordManager对象,并且设置显示Word程序
		manager.createNewDocument();
		// 创建一个新的.doc文件
		manager.insertText("Test jacob");
		// 插入文本
		manager.save("d:\\1.doc");
		// 保存.doc文件
		manager.close();
		manager.closeDocument();
		//manager.moveEnd();//将光标移至末尾
	}
}

运行结果,我们则通过java在d盘符下面创建了一个1.doc,其中的内容为Test jacob

使用jacob操作excel:

public class Client2 {
	  public static void main(String[] args)
	  {
	    ActiveXComponent xl = new ActiveXComponent("Excel.Application");
	    Dispatch xlo = xl.getObject();
	    try {
	      System.out.println("version="+xl.getProperty("Version"));
	      System.out.println("version="+Dispatch.get(xlo, "Version"));
	      xl.setProperty("Visible", new Variant(true));
	      Dispatch workbooks = xl.getProperty("Workbooks").toDispatch();
	      Dispatch workbook = Dispatch.get(workbooks,"Add").toDispatch();
	      Dispatch sheet = Dispatch.get(workbook,"ActiveSheet").toDispatch();
	      Dispatch a1 = Dispatch.invoke(sheet, "Range", Dispatch.Get,
	                                  new Object[] {"A1"},
	                                  new int[1]).toDispatch();
	      Dispatch a2 = Dispatch.invoke(sheet, "Range", Dispatch.Get,
	                                  new Object[] {"A2"},
	                                  new int[1]).toDispatch();
	      Dispatch.put(a1, "Value", "123.456");
	      Dispatch.put(a2, "Formula", "=A1*2");
	      System.out.println("a1 from excel:"+Dispatch.get(a1, "Value"));
	      System.out.println("a2 from excel:"+Dispatch.get(a2, "Value"));
	      Variant f = new Variant(false);
	      Dispatch.call(workbook, "Close", f);
	    } catch (Exception e) {
	      e.printStackTrace();
	    } finally {
	      xl.invoke("Quit", new Variant[] {});
	    }
	  }
}

运行结果是创建了excel文件,得到其相应的属性。

--用到主要的方法

ActiveXComponent中创建不同的控件调用不同的值

* 假设创建的对象名称为ax,常用对照如下:

* Word——Word.Application

* Excel——Excel.Application

* Powerpoint——Powerpoint.Application

* Outlook——Outlook.Application

经查找发现,其实"Word.Application.12"就是com在注册表中的progID; ProgID是程序员给某个CLSID指定一个易记的名字,其 组成:<program>.<component>.<version> 在注册表HKey_Classes_Root下,有版本号的ProgID和无版本号的ProgID都有列出,一般无版本号的除了有CLSID子键外会还有CurVer子键来标明版本

ax.getObject()--获得对应控件的Dispatch对象

documents=ax.getProperty("Documents")--获得对应控件的Dispatch对象

get(a,"b")--获得a对象数据结构中的b属性

call(a,"b","c")--该方法和get方法非常类似,是把b属性赋值给c

put(a,"b","c")--将ax对象a的属性b设置为c

时间: 2024-10-04 07:42:55

JACob实现java与com组件的相互操作的相关文章

java调用com组件操作word使用总结(jacob)

ava调用com组件操作word使用总结(jacob) 简单描述 在此处输入简单摘要 特别声明:使用java-com技术可以完成任何VBA可以完成的office文档操作; 一.准备工作 先了解一下概念,JACOB 就是 JAVA-COM Bridge的缩写,提供自动化的访问com的功能,也是通过JNI功能访问windows平台下的com组件或者win32系统库的.这是一个开始于 1999年的开源项目的成果,有很多使用者对该项目进行了修改,做出了自己的贡献. Jacob下载地址: http://s

java中解决组件重叠的问题(例如鼠标移动组件时)

java中解决组件覆盖的问题!     有时候在移动组件的时候会出现两个组件覆盖的情况,但是你想让被覆盖的组件显示出来或者不被覆盖! 在设计GUI时已经可以定义组件的叠放次序了(按摆放组件的先后顺序). 真正麻烦的是响应哪个组件,这就要创建一个链表,把组件对象按顺序存起来,响应事件时扫描这个链表,按 链表中的先后顺序选择响应组件对象.     所以要想满足自己的需求,那么在添加组件的时候就要注意顺序就好了! 另外如果不想用上面的方法,那么你就采用JLayeredPane这个类,分层面板可以帮助你

谈谈Java的集合组件

让我们一起谈谈Java的集合组件 我们在使用Java的时候,都会遇到并使用到Java的集合.在这里通过自己的理解和网上的资源对Java的集合方面的使用做一个简单的讲解和总结. Java主要分为3个集合组件:Set(集).List(列表).Map(映射). Collection接口:Collection是最基本的集合接口,声明了适用于Java集合的通用方法.Set和List都继承了Collection,Map. Collection接口的方法: boolean add(Object o):向集合中

java JNI 的实现(2)-java和C/C++的相互调用.

目录 概述 一,java代码 二,稍微注意通过javah生成的'C/C++'.h头文件和源java代码的关系 三,在C/C++中实现java的native方法(完整C/C++) 1,修改age,即Java_juk_demo_JSay_changeAge方法 2,调用java中的'javaStatic'方法,和上面C/C+实现方法相似 3,最后测试 概述 从第一篇java JNI 的实现(1)-又进一步加深对JVM实现的理解对JNI有了大致的理解之后,并知道JNI中java如何调用C/C++等,这

Bean(描述Java的软件组件模型)

EJB是Enterprise Java Bean的缩写,一个Bean扮演着应用程序素材的角色.它包含有一个functional interface,一个life-cycle interface,以及一个实现它所支援的商业方法的类别. 外文名 Enterprise Java Bean 缩    写Bean   定义描述Java的软件组件模型 类    型    应用程序素材的角色 目    的  将可以重复使用的软件代码打包 应用范围  应用于服务器的部件 1定义 JavaBean是描述Java的

【UML】Java代码与UML模型相互转换方法

最近重温了几个设计模式,看到大家的博客里面都是Java代码+UML视图,UML表达整体框架,然后再秀出具体的代码,点面结合.一目了然.所以也研究了一下Java代码与UML模型相互转换方法. 一.常用的UML建模工具 三大建模工具可以参考:UML建模工具Visio .Rational Rose.PowerDesign的比较 三者都能非常好的支持UML的建模,由于和Eclipse或者IDEA等代码IDE集成不太方便或者不可行,所以没有深入研究 二.Java.UML建模与反向工具推荐 十二个开源UML

word 文档导出 (freemaker+jacob)--java开发

工作中终于遇到了 需要导出word文旦的需求了.由于以前没有操作过,所以就先百度下了,基本上是:博客园,简书,CDSN,这几大机构的相关帖子比较多,然后花了2周时间 才初步弄懂.  学习顺序: 第一阶段 1,.首先 是 先了解 java 通过什么方式 来操作word的导出工作.就有了下面这个帖子了: java 操作 word 的方法 :https://www.cnblogs.com/lcngu/p/5247179.html .新手可以先看看了解下. 2. 根据需求:操作word很复杂: 1.有图

Android NDK开发篇(五):Java与原生代码通信(数据操作)

尽管说使用NDK能够提高Android程序的运行效率,可是调用起来还是略微有点麻烦.NDK能够直接使用Java的原生数据类型,而引用类型,由于Java的引用类型的实如今NDK被屏蔽了,所以在NDK使用Java的引用类型则要做对应的处理. 一.对引用数据类型的操作 尽管Java的引用类型的实如今NDK被屏蔽了,JNI还是提供了一组API,通过JNIEnv接口指针提供原生方法改动和使用Java的引用类型. 1.字符串操作 JNI把Java的字符串当作引用来处理,在NDK中使用Java的字符串,须要相

java模拟而一个电话本操作

哈哈,大家平时都在使用电话本,下面使用java来模拟而一个简单的电话本吧... 首先给出联系人的抽象类 package net.itaem.po; /** * * 电话人的信息 * */ public class User { private String name; private String phoneNumber; private String companyName; private String email; private String address; private Strin