• 12、借助Jacob实现Java打印报表(Excel、Word)


    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%jrein目录下,其中,%JAVA_HOME%就是JDK的安装目录。注意这个的jre目录必须是Eclipse当前正在使用的目录,在Eclipse中选择“window->Preferences”菜单,在弹出的对话框中选择“Java->Installed JREs”项。

      (3) 当前选择的JRE是“C:Program FilesJavajdk1.5.0_07jre”目录下的,所以需要把jacob.dll复制到“C:Program FilesJavajdk1.5.0_07jrein”目录下面。

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

    注意:在使用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  }

     

  • 相关阅读:
    Stack堆栈的数据结构
    反坦克导弹相关网页
    Java 执行jar文件出现版本错误信息
    Python3 数字保留后几位
    Python3: Windows系统上同时安装Python2和Python3
    Linux 搭建FTP
    DBCP、c3p0、Druid三大连接池区别
    Sybase 存储过程中IF的用法
    Confluence5.8部分空间名称显示为问号的解决方案
    Mysql 更改编码方式
  • 原文地址:https://www.cnblogs.com/hthuang/p/3481027.html
Copyright © 2020-2023  润新知