花了两天时间,参考了一些资料,总算是处理好了这样一个技术点。

关键的心得如下:

使用jacob,重点不是jacob本身,而是office的一些API资料。比如需要知道光标的移动, 包括上下左右的move(MoveUp, MoveDown,MoveLeft, MoveRight),包括回到首页起点Dispatch.put(selection, "Start", 0)等等。

严格的说,这边并没有很系统化的去了解jacob的底层。但对于一些关键点,还是可以拿出来分享的。比如插入一张图片之后,系统可以拿到一个Dispatch对象(例如叫做obj),我们则需要调用Dispatch.call(obj,"select"),这样相当于使用鼠标在word选中了新插入的图片,而后我们就可以通过Dispatch得到图片的ShapeRange,进而得到ShapeRange的WrapFormat,再对WrapFormat进行设定。对应的结构可以归纳为:Image->ShapeRange->WrapFormat。但是要想知道WrapFormat对应到的是哪些值,且有哪些作用,则需要去查询MSDN。这边查询到的相关值如下:

wdWrapInline 7 将形状嵌入到文字中。
wdWrapNone 3 将形状放在文字前面。请参阅 wdWrapFront 。
wdWrapSquare 0 使文字环绕形状。行在形状的另一侧延续。
wdWrapThrough 2 使文字环绕形状。
wdWrapTight 1 使文字紧密地环绕形状。
wdWrapTopBottom 4 将文字放在形状的上方和下方。
wdWrapBehind 5 将形状放在文字后面。
wdWrapFront 6 将形状放在文字前面。

这种匈牙利命名法的变量名,其实都对应到一个整型数据(应该是一个常量型的变量)。比如这次代码中需要用到的将印章图片盖在文字的前面,对应到得变量是wdWrapFront,也就是数值6.

再有就是要知道传入的word文件共有几页,加印的话,应该是每一页都要盖章的,于是就需要通过Dispatch.call(cursor,"information",4)来获取,此时cursor(光标)可能是需要回到word首页的开始位置(还未测试)。然后的思路就是要将光标指定到某个位置并以在文字前面的方式插入印章图片,实现的方式是:光标遍历到每一页的开始位置,并在此基础上移动到当前页的显眼位置。在开发过程中,将光标移动到每一页的开始位置,是花了相当的时间的。MSDN上并没有给出很直观的例子,甚至还找到了此功能无法实现的文章。直到找到了一篇名为“delphi读取WORD文档每一页的内容”的帖子,并注意到里面使用的

  //定位到第i页
      PageRange := wordapp.Selection.GoTo(wdGoToPage, wdGoToNext, IntToStr(i)); //<---->再一次匈牙利命名法的变量

这种不太一样的写法正是对应到了

  Dispatch.invoke(this.cursor, "Goto", Dispatch.Method, new Object[] {1, 2, String.valueOf(index)}, new int[1]);//<---->匈牙利命名法的变量对应到的整型常量,参考语句出处

