java-ActiveXComponent调用com组件

1,158 阅读6分钟

简介如何使用jacob进行调用com(component object modal)

下列使用jacob 1.19和1.43版本进行操作,下方会提供对应的jar包以及对应的dll(动态链接库)请对应版本进行操作。

jacob.jar以及相关的dll

1.百度云盘:
链接: pan.baidu.com/s/1YFw8LOb0…
提取码:sksk
2.网络路径: jacob1.43

第一步

需要将对应的dll放置在:jdk -->jre-->bin下否则调用时出现找不到对应的dll出现无法调用的情况 路径示例

第二步简易demo

1.基于第一步,开始我们的demo的书写,这里借鉴了大佬的demo不过写的时候忘记大佬的链接,欢迎知道的人告知,知晓后立即贴上大佬链接。

//jacob  word
    public static void main(String[] args) {
        //使用jacob之前使用下面的语句来初始化com线程,大概意思是打开冰箱门,准备放大象
        ComThread.InitSTA();

        String imgPath = "E:\\jacobtest\\test.png";
        String pages = null;
        //2、创建应用程序对象,设置参数,得到文档集合
        ActiveXComponent wordApp = new ActiveXComponent("Word.Application");//word
        ActiveXComponent excelApp = new ActiveXComponent("Excel.Application");//excel
        wordApp.setProperty("Visible", new Variant(false));//设置应用操作是文档不在明面上显示,只在后台静默处理。

        //这个操作就是模仿vba的写法,Application.Visible = False;vba代码中的对application的设置这里都可以用
        //C#的写法:new Microsoft.Office.Interop.Word.Application().Visible = false; 意思差不多
        //获得文档集合,用来操作我们需要处理的文档,


        //3、打开文档
        //有了文档对象集合,我们就可以来操作文档了,链式操作就此开始:
        //call方法,调用open方法,传递一个参数,返回一个我们的word文档对象,
        Dispatch document = wordApp.getProperty("Documents").toDispatch();
        // dispatchTarget--- 调度目标
        Dispatch doc = Dispatch.call(document, "Open", new Variant("D:\\my.docx")).toDispatch();


        //4、操作文档,每页插入一个图片,并调整大小和位置
        //我录制一个宏插入图片,翻到下一页,再插入一个图片,查看vba代码如下:
        for (int i = 0; i < 2; i++) {
            Dispatch selection = Dispatch.get(wordApp, "Selection").toDispatch();
            Dispatch inLineShapes = Dispatch.get(selection, "InLineShapes").toDispatch();
            Dispatch picture = Dispatch.call(inLineShapes, "AddPicture", imgPath).toDispatch();
            //选中图片
            Dispatch.call(picture, "Select");
            //设置宽度高度

            Dispatch.put(picture, "Width", new Variant(10));
            Dispatch.put(picture, "Height", new Variant(10));

            //设置图片相对左上角偏移位置
            selection = Dispatch.get(wordApp, "Selection").toDispatch();
            Dispatch shapeRange = Dispatch.get(selection, "ShapeRange").toDispatch();
            Dispatch.put(shapeRange, "Left", new Variant(10));
            Dispatch.put(shapeRange, "Top", new Variant(10));

            //翻到下一页
            Dispatch browser = Dispatch.get(wordApp, "Browser").toDispatch();
            Dispatch.call(browser, "Next");
        }

        //从上面的代码可以看出,每一行代码获取一个对象,相应于vba的用“.”点出来的一个对象,大概意思就是得到选中位置,得到图形范围,插入图片,选中图片,设置宽高,设置相对当前页的左边距,上边距,然后将Application.Browser.Next翻译为最后两行代码,翻到下一页,继续插入图片进行处理。
        //这里是固定的页码,如果我们不知道文档的页码呢,请看下一个案例。


        //5、得到word文档的页码:
        //网上找到一段获取文档页数的VBA代码Selection.Information(wdNumberOfPagesInDocument),按照我们的理解,翻译为java代码为:
        Dispatch selection = Dispatch.get(wordApp, "Selection").toDispatch();
////如果调用方法或者属性要得到某个值的话,直接tostring或者别的就可以了
        pages = Dispatch.call(selection, "Information", new Variant(4)).toString();

        Dispatch activeDocument = Dispatch.get(wordApp, "ActiveDocument").toDispatch();
        pages = Dispatch.call(activeDocument, "BuiltInDocumentProperties", new Variant(14)).toString();


//        Dispatch activeDocument  = Dispatch.get(wordApp, "ActiveDocument").toDispatch();
//        Dispatch builtInDocumentProperties  = Dispatch.get(activeDocument, "BuiltInDocumentProperties").toDispatch();
//        pages = Dispatch.call(builtInDocumentProperties, "Item",new Variant(14)).toString();

        //6、保存文档
        Dispatch.call(doc, "Save");

        //7、退出wordapplication
        wordApp.invoke("Quit", new Variant[]{});

        //8.释放com线程
        //使用完成后使用下面的语句来关闭现场,大概意思是关上冰箱门。。。
        ComThread.Release();
    }

