零、导读

这是使用jacob操作Word和Excel的教程,因为看不懂官方文档(英语不好,翻译太菜)所以选择去找找教程。

jacob可以操作的

1、jacob 操作 cad相关资料

对象方法和操作,里面的例子都是

http://entercad.ru/acadauto.en/

2、jacob操作word和Excel相关资料和文档(也有PPT access等资料)

这个微软官方有中文版翻译在左下角,点一下中文的即可。

https://docs.microsoft.com/zh-cn/office/vba/api/overview/word

文档中的对象和方法都是VBA的,其实本来也是用dll文件操作VBA的方式。

如果有条件在开发过程中最好使用MSoffice作为调试的首选程序,因为WPS有的时候是无法返回报错信息的,亲测

一、使用JACOB通用步骤

1、下载jacob

[jacob地址][https://sourceforge.net/projects/jacob-project/]

2、目录结构

我们下载下来的压缩包的目录结构大约是这样的

3、将dll文件放入System32

我们需要将两个dll文件放入C:\Windows\System32 中。

4、将jar文件导入我们的项目

这个我就不多赘述了,不懂得朋友只能够去百度了。

二、Jacob操作word

1、写在前面

在写代码之前需要大家理解一些层次观念,所以在代码中会讲解,请大家结合自己的使用word的过程 每一步每一步,以方便理解代码。

2、打开文档

public class WordService {private static ActiveXComponent application; //代码整个word程序private static Dispatch documents;//代表这个程序打开的所有文档private static Dispatch doc;//代表程序打开某一个文档private Dispatch tables; //自动释放 所以每次重新打开的时候需要重新赋值,即使你没有手动释放不然会报空指针private Dispatch table; //自动释放 同上private Dispatch selection; //选择器 public void openWord(String filepath){ComThread.InitSTA();//ComThread也就是我们包中的对象 jacob包中  进行初始化//创建应用application = new ActiveXComponent("Word.Application");//开启word 它会指定我们的默认程序MSoffice或者WPS程序application.setProperty("Visible",new Variant(true));//设置程序可见// Variant类,是jacob操作用于封装变量的类,常用的封装的类型如下://java基本数据类型 int float double String char boolean 等。。。//可以封装Dispath类,这个类是我们获取到的文档中的某个可以处理对象Dispatch documents = application.getProperty("Documents").toDispatch();//使用Word程序获取到所有的文档对象使用getProperty,// 如果想要获取其他的属性或者调用方法,可以查看上面提到的文档的地址//以下是文档对象的操作//文档的打开操作  这里涉及到两个方法一个类// 第一个是call方法,代表调用文档中某个对象的方法// 第二个是toDispatch方法 将call中调用的"Open"方法的返回值转化成一个可处理的对象 任何call方法返回的默认都是Variant对象,//  可以转化成其他形式的封装好的一些常用的对象包括toDispath(Dispath 可处理对象) toString(String 字符串 一般获取表格内容、正文等) toSafeArray(向量 这个到现在为止很少用到)//一个类是Dispatch类,是我们用于操作对象的类 主要调用其中的三个静态方法 call(调用文档中各个对象的方法)、 get(获取文档中对象的各个属性)、put(给文档中的各个对象赋值)// 还需要说的另外一个是 ,call方法的几个参数// Dispatch.call() 第一个参数,代表你要调用哪个对象的方法,这里是文档集合documents对象的方法 具体有哪些对象和属性方法 请看官方文档的对象介绍//第二个参数是你调用的这个对象的 哪个方法 同上想知道有哪些方法看文档,//如果没有参数的情况下前两个参数是必填的,后面不管多少个参数都是我们调用的方法中需要的参数,//比如 open方法的 第一个参数是 文件路径 第二个参数是 是否把word程序显示到前台,意思就是是否可见doc = Dispatch.call(documents, "Open", new Variant(filepath),new Variant(false)).toDispatch();//当前doc代表的是已经打开的文档,get方法如上面所说是获取到对象的属性的,// 这里代表获取当前文档的所有表格集合  注意不是一个表格 而是所有表格的集合tables = Dispatch.get(doc, "Tables").toDispatch();//获取当前应用的选择器//选择器怎么说呢就是我们在操作文档的时候 能执行选择文字的操作的东西,我们一定需要获取它selection = Dispatch.get(application, "Selection").toDispatch();}
}

在代码中向大家大概解释了Variant、Dispathch等 这里我再总结一下

Variant 用于传参的时候或者接受返回值的时候的封装 翻译过来就是变量 一般方法中的变量都需要用它封装

Dispatch 用于操作文档中对象的类

toDispatch 将接收到的 Variant转化成可以处理的对象

3、层级结构

在word中我们如果想要获取某些东西需要按照一定的层级结构才能够获取的到,接下来向大家展示一般的对象层级,当然你可以在官方的文档中查看到这些对象在上一级的属性或者方法中

大多数的对象都是通过上一层获取的,只有少量的可以通过下层获取上层 例如 Cell(单元格)的 Rows(行)属性和Columns(列)属性

说一个特殊的对象Range 区域,它代表文档中的某个对象或者某一些对象的 的区域,很多对象都有Range属性

  • 第一层 Application 应用
  • 第二层 Documents 文档集合 通过application的getProperty方法获取 上方代码中有
  • 第三层 Document 文档 通过Documents 的各个方法返回的Docuement对象 例如 open方法, item方法(需要参数 参数为索引(index)) , 或者Application对象的 ActiveDocument属性
  • 第四层 文档中的 其他对象 例如Tables 下面一层也以tables的下一层为例 可以在文档中的Document对象中查看 [Document对象][https://docs.microsoft.com/zh-cn/office/vba/api/word.document] 通过上一层的Tables 属性获取
  • 第五层 table 对象 通过上一层个item方法获取 例如 Dispath.call(tables,“Item”,new Variant(1)).toDispath(); 代表获取表格集合tables中的 第1个(下标不是0开始而是1开始)的table对象并转化成可处理对象
  • 第六层 table的 Rows对象和 Columns Cells 对象 等 代表行、列和单元格、的集合 通过 talbe 的Rows 、 Columns 和Cells 属性获取 这里的Cells代表的是表格所有单元格
  • 第七层 Row 对象 和 Column对象 某一行和某一列 的对象 通过 Rows对象 和 Columns对象的item方法获取
  • 第八层 Cell对象 通过 item方法获取 获取到某个单元格对象

上面的这些talbes rows columns对象等都可以在官方文档中查看到。

简单的介绍了层级之后 大家一定有感觉了,但是还是有点懵,如果大家有点蒙我们再来看下一段代码,大家就很快能够上手了。

4、一些常用的方法 和操作

如果大家有点基础可以直接去另外一个博主的博客上看,他这个适合一定基础的同学学习[地址][https://www.cnblogs.com/qinwangchen/p/5894236.html],

    /*** @Description: 获取某一table* @Param: [index]  table的索引 从1开始 表示第一个表格* @return: com.jacob.com.Dispatch* @Author: peach* @Date: 2019/04/10*/public Dispatch getTable() {ComThread.InitSTA();//ComThread也就是我们包中的对象 jacob包中  进行初始化ActiveXComponent application = new ActiveXComponent("Word.Application");//开启word 它会指定我们的默认程序MSoffice或者WPS程序application.setProperty("Visible",new Variant(true));//设置程序可见Dispatch documents = application.getProperty("Documents").toDispatch();//使用Word程序获取到所有的文档对象使用getProperty,Dispatch doc = Dispatch.call(documents, "Open", new Variant(filepath),new Variant(false)).toDispatch();//当前doc代表的是已经打开的文档,get方法如上面所说是获取到对象的属性的,// 这里代表获取当前文档的所有表格集合  注意不是一个表格 而是所有表格的集合Dispatch tables = Dispatch.get(doc, "Tables").toDispatch();//获取当前应用的选择器//选择器怎么说呢就是我们在操作文档的时候 能执行选择文字的操作的东西,我们一定需要获取它Dispatch selection = Dispatch.get(application, "Selection").toDispatch();//获取文档中第一个表格,可以调用add方法添加 详情查看文档。table = Dispatch.call(this.getTables(), "Item",new Variant(1)).toDispatch();return table;}/*** @Description:通过行数和列数获取到单元格* @Param: [row, column]* @return: com.jacob.com.Dispatch* @Author: peach* @Date: 2019/04/17*/public Dispatch getCell(Integer row,Integer column){Dispatch cell = Dispatch.call(table, "Cell", new Variant(row), new Variant(column)).toDispatch();//这里是通过此单元格的行数和列数类进行定位,行数和列数从1开始return cell;}/** * @Description: 取消当前表格中所有字体的加粗* @Param: [] * @return: void * @Author: peach* @Date: 2019/04/11 */ private void cancelBold(){Dispatch.call(table,"Select");Dispatch font = Dispatch.get(selection, "Font").toDispatch();Dispatch.put(font,"Bold",new Variant(false));}/** * @Description: tables集合对象get方法* @Param: [] * @return: com.jacob.com.Dispatch * @Author: peach* @Date: 2019/04/10 */ public Dispatch getTables() {//获取所有的tables对象if (tables == null || tables.m_pDispatch == 0){tables = Dispatch.get(doc,"Tables").toDispatch();}return tables;}

如果想要看到更多方法和属性请点击[微软开发者平台][https://docs.microsoft.com/zh-cn/office/vba/api/overview/word]

讲一下怎么看这个开发文档吧,如果不习惯中文可以使用英文,

我们可以看到代码中的语法这一列,他写的是

expression.tables 并且tables是Document的属性,我们一定要看清楚这个是对象的属性还是方法

然后下面说了这个expression代表的是一个Document对象,意思我们可以通过获取Document的tables属性获取到tables,前面说的返回一个Table集合, 该集合代表指定文档中的所有表格。 此为只读属性。

那么我们在代码里面怎么写呢?

当前是tables属性,那么我们的调用方式如下:

Dispatch tables = Dispatch.get(doc,"Tabels").toDispatch(); //因为Tables是属性,所以调用get方法

Dispatch是所有处理类的存放地址,doc代表的是Document对象,第二个参数是需要拿到的第一个参数的属性名称。最后调用toDispatch转换成可操作的对象。

如果调用有参数的方法

我们可以看到文档中,tables对象的item方法需要传递参数,类型是long类型的,且参数是必须的,参数代表的意思是index 也就是索引,返回值是单个Table对象,

VBA中的调用方式是

​ expression.item(Long index);

我们在jacob的调用方式如下

Dispatch table = Dispatch.call(tables,"Item",new Variant(1)).toDispatch();//因为item是方法,所以使用call方法,获取到Tables集合的第一个表格, 注意索引是从1开始不是从0

5、一些操作和异常需要注意

1)、通过获取某个单元格删除某一行

​ 这里需要说明下,如果是平常逻辑 我们通过获取tables->table->rows->row即可删除 我为什么需要获取到 row->cell->Rows呢

​ 原因如下:

​ 如果你的表格里面有纵向合并的单元格或者横向合并的单元格,让我们通过rows的item方法获取到某一行的或者columns的item方法获取到某一列的时候会报错

​ 报错信息大概是:

     com.jacob.com.ComFailException: Invoke of: ItemSource: Microsoft WordDescription: 无法访问此集合中单独的行,因为表格有纵向合并的单元格。

​ 没错这个报错是中文的,所以我们需要通过获取到某一个单元格反向选择这个单元格的rows属性,虽然是Rows,但是返回的却是一行。

    /** * @Description: 通过获取某个单元格而删除这个单元格所在的某一行* @Param: [cell] * @return: void * @Author: peach* @Date: 2019/04/11 */ private void deleteRow(Dispatch cell){//此处如果调用rows的select方法,再将选择的删除 那么删除的是选择的rows里面得内容 如果直接调用rows的delete方法则删除的是表格的行Dispatch range = Dispatch.call(cell, "Range").toDispatch();Dispatch rows = Dispatch.get(range, "Rows").toDispatch();Dispatch.call(rows,"Delete"); //删除行 包括表格//下面的方式会删除行里面得内容 保留表格结构
//        Dispatch.call(rows,"Select");
//        Dispatch.call(selection,"Delete");}

2)、对象的select方法

这个方法非常神奇,当我们需要获取某个对象的时候,一定要先调用它的select方法将其选中,选中之后才能够获取Text或者Value属性获取他的值。

当我们选择一个对象之后,我们在打开文档时初始化的selection对象(选择器对象)中自动就会将我们调用select的这个对象放到选择器中,之后调用

例如:

    /** * @Description: 获取传递过来的单元格的值* @Param: [cell] * @return: java.lang.String * @Author: peach* @Date: 2019/04/11 */ private String getCellValue(Dispatch cell){Dispatch.call(cell,"Select"); //首先调用select方法 return Dispatch.call(selection, "Text").toString(); //注意这里的第一个参数是选择器哦,返回的是该单元格中的值}

三、使用jacob操作Excel

因为使用的同样都是jacob,所以开启方法和调用方法的方式都差不多,但是依然有不同的地方,接下来向大家介绍。

1、开启线程和打开EXCEL文档

private static ActiveXComponent excelApplication; //excel程序对象 防止打开多个
private static Dispatch workbooks; //全部工作簿对象
private Dispatch workbook;//具体某一个工作簿对象
private Dispatch sheets;//获取所有的sheets对象
private Dispatch currentSheet;//获取当前sheet/**
* @Description: 打开文档
* @Param: [filepath, visible]
* @return: void
* @Author: peach
* @Date: 2019/04/11
*/
public void openExcel(String filepath,boolean visible){try {//初始化线程ComThread.InitSTA();excelApplication = new ActiveXComponent("Excel.Application");excelApplication.setProperty("Visible",new Variant(visible));//设置不可见//前面的操作和word一致,从这里开始,有点不同//首先这里不再是文档集合Documents ,而是工作表集合Workbooks,但是和文档集合是一个层级workbooks = excelApplication.getProperty("Workbooks").toDispatch();//打开已经存在的Excel文档workbook = Dispatch.invoke(workbooks,//第一个参数是被执行invoke的对象"Open",//第二个参数是  被执行参数的什么属性或者方法Dispatch.Method,//这里第三个参数, 如果第二个参数是方法这里就调用call 如果是属性就调用getnew Object[]{ // 第四个参数   将文档成功打开之后 workerbooks的 Open方法/参数将会变成这个参数的值filepath,  //文件路径new Variant(false),//是否以只读的方式打开,因为要操作所以需要不使用只读的方式new Variant(false),//这个参数目前未知"1","pwd" //此处为密码,如果该文档有蜜蜡聚设置密码},new int[1] //第五个参数为错误级别,一般为1即可).toDispatch();//invoke 就是没有返回值的call方法}catch (Exception e){//执行清空操作e.printStackTrace();}
}

2、定位到某一个工作表

工作表的概念我们应该都清除,也就是在左下角通过sheet1,sheet2,sheet3的方式进行转换。

每一个sheet就是一个工作表,之后再获取到这个工作表中所有元素或者其他,所以我们获取的顺序也应该是如下:

application(程序、应用)->Workbooks(工作簿的集合)->workbook(某一个工作簿)->sheet(工作表)->表中的其他元素(usedRange等)

/**
* @Description:  获取当前活动的sheet ,当Excel第一次打开的时候的sheet即为activesheet,当我们切换之后 这个activesheet就会改变
* @Param: []
* @return: com.jacob.com.Dispatch
* @Author: peach
* @Date: 2019/04/03
*/
private Dispatch getCurrentSheet(){currentSheet = Dispatch.get(workbook,"ActiveSheet").toDispatch();return currentSheet;
}/** * @Description: 获取当前单元格所有已经使用的区域的集合 * @Param: [] * @return: com.jacob.com.Dispatch * @Author: peach* @Date: 2019/04/22 */ private Dispatch getUsedRange(){Dispatch useRange = Dispatch.get(this.getCurrentSheet(), "UsedRange").toDispatch();return useRange;}/*** @Description:  获取单元格的值,和word不通过的是,在excel中是有横纵坐标的,所以我们传递的位置值类似于C1 C2这样* @Param: [position]  位置信息 可以通过getposition方法生成* @return: java.lang.String * @Author: peach* @Date: 2019/04/03 */ private String getCellValue(String position){Dispatch cell = Dispatch.invoke(getCurrentSheet(),"Range",Dispatch.Get,new Object[]{new Variant(position)},new int[1]).toDispatch();return Dispatch.get(cell,"value").toString(); //todo 验证了 有区别 尽量使用value,获取到的是全部的值,如果使用text则获取excel显示出来的值 }

在表格中,没有第一个表第二个二表这样的概念,所以我们可以直接通过A1 A2的方式进行获取,同时如果表格中存在合并的单元格,则以第一个单元格位置为整个单元格的位置,例如:

可以通过定位到某一个range(区域,能够选择的部分)来获取到其中的值,代码如下:

/**
* @Description:  获取单元格的值,和word不通过的是,在excel中是有横纵坐标的,所以我们传递的位置值类似于C1 C2这样
* @Param: [position]  位置信息 可以通过getposition方法生成
* @return: java.lang.String
* @Author: peach
* @Date: 2019/04/03
*/
private String getCellValue(String position){Dispatch cell = Dispatch.invoke(getCurrentSheet(),"Range",Dispatch.Get,new Object[]{new Variant(position)},new int[1]).toDispatch();//由于get方法无法传值,所以只有使用invoke方法进行获取。return Dispatch.get(cell,"value").toString(); //todo 验证了 Value和text 有区别 尽量使用value 大小写没啥区别   text和value区别看下方
}

这里说一下value和text的区别,也就是我们调用get方法的时候获取的是这个对象中的哪个属性,excel中如果使用

​ text:获取到的是这个文本中显示给用户看的值

​ value:获取到全部长度的值

2、特殊说明

其次invoke和get,call方法的差别,这三个方法在jacob操作的任何文档都可以调用,他们三个有什么区别呢,我们慢慢说,先看看调用方式。

call方法

//没有参数没有返回值的call
Dispatch.call(currentSheet,"Select");
//有返回值的call
Dispatch chartObjects = Dispatch.call(currentSheet,"ChartObjects").toDispatch();
//有参数的call
Dispatch chartObject = Dispatch.call(chartObjects"Item", new Variant(1)).toDispatch();

get方法

//get方法会有返回值,但是get方法不能够传递参数,因为这个Chart本身就是个参数
Dispatch chart = Dispatch.get(chartObject, "Chart").toDispatch();

invoke方法是get和call方法的集合

Dispatch.invoke(sheets, //第一个参数需要调用的 对象 当前sheets对象"Item", //调用的地向的哪个 方法或者属性 当前sheets对象的Item方法Dispatch.Method, //调用方式,如果是 方法则使用Dispatch.Method 如果是属性则使用Dispatch.Getnew Object[]{new Variant{name}}, //此方法的参数  如果有多个则在Object数组中添加多个new int[1] //错误级别,默认为1即可).toDispatch();

我们可以发现,其实invoke和get、call方法相同,在底层get和call方法其实都是调用的invoke方法,无非是这样方便我们调用。

我们都知道前面在word中的介绍我们获取表格的某一个单元格,我们使用的方式是行,列的方式如下:

/**
* @Description:通过行数和列数获取到单元格
* @Param: [row, column]
* @return: com.jacob.com.Dispatch
* @Author: peach
* @Date: 2019/04/17
*/
public Dispatch getCell(Integer row,Integer column){Dispatch cell = Dispatch.call(table, "Cell", new Variant(row), new Variant(column)).toDispatch();//这里是通过此单元格的行数和列数类进行定位,行数和列数从1开始return cell;
}

但是在excel中,我们并没有按照这个方式,而是通过字母+数字的方式定位,举个例子,第一行第一列的单元格在EXCEL表示为A1单元格, 所以在excel中定位单元格需要遵循这个方式,下面给了两个方法,一个是生成坐标,另外一个则是通过坐标获取到单元格中的值。

      /** * @Description: 通过行数和列数获取到当前表格中的position* @Param: [row, column] 行和列* @return: java.lang.String * @Author: peach* @Date: 2019/04/03 */ private String getPosition(Integer row,Integer column){Integer columnCount = getColumnCount(getCurrentSheet());String position = "";if (columnCount >26){  //第27列表示的是AA,所以我们需要转换成int multiple = columnCount/26;  //1 用列数除以26 看我们需要多少个A、获取十位int remainder = columnCount%26; // 取出余下的数字 加上A的ascii码 就得到个位数的字母char rchar = (char)(remainder+64); //通过ascii码转换的形式获取大写的A ,这个是余下的数代表的字母 1代表A char mchar = (char)(multiple+64); //这是左边的字母position = mchar+""+rchar;}else{position = (char)(column+64)+"";}return position+""+row;}/*** @Description:  获取单元格的值,和word不通过的是,在excel中是有横纵坐标的,所以我们传递的位置值类似于C1 C2这样* @Param: [position]  位置信息 可以通过getposition方法生成* @return: java.lang.String * @Author: peach* @Date: 2019/04/03 */ private String getCellValue(String position){Dispatch cell = Dispatch.invoke(getCurrentSheet(),"Range",Dispatch.Get,new Object[]{new Variant(position)},new int[1]).toDispatch();return Dispatch.get(cell,"value").toString(); //todo 验证了 有区别 尽量使用value 大小写也没啥区别}

我们通过当前表格的Range属性,传入参数即可。

更多对象和方法参照官方文档,这一部分在页面最顶端。

四、使用jacob操作AutoCAD

jacob还可以操作AutoCAD,

AutoCAD的操作是我踩坑最多的,因为之前没有用过AutoCAD这方面的软件,话不多说直接上代码吧。

注意,我是用的是AutoCAD的经典模式,也就是黑色的平面图的那种。版本是AutoCAD2007 因为客户的版本较低,所以我们只能用低版本,但是实际上没多大差别。

1、打开有一个autocad文件

    ActiveXComponent app;Dispatch documents;Dispatch doc;Dispatch cads;Dispatch cad;/** * @Description: 打开AutoCAD文件* @Param: [] * @return: void * @Author: peach* @Date: 2019/04/22 */ public void openFile(){ComThread.InitSTA();app = new ActiveXComponent("AutoCAD.Application");app.setProperty("visible",new Variant(true));//设置可见documents = app.getProperty("Documents").toDispatch();//获取到文档集合对象 这里和word一致doc = Dispatch.invoke(documents, "Open", Dispatch.Method, new Object[]{"C:\\Users\\Administrator\\Desktop\\桩顶水平位移变化曲线图11.07.dwg",new Variant(false), //不以 只读 方式打开new Variant(false)}, new int[1]).toDispatch();}/*** @Description: 画线,通过两点坐标画线和圆* @Param: []* @return: void* @Author: peach* @Date: 2019/04/22*/public void DrawLine(){Dispatch ModelSpace = Dispatch.get(doc,"ModelSpace").toDispatch();double[] startPoint={100.0,100.0,0}; //注意 此处只能使用基本类型小写double,不能使用封装类Double 大写的Double 不然会报错该方法的数据类型在文档中已经提出double[] endPoint={200.0,200.0,0};double radius = 25;Dispatch.call(modelSpace, "AddLine", startPoint, endPoint).toDispatch();}

关于double参数的问题,在文档的方法中,已经写得很清楚,他是基本类型中的double而不是封装类Double,我们一起来看看

[addLine方法][http://entercad.ru/acadauto.en/idh_addline.htm]

翻译之后如下,使用的是chrom浏览器的翻译功能,如果不能再当前页翻译,就右键点击链接新开一页之后翻译:

2、AutoCAD的目录结构

这个在官方文档中提出了更加详细,一起看看吧

[AutoCAD官方文档地址][http://entercad.ru/acadauto.en/]

可以看到我们常用的对象层级关系如下:

关于在工作空间中画图

Application-> Documents->Document->ModelSpace->其他子组件 最常用

Application-> Documents->Document->Blocks->Block->其他子组件

关于获图层

Application-> Documents->Document->Layers->Layer

关于视图

Application-> Documents->Document->Views->View

关于坐标轴

Application-> Documents->Document->UCSs->UCS

其他还有很多方式可以获取到我们想要的方法或者属性。

五、常见错误和异常

这位博主给大家整理了一些[地址][https://www.cnblogs.com/yzuzhang/p/5134655.html]

我这里说一些很奇葩的错误吧,

1、com.jacob.com.ComFailException: Can’t map name to dispid: XXXX

这样的错误通常都是属性写错了,没有找到XXXX这个属性或者方法

2、com.jacob.com.ComFailException: Invoke of: Item
Source: Microsoft Word
Description: 集合所要求的成员不存在。

这样的错误表示你想要获取的这个对象的索引超过了集合的最大值,

3、com.jacob.com.ComFailException: Invoke of: Item
Source: Microsoft Word
Description: 无法访问此集合中单独的行,因为表格有纵向合并的单元格。

这个错在word中很常见,因为word表格中有合并单元格 所以没有办法定位到某一行,解决办法在上方的word中一个方法叫做 通过单元格反向获取此列可以获取到这一列。

4、com.jacob.com.ComFailException: Invoke of: AddLine
Source:
Description:

对 这样的错 什么报错信息都没有的,这样的错代表的是 通过java调用文档底层的方法出错,首先排查我们的数据类型是否填写正确,正确的数据类型在官网都是有的,可以对照。其次看看官方的调用实例代码,排查是否出错。

类似于数据需要基本类型double 不能是否装类型Double

5、java.lang.IllegalArgumentException: Can’t pass in null Dispatch object

代表不能够转换null对象为Dispatch,怎么看我们拿到的对象是不是空的呢,我们可以通过

table.m_pDispatch();//它的值来判断 如果值为0则是空的

6、com.jacob.com.ComFailException: Invoke of: Open
Source: Microsoft Word
Description: 命令失败

一般原因是我们打开了某一文档但是并没有关闭,之后又以非只读的方式打开了,所以导致冲突,我们只需要关闭之前的文档重新运行即可。

以上就是全部内容

jacob操作excel、word、AutoCAD分享相关推荐

  1. jacob java excel_使用 Jacob 操作Excel、Word文件

    Excel是常用的报表格式,一般系统中要求生成报表,多半都是使用Excel格式.在Java中操作Excel可以使用JavaExcel(jxl)或poi,大部分常用的功能都能实现,也很方便,但生成好的报 ...

  2. jacob操作office word简单教程

    现在的项目中操作word文件比较多,word文件的加密解密,转换为各种格式,插入图片,添加水印.html转word等等各种东西,大家也都知道,java语言是不能直接操作word或者excel的,不像C ...

  3. 一文学会用Python操作Excel+Word+CSV

    作者:奈何缘浅wyj https://juejin.im/post/6868073137263607821 Python 操作 Excel 常用工具 数据处理是 Python 的一大应用场景,而 Ex ...

  4. MFC VC 操作Excel,word的OLE对象

    声明:上次写这篇文章的时候用的是截图,导致看不见东西,不是故意的. 本文的内容有两部分: 第一部分是手动打开一个excel表格以后,Ctrl+C复制表格中的内容,点击程序中的一个按钮,跳到OnTree ...

  5. php excel 设置常规_php实现的操作excel类详解

    本文实例讲述了php实现的操作excel类.分享给大家供大家参考,具体如下: class Excel { static $instance=null; private $excel=null; pri ...

  6. 基于 DocumentFormat.OpenXml 操作 Excel (1)-- 初识

    最近抽空研究了一下 基于DocumentFormat.OpenXml操作Excel,也把自己的理解记录下来,便于日后可以查阅. 各种系统中,导出Excel是一种很常见的功能,在C#/.Net 环境下, ...

  7. jacob操作word和excel

    jacob操作word和excel jacob的官方文档:http://danadler.com/jacob/ 微软的javasdk文档:http://f2.grp.yahoofs.com/v1/II ...

  8. jacob操作word excel 将word excel转换成网页形式

    jacob操作word excel(来自http://sinye.iteye.com/blog/588050) 项目开发过程中,需求涉及到了各种文档转换为HTML或者网页易显示格式,现在将实现方式整理 ...

  9. jacob操作office分享

    简介: jacob(java com bridge,java com桥)分为两个部分,jacob.jar,jacob.dll,使用时两个东西的版本要一致,而且还分32位和64位,它的位数和jdk的位数 ...

最新文章

  1. 神策学堂发布——你有一份数据驱动指南待查收
  2. html5实现的复古软件winamp的播放效果
  3. 数据结构实验之栈一:进制转换
  4. android自动布局优先级,自动布局AutoLayout
  5. yum 安装 一个小问题导致找不到安装包
  6. Windows7下安装redmine-3.4.6
  7. POJ2104(K-th Number)
  8. 如何搭建私人电子图书馆
  9. 视频识别车牌号(Python)
  10. 基于MATLAB的DS证据融合代码
  11. STM32F4 使用 JFlash 加密后无法再擦除了
  12. 一直播、小咖秀大数据自动化运维实践
  13. 51单片机指令系统详解
  14. 李开复写给中国大学生的七封信【7/7】
  15. Linux系统管理、系统安全命令概述
  16. Thinkphp3.2(tp3.2) sql语句表达式查询字符列表【eq,neq,gt,egt,lt,elt,in,between,like,exp】
  17. python adb控制手机制作剑气除魔游戏辅助
  18. Dynamics 365 可编辑子网格的字段禁用不可编辑
  19. 【JVM】字节码与ASM字节码增强、Instrument实现类的动态重加载
  20. 永磁同步电机滑膜控制SMO控制仿真模型

热门文章

  1. Dota 游戏中的攻击与伤害分析
  2. 径向基函数模型matlab,径向基函数RBF.ppt
  3. CNCF 云原生容器生态系统概要
  4. 树莓派无线中继的实现
  5. AndroidStudio运行模拟器--夜神
  6. 命令行的迅雷,这样用会更香
  7. SASS _ 入门版
  8. 十、如何给标识符命名
  9. 批处理:批量修改文件名称
  10. mysql datasource property_spring配置datasource三种方式