12、使用Jacob来处理文档


Word或Excel程序是以一种COM组件形式存在的。如果能够在Java中调用相应组件,便能使用它的方法来获取文档中的文本信息。Jacob是一个JAVA到微软的COM接口的桥梁。Jacob允许任何JVM访问COM对象,从而使JAVA应用程序能够调用COM对象。如果要对 MS Word、Excel 进行处理,Jacob 是一个好的选择。

12.1、Jacob的下载


Jacob 是Java-COM Bridge的缩写,它在Java与微软的COM组件之间构建一座桥梁。使用Jacob自带的DLL动态链接库,并通过JNI的方式实现了在Java平台上对COM程序的调用。Jacob下载的地址为:

http://sourceforge.net/project/showfiles.php?group_id=109543&package_id=118368。

12.2、在Eclipse中的配置


(1) 将jacob.jar导入工程的Build Path,然后确认自己机器的CPU类型(X86或AMD64),并选择不同目录下的jacob.dll文件。

(2) 将jacob.dll放到%JAVA_HOME%\jre\bin目录下,其中,%JAVA_HOME%就是JDK的安装目录。注意这个的jre目录必须是Eclipse当前正在使用的目录,在Eclipse中选择“window->Preferences”菜单,在弹出的对话框中选择“Java->Installed JREs”项。

(3) 当前选择的JRE是“C:\Program Files\Java\jdk1.5.0_07\jre”目录下的,所以需要把jacob.dll复制到“C:\Program Files\Java\jdk1.5.0_07\jre\bin”目录下面。

(4) 在工程中新建一个ch7.jacob包,并在包中创建WordReader类。该类将提供一个静态的extractDoc()方法。它接收两个参数,一个是要处理的DOC文件名,另一个则是输出的文件名,然后通过JNI调用Word的API转换内容,该函数的代码如下。

  1. public static void extractDoc(String inputFIle, String outputFile) {
  2.  
  3. boolean flag = false;
  4.  
  5. // 打开Word应用程序
  6.  
  7. ActiveXComponent app = new ActiveXComponent("Word.Application");
  8.  
  9. try {
  10.  
  11. // 设置word不可见
  12.  
  13. app.setProperty("Visible", new Variant(false));
  14.  
  15. // 打开word文件
  16.  
  17. Dispatch doc1 = app.getProperty("Documents").toDispatch();
  18.  
  19. Dispatch doc2 = Dispatch.invoke(
  20.  
  21. doc1,
  22.  
  23. "Open",
  24.  
  25. Dispatch.Method,
  26.  
  27. new Object[] { inputFIle, new Variant(false),
  28.  
  29. new Variant(true) }, new int[1]).toDispatch();
  30.  
  31. // 作为txt格式保存到临时文件
  32.  
  33. Dispatch.invoke(doc2, "SaveAs", Dispatch.Method, new Object[] {
  34.  
  35. outputFile, new Variant(7) }, new int[1]);
  36.  
  37. // 关闭word
  38.  
  39. Variant f = new Variant(false);
  40.  
  41. Dispatch.call(doc2, "Close", f);
  42.  
  43. flag = true;
  44.  
  45. } catch (Exception e) {
  46.  
  47. e.printStackTrace();
  48.  
  49. } finally {
  50.  
  51. app.invoke("Quit", new Variant[] {});
  52.  
  53. }
  54.  
  55. if (flag == true) {
  56.  
  57. System.out.println("Transformed Successfully");
  58.  
  59. } else {
  60.  
  61. System.out.println("Transform Failed");
  62.  
  63. }
  64.  
  65. }

注意:在使用Jacob时,很重要的一点是,用户本地系统中必须安装有Word的应用程序。否则也就无法建立Java-COM桥,进而无法解析了。

12.3、Jacob中常用方法


(1) 初始化com的线程,很重要,否则第二次创建com对象的时候会出现can't co-create object异常,完成操作com组件后要调用release方法。

ComThread.InitSTA();// 初始化com的线程

(2) 初始化word应用程序,新建一个空白文档,取得文档内容对象

//Instantiate objWord //Declare word object

ActiveXComponent objWord = new ActiveXComponent("Word.Application");

//Assign a local word object

Dispatch wordObject = (Dispatch) objWord.getObject();

//Create a Dispatch Parameter to show the document that is opened