以下是完整的Java代码,要正确使用的话,需要将jacob的jar包放进工程,并在运行环境中加入jacob.dll。

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

 public class WordInsertPicture {

  public WordInsertPicture() {
  }

  // 声明一个静态的类实例化对象
  private static WordInsertPicture instance;
  // 声明word文档对象
  private Dispatch doc = null;
  // 声明word文档当前活动视窗对象
  private Dispatch activeWindow = null;
  // 声明word文档选定区域或插入点对象
  private Dispatch docSelection = null;
  // 声明所有word文档集合对象
  private Dispatch wrdDocs = null;
  // 声明word文档名称对象
  private String fileName;
  // 声明ActiveX组件对象:word.Application,Excel.Application,Powerpoint.Application等等
  private ActiveXComponent wrdCom;

  /**
   * 获取Word操作静态实例对象
   *
   * @return 报表汇总业务操作
   */
  public final static synchronized WordInsertPicture getInstance() {
   if (instance == null)
    instance = new WordInsertPicture();
   return instance;
  }

  /**
   * 初始化Word对象
   *
   * @return 是否初始化成功
   */
  public boolean initWordObj() {
   boolean retFlag = false;
   ComThread.InitSTA();// 初始化com的线程,非常重要!!使用结束后要调用 realease方法
   wrdCom = new ActiveXComponent("Word.Application");// 实例化ActiveX组件对象:对word进行操作
   try {
    /*
     * 返回wrdCom.Documents的Dispatch
     * 获取Dispatch的Documents对象,可以把每个Dispatch对象看成是对Activex控件的一个操作
     * 这一步是获得该ActiveX控件的控制权。
     */
    wrdDocs = wrdCom.getProperty("Documents").toDispatch();
    // 设置打开的word应用程序是否可见
    wrdCom.setProperty("Visible", new Variant(false));
    retFlag = true;
   } catch (Exception e) {
    retFlag = false;
    e.printStackTrace();
   }
   return retFlag;
  }

  /**
   * 创建一个新的word文档
   *
   */
  public void createNewDocument() {
   // 创建一个新的文档
   doc = Dispatch.call(wrdDocs, "Add").toDispatch();
   // 获得当前word文档文本
   docSelection = Dispatch.get(wrdCom, "Selection").toDispatch();
  }

  /**
   * 取得活动窗体对象
   *
   */
  public void getActiveWindow() {
   // 获得活动窗体对象
   activeWindow = wrdCom.getProperty("ActiveWindow").toDispatch();
  }

  /**
   * 打开一个已存在的文档
   *
   * @param docPath
   */
  public void openDocument(String docPath) {
   if (this.doc != null) {
    this.closeDocument();
   }
   this.doc = Dispatch.call(wrdDocs, "Open", docPath).toDispatch();
   this.docSelection = Dispatch.get(wrdCom, "Selection").toDispatch();
  }

  /**
   * 关闭当前word文档
   *
   */
  public void closeDocument() {
   if (this.doc != null) {
    Dispatch.call(this.doc, "Save");
    Dispatch.call(this.doc, "Close", new Variant(true));
    this.doc = null;
   }
  }
   /**
   * 文档设置图片水印
   *
   * @param waterMarkPath
   *            水印路径  */
  public void setWaterMark(String waterMarkPath) {
   // 取得活动窗格对象
   Dispatch activePan = Dispatch.get(this.activeWindow, "ActivePane")
     .toDispatch();
   // 取得视窗对象
   Dispatch view = Dispatch.get(activePan, "View").toDispatch();
   // 打开页眉,值为9,页脚为10
   Dispatch.put(view, "SeekView", new Variant(9));
   //获取页眉和页脚
   Dispatch headfooter = Dispatch.get(this.docSelection, "HeaderFooter")
     .toDispatch();
   // 获取水印图形对象
   Dispatch shapes = Dispatch.get(headfooter, "Shapes").toDispatch();
   // 给文档全部加上水印,设置了水印效果,内容,字体,大小,是否加粗,是否斜体,左边距,上边距。
     //调用shapes对象的AddPicture方法将全路径为picname的图片插入当前文档
      Dispatch picture = Dispatch.call(shapes, "AddPicture", waterMarkPath).toDispatch();
   //选择当前word文档的水印
   Dispatch.call(picture, "Select");
   Dispatch.put(picture, "Left", new Variant(0));
   Dispatch.put(picture, "Top", new Variant(150));
   Dispatch.put(picture, "Width", new Variant(150));
   Dispatch.put(picture, "Height", new Variant(80));

  //关闭页眉
   Dispatch.put(view, "SeekView", new Variant(0));
  }

  /**
   * 关闭Word资源
   *
   *
   */
  public void closeWordObj() {
   // 关闭word文件
   wrdCom.invoke("Quit", new Variant[] {});
   // 释放com线程。根据jacob的帮助文档,com的线程回收不由java的垃圾回收器处理
   ComThread.Release();
  }

  /**
   * 得到文件名
   *
   * @return .
   */
  public String getFileName() {
   return fileName;
  }

  /**
   * 设置文件名
   *
   * @param fileName .
   */
  public void setFileName(String fileName) {
   this.fileName = fileName;
  }

  /**
   * 开始为word文档添加水印
   *
   * @param wordPath
   *            word文档的路径
   * @param waterMarkPath
   *            添加的水印图片路径
   * @return 是否成功添加
   */
  public boolean addWaterMark(String wordPath, String waterMarkPath) {
   try {
    if (initWordObj()) {
     openDocument(wordPath);
     getActiveWindow();
     setWaterMark(waterMarkPath);
     closeDocument();
     closeWordObj();
     return true;

    } else
     return false;
   } catch (Exception e) {
       e.printStackTrace();
       closeDocument();
       closeWordObj();
       return false;
   }
  }

  public boolean insertImage(String wordPath,String imagePath)
  {
       try {
            if (initWordObj()) {
             openDocument(wordPath);
             getActiveWindow();
             // 用于指定位置MoveRight以及MoveDown
             Dispatch selection = Dispatch.get(wrdCom, "Selection").toDispatch();
             for(int i = 0; i < 10; i++){
                 Dispatch.call(selection, "MoveRight");
             }
             for(int i = 0; i < 10; i++){
                 Dispatch.call(selection, "MoveDown");
             }
             Dispatch image = Dispatch.get(selection, "InlineShapes").toDispatch();
             Dispatch dv = Dispatch.call(image, "AddPicture", imagePath).toDispatch();
             Dispatch.call(dv, "Select");

             //Dispatch Left = Dispatch.get(position, "Left").toDispatch();
             selection = Dispatch.get(wrdCom, "Selection").toDispatch();
             Dispatch shaperange   = Dispatch.get(selection, "ShapeRange").toDispatch();
             Dispatch wf = Dispatch.get(shaperange, "WrapFormat").toDispatch();
             Dispatch.put(wf, "Type", "6");
             int pcnt = Integer.parseInt(Dispatch.call(selection,"information",4).toString());
             for(int p = 1; p < pcnt; p++){
                 Dispatch.invoke(selection, "Goto", Dispatch.Method, new Object[] {1, 2, String.valueOf(p)}, new int[1]);
                 for(int i = 0; i < 10; i++){
                     Dispatch.call(selection, "MoveRight");
                 }
                 for(int i = 0; i < 10; i++){
                     Dispatch.call(selection, "MoveDown");
                 }
                 Dispatch imagef = Dispatch.get(selection, "InlineShapes").toDispatch();
                 Dispatch dvf = Dispatch.call(imagef, "AddPicture", imagePath).toDispatch();
                 Dispatch.call(dvf, "Select");

                 //Dispatch Left = Dispatch.get(position, "Left").toDispatch();
                 selection = Dispatch.get(wrdCom, "Selection").toDispatch();
                 Dispatch shaperangef   = Dispatch.get(selection, "ShapeRange").toDispatch();
                 Dispatch wff = Dispatch.get(shaperangef, "WrapFormat").toDispatch();
                 Dispatch.put(wff, "Type", "6");

                 Dispatch.put(selection, "Start", 0); // 回到页首
             }

             closeDocument();
             closeWordObj();
             return true;
            } else
             return false;
           } catch (Exception e) {
               e.printStackTrace();
               closeDocument();
               closeWordObj();
               return false;
           }
  }

  /**
   * 测试功能
   *
   */
  public static void main(String[] argv) {
   WordInsertPicture wordObj = WordInsertPicture.getInstance();
 //System.out.println(wordObj.getDocPages());
   wordObj.insertImage("e://1//Adf.docx", "e://1//watermark.png");
   //watermark.png");
  }
 }