以上是一个简单的main函数的实现,作用是在操作my.docx在其中插入图片

2.spring-boot的版本(本人想用jacob使用com组件,其组件==需要管理员权限==)

1.想了一个比较蠢的方法将其写在spring-boot的启动方法中,打成jar包,然后cmd管理员运行。 2.可以使用bat 文件进行启动项目,在其中指定启动参数方法 使用此方法注意修改java home 对应的jre下的dll,否则可能由于有多个jdk,导致启动使用的jdk下并没有dll出现调度失败(你可能存在多个jdk,idea中可以运行,但是打包jar后不能运行)

	1.引用pom.xml
       <dependency>
            <groupId>net.sf.jacob-project</groupId>
            <artifactId>jacob</artifactId>
            <version>1.14.3</version>
        </dependency>
       2.书写启动方法,实现ApplicationRunner 的run方法,在启动spring的时候就会调用该方法
package com.example.demo;

import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.ComThread;
import com.jacob.com.Dispatch;
import com.jacob.com.Variant;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

@Component
public class Wordjacob implements ApplicationRunner {
    @Override
    public void run(ApplicationArguments args) throws Exception {
        //使用jacob之前使用下面的语句来初始化com线程,大概意思是打开冰箱门,准备放大象
        ComThread.InitSTA();

        String imgPath = "E:\\jacobtest\\test.png";
        String pages = null;
        //2、创建应用程序对象,设置参数,得到文档集合
        ActiveXComponent wordApp = new ActiveXComponent("Word.Application");//word
        ActiveXComponent excelApp = new ActiveXComponent("Excel.Application");//excel
        wordApp.setProperty("Visible", new Variant(false));//设置应用操作是文档不在明面上显示,只在后台静默处理。

        //这个操作就是模仿vba的写法,Application.Visible = False;vba代码中的对application的设置这里都可以用
        //C#的写法:new Microsoft.Office.Interop.Word.Application().Visible = false; 意思差不多
        //获得文档集合,用来操作我们需要处理的文档,


        //3、打开文档
        //有了文档对象集合,我们就可以来操作文档了,链式操作就此开始:
        //call方法,调用open方法,传递一个参数,返回一个我们的word文档对象,
        Dispatch document = wordApp.getProperty("Documents").toDispatch();
        // dispatchTarget--- 调度目标
        Dispatch doc = Dispatch.call(document, "Open", new Variant("D:\\my.docx")).toDispatch();


        //4、操作文档,每页插入一个图片,并调整大小和位置
        //我录制一个宏插入图片,翻到下一页,再插入一个图片,查看vba代码如下:
        for (int i = 0; i < 2; i++) {
            Dispatch selection = Dispatch.get(wordApp, "Selection").toDispatch();
            Dispatch inLineShapes = Dispatch.get(selection, "InLineShapes").toDispatch();
            Dispatch picture = Dispatch.call(inLineShapes, "AddPicture", imgPath).toDispatch();
            //选中图片
            Dispatch.call(picture, "Select");
            //设置宽度高度

            Dispatch.put(picture, "Width", new Variant(10));
            Dispatch.put(picture, "Height", new Variant(10));

            //设置图片相对左上角偏移位置
            selection = Dispatch.get(wordApp, "Selection").toDispatch();
            Dispatch shapeRange = Dispatch.get(selection, "ShapeRange").toDispatch();
            Dispatch.put(shapeRange, "Left", new Variant(10));
            Dispatch.put(shapeRange, "Top", new Variant(10));

            //翻到下一页
            Dispatch browser = Dispatch.get(wordApp, "Browser").toDispatch();
            Dispatch.call(browser, "Next");
        }

        //从上面的代码可以看出,每一行代码获取一个对象,相应于vba的用“.”点出来的一个对象,大概意思就是得到选中位置,得到图形范围,插入图片,选中图片,设置宽高,设置相对当前页的左边距,上边距,然后将Application.Browser.Next翻译为最后两行代码,翻到下一页,继续插入图片进行处理。
        //这里是固定的页码,如果我们不知道文档的页码呢,请看下一个案例。


        //5、得到word文档的页码:
        //网上找到一段获取文档页数的VBA代码Selection.Information(wdNumberOfPagesInDocument),按照我们的理解,翻译为java代码为:
        Dispatch selection = Dispatch.get(wordApp, "Selection").toDispatch();
////如果调用方法或者属性要得到某个值的话,直接tostring或者别的就可以了
        pages = Dispatch.call(selection, "Information", new Variant(4)).toString();

        Dispatch activeDocument = Dispatch.get(wordApp, "ActiveDocument").toDispatch();
        pages = Dispatch.call(activeDocument, "BuiltInDocumentProperties", new Variant(14)).toString();


//        Dispatch activeDocument  = Dispatch.get(wordApp, "ActiveDocument").toDispatch();
//        Dispatch builtInDocumentProperties  = Dispatch.get(activeDocument, "BuiltInDocumentProperties").toDispatch();
//        pages = Dispatch.call(builtInDocumentProperties, "Item",new Variant(14)).toString();

        //6、保存文档
        Dispatch.call(doc, "Save");

        //7、退出wordapplication
        wordApp.invoke("Quit", new Variant[]{});

        //8.释放com线程
        //使用完成后使用下面的语句来关闭现场,大概意思是关上冰箱门。。。
        ComThread.Release();
    }
}