Dispatch.put((Dispatch) wordObject, "Visible", new Variant(true));

// new Variant(true)表示word应用程序可见

Tip:设置一个对象的属性的时候,利用Dispatch的put方法,给属性赋值。上面这行语句相当于vb的wordObject.Visible=true语句。

//Instantiate the Documents Property

Dispatch documents = objWord.getProperty("Documents").toDispatch();

//documents表示word的所有文档窗口。

//Add a new word document, Current Active Document

Dispatch document = Dispatch.call(documents, "Add").toDispatch();

// 使用Add命令创建一个新文档,用Open命令可以打开一个现有文档

Tip:调用一个对象的方法的时候,利用Dispatch的call方法,上面的语句相当于vb的document = documents.Add() 语句。

Dispatch wordContent = Dispatch.get(document, "Content").toDispatch();

// 取得word文件的内容

Tip:取得一个对象的成员变量(属性)时,利用Dispatch的get方法,上面的语句相当于vb的wordContent = document.Content语句。

(3) 取得word文档的内容后,可以对其内容进行操作

Dispatch.call(wordContent, "InsertAfter", "这里是一个段落的内容");//插入一个段落

(4) 设置刚插入的段落的文字格式

Dispatch paragraphs = Dispatch.get(wordContent, "Paragraphs").toDispatch();

// 获取所有段落

int  paragraphCount = Dispatch.get(paragraphs, "Count").toInt();

// 总的段落数

Dispatch lastParagraph = Dispatch.call(paragraphs, "Item",new Variant(paragraphCount)).toDispatch();

// 最后一段

Dispatch lastParagraphRange = Dispatch.get(lastParagraph, "Range").toDispatch();

Dispatch font = Dispatch.get(lastParagraphRange, "Font").toDispatch();

Dispatch.put(font, "Bold", new Variant(true));

// 设置为黑体

Dispatch.put(font, "Italic", new Variant(true));

// 设置为斜体

Dispatch.put(font, "Name", new Variant("宋体")); //

Dispatch.put(font, "Size", new Variant(12)); //小四

注意:如果想插入一个新的空白行,也需要设置段落的文字格式,否则新插入行的文字格式会于刚插入的段落的格式相同。

(5) 将当前文档保存

Dispatch.call(document, "SaveAs", new Variant("C:abc.doc")); // 保存一个新文档

(6) 释放COM线程

ComThread.Release();//释放com线程。根据Jacob的帮助文档,com的线程回收不由java的垃圾回收器处理。

12.4、Jacob中常用模块


(1) 打印模块

  1. ActiveXComponent axc = null;
  2. try {
  3. ComThread.InitSTA();
  4. axc = new ActiveXComponent("Excel.Application");
  5. Dispatch.put(axc, "Visible", new Variant(false));
  6. Dispatch workbooks = axc.getProperty("Workbooks").toDispatch();
  7. Dispatch workbook = Dispatch.call(workbooks, "Open", fileFullPath,
  8. new Integer(0), Boolean.FALSE).toDispatch();
  9. Dispatch sheets = Dispatch.call(workbook, "Worksheets").toDispatch();
  10. Dispatch sheet = Dispatch.call(sheets, "Item", new Integer(1))
  11. .toDispatch();
  12. Dispatch.call(sheet, "PrintOut", new Integer(beginPage), new Integer(endPage), new Integer(copys));
  13. Dispatch.call(workbook, "Close", Variant.VT_FALSE);
  14. } finally {
  15. axc.invoke("Quit", new Variant[] {});
  16. ComThread.Release();
  17. }

(2) 纸张大小设置

  1. Dispatch pageSetup = Dispatch.call(sheet, "PageSetup").toDispatch();
  2. Dispatch.put(pageSetup, "PaperSize", new Integer(8));//A3是8,A4是9,A5是11等等

可通过如下方式获取纸张大小所对应的整数值

  1. int ps = Dispatch.get(pageSetup, "PaperSize").toInt();
  2. System.out.println("ps=" + ps);