jacob 给word加印的功能的更多相关文章

  1. Java文件操作系列[3]——使用jacob操作word文档

    Java对word文档的操作需要通过第三方组件实现,例如jacob.iText.POI和java2word等.jacob组件的功能最强大,可以操作word,Excel等格式的文件.该组件调用的的是操作 ...

  2. Excel与Word套打功能使用技巧及EXCEL数据处理成绩

    Excel与Word套打功能使用技巧 婚礼邀请友人参加,就需要写请柬.而且写请柬不但要求字写得端正,还不能有错别字,再加上邀请的朋友多,写请柬就是一个劳累活.这时我们利用Word的套打功能,就会让写请 ...

  3. jacob 操作word转pdf

    项目需要对上传的word及pdf进行在线预览,因基于jquery的pdf插件,很方面实现在线预览,而word实现在线预览费劲不少,于是想到在进行上传处理时,直接将word转成pdf,在预览时直接预览p ...

  4. 【文件】使用jacob将word转换成pdf格式

    使用jacob将word转换成pdf格式   1.需要安装word2007或以上版本,若安装07版本学确保该版本已安装2downbank0204MicrosoftSaveasPDF_ XPS,否则安装 ...

  5. ckeditor粘贴word图片自动上传功能

    由于工作需要必须将word文档内容粘贴到编辑器中使用 但发现word中的图片粘贴后变成了file:///xxxx.jpg这种内容,如果上传到服务器后其他人也访问不了,网上找了很多编辑器发现没有一个能直 ...

  6. MindManager导出Word文档功能介绍

    Mindmanager思维导图软件作为一款能与Microsoft office软件无缝集成的思维导图软件,支持Word文档的快速导入与导出,并支持Word文档的目录生成.模板套用等,极大地方便了用户完 ...

  7. jacob 操作word

    1. 首先下载jacob-1.18.zip,解压后有两个文件jacob.jar 和 jacob.dll.需要把jacob.jar放到你工程的classpath中并且把jacob.dll放到jdk的bi ...

  8. 使用Jacob与Word文件交互

    转自:http://www.blogjava.net/lonsy/archive/2009/01/09/250713.html Jacob项目的官方地址: Http://sourceforge.net ...

  9. Java使用Jacob转换Word为HTML

    从今天开始,我也要养成记录开发中遇到的问题和解决方法的好习惯! 最近开发一个Android项目,需要用到查看Word和Pdf文档的功能,由于Android没有直接显示Word和PDF文档的组件,只有一 ...