3.结果展示

jacobwaord结果展示

本人遇到的问题

1.这个实例化ActiveXcomponent的时候的programId如何获取现在也不知道,百度暂时没找到(补充下方有相关介绍)

  //2、创建应用程序对象,设置参数,得到文档集合
        ActiveXComponent wordApp = new ActiveXComponent("Word.Application");//word

2.部分报错

1.jacob 报错 Can't co-create object
www.cnblogs.com/zy2009/p/68…
stackoverflow.com/questions/2…
2.使用jacob错误 java.lang.IllegalArgumentException: Can't pass in null Dispatch object* www.cnblogs.com/zhangqb/p/1…
3.java.lang.UnsatisfiedLinkError: no jacob-1.14.3-x64 in java.library.path blog.csdn.net/yidragon88x…

3.管理员权限

1.在Java中执行程序的时候是以管理员身份执行的,代码怎么获得管理员权限
bbs.csdn.net/topics/3948…
2.Java之——使用nircmd代替cmd解决管理员权限问题
blog.csdn.net/l1028386804…
3.使用spring-boot 做成jar 使用cmd 管理员运行
4.使用bat 文件,同样使用管理员运行

4.使用==管理员==cmd运行spring-boot的jar

1.使用了新的jdk 更换了java_home 以及path 需要重启电脑才能生效, 下面的代码可以查看一些你启动时的信息,更换了jdk一定要确认是否生效

for (Object value : System.getProperties().keySet()) {
                System.out.println("99999" + value + ":" + System.getProperty(String.valueOf(value)));
            }

2.下面是本人启动时的一些配置信息,查看其中的 ==java.home==,==java.library.path== 以及其余与java相关的信息

99999java.runtime.name:Java(TM) SE Runtime Environment
99999java.protocol.handler.pkgs:org.springframework.boot.loader
99999sun.boot.library.path:D:\chaoran\tool\jacobjdk\jre\bin
99999java.vm.version:25.91-b15
99999java.vm.vendor:Oracle Corporation
99999java.vendor.url:http://java.oracle.com/
99999path.separator:;
99999java.vm.name:Java HotSpot(TM) Client VM
99999file.encoding.pkg:sun.io
99999user.country:CN
99999user.script:
99999sun.java.launcher:SUN_STANDARD
99999sun.os.patch.level:
99999PID:19276
99999java.vm.specification.name:Java Virtual Machine Specification
99999user.dir:E:\idea\spring2\jacob\target
99999java.runtime.version:1.8.0_91-b15
99999java.awt.graphicsenv:sun.awt.Win32GraphicsEnvironment
99999java.endorsed.dirs:D:\chaoran\tool\jacobjdk\jre\lib\endorsed
99999os.arch:x86
99999CONSOLE_LOG_CHARSET:GBK
99999java.io.tmpdir:C:\Users\用户\AppData\Local\Temp\
99999line.separator:

99999java.vm.specification.vendor:Oracle Corporation
99999user.variant:
99999os.name:Windows 10
99999FILE_LOG_CHARSET:GBK
99999sun.jnu.encoding:GBK
99999spring.beaninfo.ignore:true
99999java.library.path:D:\chaoran\tool\jacobjdk\bin;C:\Windows\Sun\Java\bin;C:\Windows\system32;C:\Windows;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Program Files\TortoiseSVN\bin;C:\Program Files (x86)\Microsoft SQL Server\Client SDK\ODBC\130\Tools\Binn\;C:\Program Files (x86)\Microsoft SQL Server\140\Tools\Binn\;C:\Program Files (x86)\Microsoft SQL Server\140\DTS\Binn\;C:\Program Files (x86)\Microsoft SQL Server\140\Tools\Binn\ManagementStudio\;D:\chaoran\tool\jacobjdk\bin;C:\Users\用户\AppData\Local\Microsoft\WindowsApps;D:\webstorm\WebStorm 2020.2.1\bin;C:\Users\用户\AppData\Local\GitHubDesktop\bin;.
99999java.specification.name:Java Platform API Specification
99999java.class.version:52.0
99999sun.management.compiler:HotSpot Client Compiler
99999os.version:10.0
99999user.home:C:\Users\用户
99999catalina.useNaming:false
99999user.timezone:Asia/Shanghai
99999java.awt.printerjob:sun.awt.windows.WPrinterJob
99999file.encoding:GBK
99999java.specification.version:1.8
99999catalina.home:C:\Users\用户\AppData\Local\Temp\tomcat.9999.4313721006538307537
99999java.class.path:demo-0.0.1-SNAPSHOT.jar
99999user.name:用户
99999java.vm.specification.version:1.8
99999sun.java.command:demo-0.0.1-SNAPSHOT.jar
99999java.home:D:\chaoran\tool\jacobjdk\jre
99999sun.arch.data.model:32
99999user.language:zh
99999java.specification.vendor:Oracle Corporation
99999awt.toolkit:sun.awt.windows.WToolkit
99999java.vm.info:mixed mode
99999java.version:1.8.0_91
99999java.ext.dirs:D:\chaoran\tool\jacobjdk\jre\lib\ext;C:\Windows\Sun\Java\lib\ext
99999sun.boot.class.path:D:\chaoran\tool\jacobjdk\jre\lib\resources.jar;D:\chaoran\tool\jacobjdk\jre\lib\rt.jar;D:\chaoran\tool\jacobjdk\jre\lib\sunrsasign.jar;D:\chaoran\tool\jacobjdk\jre\lib\jsse.jar;D:\chaoran\tool\jacobjdk\jre\lib\jce.jar;D:\chaoran\tool\jacobjdk\jre\lib\charsets.jar;D:\chaoran\tool\jacobjdk\jre\lib\jfr.jar;D:\chaoran\tool\jacobjdk\jre\classes
99999java.awt.headless:true
99999java.vendor:Oracle Corporation
99999sun.stderr.encoding:ms936
99999catalina.base:C:\Users\用户\AppData\Local\Temp\tomcat.9999.4313721006538307537
99999file.separator:\
99999java.vendor.url.bug:http://bugreport.sun.com/bugreport/
99999sun.io.unicode.encoding:UnicodeLittle
99999sun.cpu.endian:little
99999sun.stdout.encoding:ms936
99999sun.desktop:windows
99999sun.cpu.isalist:pentium_pro+mmx pentium_pro pentium+mmx pentium i486 i386 i86

附:截图

spring-boot-cmd

附加部分programid

MS控件名programid
InternetExplorerInternetExplorer.Application
ExcelExcel.Application
WordWord.Application
PowerpointPowerpoint.Application
vb/java ScriptScriptControl
windows media PlayerWMPlayer.OCX
OutlookOutlook.Application
VisioVisio.Application
DAODAO.PrivateDBEngine.35
MultiFaceMultiFace.Face

补充查看programid的方法

查看大佬的方式借鉴一下: 在执行程序之前,先执行下这个dll文件,MyOcx.dll,dll下载地址在: pan.baidu.com/s/1nuDn9up,… 打开cmd命令窗口,输入:regsvr32 D:/MyOcx.dll(我的MyOcx.dll文件在D盘根目录下。),执行完成后,会弹出框提示已经注册完dll文件的信息。对于dll文件,你可以通过这个工具打开查看:eXeScope 下载地址:pan.baidu.com/s/1bpsPzWz 打开查看MyOcx.dll文件,其中关注下这个CLSID值,如下图:

查看programid

CLSID的值为:8BE91377-DC16-45EF-8047-AD13354E755E
在windows的注册表中搜这个CLSID,其中打开注册表的方式是:在windows键+R,然后输入”regedit”,弹出注册表窗口,然后,Ctrl+F,输入CLSID的值:8BE91377-DC16-45EF-8047-AD13354E755E,回车,等待片刻后,会定位到你要搜索的内容。如下图:

programidcheck

附链接:www.cnblogs.com/guchunchao/…

结尾

1.此文章本人调用jacob 的笔记,如有错误请各位大佬指导改正
2.对于本人引用的链接和demo代码,如有遇到原始的希望告知,方便及时贴上其原帖
3.如果对上述的问题存在解答方法,欢迎在帖子下评论。