(3)页边距设置

  1. Dispatch.put(pageSetup, "LeftMargin", new Variant(left)); //左
  2. Dispatch.put(pageSetup, "TopMargin", new Variant(top)); //上
  3. Dispatch.put(pageSetup, "RightMargin", new Variant(right)); //右
  4. Dispatch.put(pageSetup, "BottomMargin", new Variant(bottom)); //下
  5. Dispatch.put(pageSetup, "HeaderMargin", new Variant(header)); //页眉
  6. Dispatch.put(pageSetup, "FooterMargin", new Variant(footer)); //页脚

注: left、top、right、bottom、header和footer是double类型的数值,并且如果单位是厘米的话,需乘以28.35。

(4) 统计Excel已使用的行数

  1. Dispatch userRange=Dispatch.call(sheet, "UsedRange").toDispatch();
  2. Dispatch row=Dispatch.call(userRange, "Rows").toDispatch();
  3. int rowCount=Dispatch.get(row,"Count").getInt();
  4. System.out.println("rowCount=" + rowCount);

(5) 在指定的行号上插入一空行

  1. Dispatch rowSheet = Dispatch.call(sheet, "Rows", new Variant(i)).toDispatch();//这里的i是行号,int类型
  2. rowSheet.call(rowSheet, "Insert");

(6) 根据不同版本的Excel做不同的处理

  1. System.out.println("version=" + axc.getProperty("Version"));

12.5、程序实例


(1)实例一:

  1. package com.xfzx.test.POI.main;
  2.  
  3. import com.jacob.activeX.ActiveXComponent;
  4. import com.jacob.com.ComThread;
  5. import com.jacob.com.Dispatch;
  6. import com.jacob.com.Variant;
  7.  
  8. public class JacobPress {
  9.  
  10. /**
  11. * @param args
  12. */
  13. public static void main(String[] args) {
  14. // TODO Auto-generated method stub
  15. printWord("D:/txt.docx");
  16. // printExcel("D:/提醒通知明细通用模板.xlsx");
  17. }
  18.  
  19. public static void printExcel(String filePath) {
  20. /**
  21. * 功能:实现打印工作
  22. */
  23. ComThread.InitSTA();
  24. ActiveXComponent xl = new ActiveXComponent("Excel.Application");
  25. try {
  26. // System.out.println("version=" + xl.getProperty("Version"));
  27. // 不打开文档
  28. Dispatch.put(xl, "Visible", new Variant(true));
  29. Dispatch workbooks = xl.getProperty("Workbooks").toDispatch();
  30. // 打开文档
  31. Dispatch excel = Dispatch.call(workbooks, "Open", filePath)
  32. .toDispatch();
  33. // 开始打印
  34. Dispatch.call(excel, "PrintOut");
  35. xl.invoke("Quit", new Variant[] {});
  36. } catch (Exception e) {
  37. e.printStackTrace();
  38. } finally {
  39. // 始终释放资源
  40. ComThread.Release();
  41. }
  42. }
  43.  
  44. public static void printWord(String filePath) {
  45. ComThread.InitSTA();
  46. ActiveXComponent wd = new ActiveXComponent("Word.Application");
  47. try {
  48. // 不打开文档
  49. Dispatch.put(wd, "Visible", new Variant(true));
  50. Dispatch document = wd.getProperty("Documents").toDispatch();
  51. // 打开文档
  52. Dispatch doc = Dispatch.invoke(document, "Open", Dispatch.Method,
  53. new Object[] { filePath }, new int[1]).toDispatch();
  54. // 开始打印
  55. Dispatch.callN(doc, "PrintOut");
  56. wd.invoke("Quit", new Variant[] {});
  57. } catch (Exception e) {
  58. e.printStackTrace();
  59. } finally {
  60. // 始终释放资源
  61. ComThread.Release();
  62. }
  63. }
  64.  
  65. // 获得文件后缀名
  66. public static String getPostfix(String inputFilePath) {
  67. String[] p = inputFilePath.split("\\.");
  68. if (p.length > 0) {// 判断文件有无扩展名
  69. // 比较文件扩展名
  70. return p[p.length - 1];
  71. } else {
  72. return null;
  73. }
  74. }
  75.  
  76. }