随机推荐

  1. HTML目录

    1. 表格标记 2. HTML常用标记 3. 博客园添加访问人数统计 4. 如何快速掌握CSS(各种CSS工具) 5. HTTP协议状态码详解(HTTP Status Code)(转)

  2. Qt 类外调用一个 private slots 函数

    MainWindow中 private slots 函数 void print_on_log(QString strtemp);输出一个字符串到编辑窗口中 class MainWindow:publi ...

  3. JavaScript组成

    JavaScript由ECMAScript,Dom,Bom三部分组成. ECMAScript是一种由Ecma国际(前身为欧洲计算机制造商协会,英文名称是European Computer Manufa ...

  4. NSBlockOperation添加多个任务

    //创建一个队列 NSOperationQueue *operation=[[NSOperationQueue alloc]init]; //把任务放在NSBlockOperation里面 NSBlo ...

  5. Oracle基础 exp/imp和expdp/impdp的区别:

    一.exp/imp和expdp/impdp在功能上的区别: 1.把用户usera的对象导入到userb emp/imp用法: formuser=usera touser=userb; empdp/im ...

  6. Oracle 基础——索引

    一.索引 索引是一种快速访问数据的途径,可提高数据库性能.索引使数据库程序无须对整个表进行扫描,就可以在其中找到所需的数据,就像书的目录,可以快速查找所需的信息,无须阅读整本书. 二.索引存在的问题 ...

  7. Oracle数据库查看执行计划

    基于ORACLE的应用系统很多性能问题,是由应用系统SQL性能低劣引起的,所以,SQL的性能优化很重要,分析与优化SQL的性能我们一般通过查看该SQL的执行计划,本文就如何看懂执行计划,以及如何通过分 ...

  8. Spring Data Jpa 详解 (配置篇)

    前言: JPA全称Java Persistence API,即Java持久化API,它为Java开发人员提供了一种对象/关系映射工具来管理Java应用中的关系数据,结合其他ORM的使用,能达到简化开发 ...

  9. HDU 2084 数塔 (DP)

    数塔 Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Pr ...

  10. CentOS安装VMware Tools

    新建cdrom挂载目录 mkdir /mnt/cdrom 挂载光驱 mount -t auto /dev/cdrom /mnt/cdrom这命令就是把CentOS CDROM挂载在/mnt/cdrom ...