(2)实例二:

  1. public static boolean printOfficeFile(File f) {
  2. if (f != null && f.exists()) {
  3. String fileNameString = f.getName();
  4. String postfixString = Utils.getPostfix(fileNameString);
  5. if (postfixString.equalsIgnoreCase("xls")
  6. || postfixString.equalsIgnoreCase("xlsx")) {
  7. /**
  8. * 功能:实现excel打印工作
  9. */
  10. ComThread.InitSTA();
  11. ActiveXComponent xl = new ActiveXComponent("Excel.Application");
  12. try {
  13. // System.out.println("version=" +
  14. // xl.getProperty("Version"));
  15. // 不打开文档
  16. Dispatch.put(xl, "Visible", new Variant(false));
  17. Dispatch workbooks = xl.getProperty("Workbooks")
  18. .toDispatch();
  19. // 打开文档
  20. Dispatch excel = Dispatch.call(workbooks, "Open",
  21. f.getAbsolutePath()).toDispatch();
  22. // 横向打印(2013/05/24)
  23. // Dispatch currentSheet = Dispatch.get(excel, "ActiveSheet")
  24. // .toDispatch();
  25. // Dispatch pageSetup = Dispatch
  26. // .get(currentSheet, "PageSetup").toDispatch();
  27. // Dispatch.put(pageSetup, "Orientation", new Variant(2));
  28. //每张表都横向打印2013-10-31
  29. Dispatch sheets = Dispatch.get((Dispatch) excel, "Sheets")
  30. .toDispatch();
  31. // 获得几个sheet
  32. int count = Dispatch.get(sheets, "Count").getInt();
  33. // System.out.println(count);
  34. for (int j = 1; j <=count; j++) {
  35. Dispatch sheet = Dispatch.invoke(sheets, "Item",
  36. Dispatch.Get, new Object[] { new Integer(j) },
  37. new int[1]).toDispatch();
  38. Dispatch pageSetup = Dispatch.get(sheet, "PageSetup").toDispatch();
  39. Dispatch.put(pageSetup, "Orientation", new Variant(2));
  40. Dispatch.call(sheet, "PrintOut");
  41. }
  42. // 开始打印
  43. if (excel != null) {
  44. //Dispatch.call(excel, "PrintOut");
  45. //增加以下三行代码解决文件无法删除bug
  46. Dispatch.call(excel, "save");
  47. Dispatch.call(excel, "Close" , new Variant(true));
  48. excel=null;
  49. }
  50. xl.invoke("Quit", new Variant[] {});
  51. xl=null;
  52. return true;
  53. } catch (Exception e) {
  54. e.printStackTrace();
  55. return false;
  56. } finally {
  57. // 始终释放资源
  58. ComThread.Release();
  59. }
  60. } else if (postfixString.equalsIgnoreCase("doc")
  61. || postfixString.equalsIgnoreCase("docx")) {
  62. ComThread.InitSTA();
  63. ActiveXComponent wd = new ActiveXComponent("Word.Application");
  64. try {
  65. // 不打开文档
  66. Dispatch.put(wd, "Visible", new Variant(false));
  67. Dispatch document = wd.getProperty("Documents")
  68. .toDispatch();
  69. // 打开文档
  70. Dispatch doc = Dispatch.invoke(document, "Open",
  71. Dispatch.Method, new Object[] { f.getAbsolutePath() },
  72. new int[1]).toDispatch();
  73. // 开始打印
  74. if (doc != null) {
  75. Dispatch.call(doc, "PrintOut");
  76. //增加以下三行代码解决文件无法删除bug
  77. Dispatch.call(doc, "save");
  78. Dispatch.call(doc, "Close" , new Variant(true));
  79. doc=null;
  80. }
  81. wd.invoke("Quit", new Variant[] {});
  82. wd=null;
  83. return true;
  84. } catch (Exception e) {
  85. e.printStackTrace();
  86. return false;
  87. } finally {
  88. // 始终释放资源
  89. ComThread.Release();
  90. }
  91. } else {
  92. return false;
  93. }
  94. } else {
  95. return false;
  96. }
  97. }

12、借助Jacob实现Java打印报表(Excel、Word)的更多相关文章

  1. 10、借助POI实现Java生成并打印excel报表(1)

    10.1.了解 Apache POI 实际开发中,用到最多的是把数据库中数据导出生成报表,尤其是在生产管理或者财务系统中用的非常普遍.生成报表格式一般是EXCEL或者PDF .利用Apache  PO ...

  2. IIS下打印报表到Excel

    阅读本文之前,请先看上一篇文章<.NET下Excel报表的打印>. 上一篇文章<.NET下Excel报表的打印>介绍了关于报表打印到Excel文件中的方法.若要把项目通过IIS ...

  3. java读取大容量excel之二(空格、空值问题)

    最近在项目中发现,对于Excel2007(底层根本是xml) ,使用<java读取大容量excel之一>中的方式读取,若待读取的excel2007文件中某一列是空值,(注意,所谓的空值是什 ...

  4. Java 打印金字塔 or 打印带数字的金字塔 (Java 学习中的小记录)

    Java 打印金字塔 or 打印带数字的金字塔 (Java 学习中的小记录) 作者:王可利(Star·星星) 效果图: 代码如下: class Star8 { public static void m ...

  5. 重构:以Java POI 导出EXCEL为例

    重构 开头先抛出几个问题吧,这几个问题也是<重构:改善既有代码的设计>这本书第2章的问题. 什么是重构? 为什么要重构? 什么时候要重构? 接下来就从这几个问题出发,通过这几个问题来系统的 ...

  6. 反射反射,程序员的快乐+反射案例:打印和Excel导出

    还是那几句话: 学无止境,精益求精 十年河东,十年河西,莫欺少年穷 学历代表你的过去,能力代表你的现在,学习代表你的将来 看过设计模式的童鞋都知道:反射反射,程序员的快乐!今天我们就利用反射来制作打印 ...

  7. 如何在C/S下打印报表

     java应用有不少是C/S模式,在C/S模式下,同样可以调用API接口运算报表.CSReport是C/S模式下的报表控件类,在这个类中可以获得报表的显示面板.获得报表的打印面板.显示报表打印窗口 ...

  8. java 实现导出Excel文件

    java 实现导出Excel(java生成 excel 并导出文件) 经常有有一些数据需要导出成   excel  格式 ,所以就需要实现啦 开始: 1.加入jar poi-3.6-20091214. ...

  9. 在java poi导入Excel通用工具类示例详解

    转: 在java poi导入Excel通用工具类示例详解 更新时间:2017年09月10日 14:21:36   作者:daochuwenziyao   我要评论   这篇文章主要给大家介绍了关于在j ...

随机推荐

  1. redux计算器

    //简单运用redux写了一个加减乘除功能 <!DOCTYPE html><html lang="en"><head> <meta cha ...

  2. zoom动画,实现图片点击预览效果

    参考:https://developer.android.google.cn/training/animation/zoom.html 1.创建Views 下面的布局包括了你想要zoom的大版本和小版 ...

  3. JSP自定义不带属性和标签体的简单标签

    1. 新建HelloTag类 2. 添加额外的Jar包 (1). 右键项目 -> Build Path -> Configure Build Path -> Libraries -& ...

  4. Hibernate基础学习(四)—对象-关系映射(上)

    一.映射对象标识符      Java语言按内存地址来识别或区分同一个类的不同对象,而关系数据库按主键值来识别或区分同一个表的不同记录.Hibernate使用对象标识符(OID)来建立内存中的对象和数 ...

  5. C# 遍历泛型集合

    /// <summary> /// 遍历泛型 /// </summary> /// <typeparam name="T"></typep ...

  6. 将1、2、3、……、n这n个连续自然数分成g组,使每组的和相等。g组中个数最多的一组有几个?

    <style type="text/css"> #content { width: 600px; margin: 150px auto 0 auto; } dl dd ...

  7. 分离你的spring配置文件,让结构更清晰

    前言 接着上一篇的,这次框架的改变也成功分离了spring的配置文件. 以前,spring的配置文件从一开始的一点,到后面的逐渐变多,慢慢的,在一个spring的配置文件中就包含了好几块不同的bean ...

  8. Jquery Validation 验证控件的使用说明

    转载自:http://blog.csdn.net/huang100qi/article/details/52453970,做了一些简化及修改 下载地址:https://jqueryvalidation ...

  9. mysql数据库实操笔记20170418

    一.建立商品分类表和价格表: 1.分类表`sankeq``sankeq`CREATE TABLE cs_mysql11(id INT(11) NOT NULL AUTO_INCREMENT,categ ...

  10. 《算法4》读书笔记 1.4 - 算法分析(Analysis of Algorithm)

    --------------------------- First priority is to make you code ** CLEAR and CORRECT, but PERFORMANCE ...