免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3393 | 回复: 1
打印 上一主题 下一主题

html内容生成为word文档实现思路 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-12-13 17:01 |只看该作者 |倒序浏览
html内容生成为word文档实现思路











最近在做将HTML的内容转换成word文档,在处理html表格与图片的问题上还是花了一点心思。所以写这一篇文章将整个思路记录下来。

处理HTML标签我用的是Jsoup组件,生成word文档这方面我用的是Jacob组件。有兴趣的朋友可以去Google搜索一下这两个组件。大致思路如下:

先利用jsoup将得到的html代码“标准化”(Jsoup.parse(String html))方法,然后利用FileWiter将此html内容写到本地的template.doc文件中,此时如果文章中包含图片的话,template.doc就会依赖你的本地图片文件路径,如果你将图片更改一个名称或者将路径更改,再打开这个template.doc,图片就会显示不出来(出现一个叉叉)。为了解决此问题,利用jsoup组件循环遍历html文档的内容,将img元素替换成${image_自增值}的标识,取出img元素中的src属性,再以键值对的方式存储起来,例如:
  1. ?123 Map<Integer,String> imgMap = new HashMap<Integer,String>();   imgMap.put(1,”D:\\lucene.png”);
复制代码
此时你的html内容会变成如下格式:(举个示例)
  1. ?<html>     <head></head>     <body>                   <p>测试消息1</p>         <p>${image_1}<p>         <table>             <tr>                 <td> <td>             </tr>         </table>         <p>测试消息2</p>         <a href="http://www.google.com.hk"><p>${image_2}</p></a>         <p>测试消息3</p>     </body> </html>
复制代码
保存到本地文件以后,利用MSOfficeGeneratorUtils类(工具类详见下面,基于开源组件Jacob)打开你保存的这个template.doc,调用replaceText2Image,将上面代码的图片标识替换为图片,这样就消除了本地图片路径的问题。 然后再调用copy方法,复制整篇文档,关闭template.doc文件,新建一个doc文件(createDocument),调用 paste方法粘贴你刚复制的template.doc里的内容,保存。基本上就ok了。

关于copy整个word文档的内容,也会出现一个隐式问题。就是当复制的内容太多时,关闭word程序的时候,会谈出一个对话框,问你是否将复制的数据应用于其它的程序。对于这个问题解决方法很简单,你可以在调用 quit(退出word程序方法)之前,新建一篇文档,输入一行字,然后调用 copy方法,对于复制的数据比较少时,关闭word程序时,它不会提示你的。见如下代码

?123456 //复制一个内容比较少的*.doc文档,防止在关闭word程序时提示有大量的copy内容在内存中,是否应用于其它程序对话框, msOfficeUtils.createNewDocument(); msOfficeUtils.insertText("测试消息"); msOfficeUtils.copy(); msOfficeUtils.close(); msOfficeUtils.quit();
Jacob在sourceforge上的链接

Jsoup官网
  1. MsOfficeGeneratorUtils

  2. expand source?
  3. 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257 package com.topstar.test;   import java.io.File; import java.io.IOException; import java.util.List;   import com.jacob.activeX.ActiveXComponent; import com.jacob.com.ComThread; import com.jacob.com.Dispatch; import com.jacob.com.Variant;   /**  * 利用JACOB对Microsoft Office Word 进行相关操作  *   * @author xiaowu  * @category topstar  * @version 1.0  * @since 2011-12-5  */public class MSOfficeGeneratorUtils {       /**      * Microsoft Office Word 程序对象      */    private ActiveXComponent word = null;       /**      * Word 活动文档对象      */    private Dispatch document = null;       /**      * 所有 Word 文档对象      */    private Dispatch documents = null;       /**      * selection 代表当前活动文档窗口中的所选内容。如果文档中没有选中任何内容,则此对象代表插入点(即光标所在位置)。<br/>      * 每个文档窗口中只能存在一个selection对象,并且在整个应用程序中,只能存在一个活动的selection对象      */    private Dispatch selection = null;       /**      * range 对象代表文档中的一个连续的区域。每个range对象由一个起始字符位置与结束字符位置定义。<br/>      * range 对象独立于所选内容。你可以定义和处理一个范围而无需改变所选内容。还可以在文档中定义多个范围。但每个文档中只能有一个所选内容      */    private Dispatch range = null;       /**      * PageSetup 对象包含文档所有页面的设置属性(如纸张大小,左边距,下边距)      */    private Dispatch pageSetup = null;       /**      * 文档中的所有表格对象      */    private Dispatch tables = null;       /** 单个表格对象 */    private Dispatch table = null;       /** 表格所有行对象 */    private Dispatch rows = null;       /** 表格所有列对象 */    private Dispatch cols = null;       /** 表格指定行对象 */    private Dispatch row = null;       /** 表格指定列对象 */    private Dispatch col = null;       /** 表格中指定的单元格 */    private Dispatch cell = null;       /** 字体 */    private Dispatch font = null;       /** 对齐方式 */    private Dispatch alignment = null;       /**      * 构造方法      *       * @param visible      *            设置在生成word文档时,程序是否可见      */    public MSOfficeGeneratorUtils(boolean visible) {         if (this.word == null) {             // 初始化Microsoft Office Word 实例             this.word = new ActiveXComponent("Word.Application");             this.word.setProperty("Visible", new Variant(visible));             // 禁用宏             this.word.setProperty("AutomationSecurity", new Variant(3));         }         if (this.documents == null)             this.documents = word.getProperty("Documents").toDispatch();     }       /**      * 设置页面方向与页边距      *       * @param orientation      *            页面方向      *            <ul>      *            <li>0 横向</li>      *            <li>1 纵向</li>      *            </ul>      * @param leftMargin      *            左边距      * @param rightMargin      *            右边距      * @param topMargin      *            上边距      * @param buttomMargin      *            下边距      */    public void setPageSetup(int orientation, int leftMargin, int rightMargin,             int topMargin, int buttomMargin) {         if (this.pageSetup == null)             this.getPageSetup();         Dispatch.put(pageSetup, "Orientation", orientation);         Dispatch.put(pageSetup, "LeftMargin", leftMargin);         Dispatch.put(pageSetup, "RightMargin", rightMargin);         Dispatch.put(pageSetup, "TopMargin", topMargin);         Dispatch.put(pageSetup, "BottomMargin", buttomMargin);     }       /**      * 打开word文档      *       * @param docPath      *            word文档路径      * @return 打开的文档对象      */    public Dispatch openDocument(String docPath) {         this.document = Dispatch.call(documents, "Open", docPath).toDispatch();         this.getSelection();         this.getRange();         this.getAlignment();         this.getFont();         this.getPageSetup();         return this.document;     }       /**      * 创建一篇新文档      *       * @return 文档对象      */    public Dispatch createNewDocument() {         this.document = Dispatch.call(documents, "Add").toDispatch();         this.getSelection();         this.getRange();         this.getPageSetup();         this.getAlignment();         this.getFont();         return this.document;     }       /**      * 获取选定的内容或插入点      *       * @return selection      */    public Dispatch getSelection() {         this.selection = word.getProperty("Selection").toDispatch();         return this.selection;     }       /**      * 获取当前文档中可以修改的部分,前提是必须存在选中内容      *       * @return range      */    public Dispatch getRange() {         this.range = Dispatch.get(this.selection, "Range").toDispatch();         return this.range;     }       /**      * 获得当前文档的页面属性      */    public Dispatch getPageSetup() {         if (this.document == null)             return this.pageSetup;         this.pageSetup = Dispatch.get(this.document, "PageSetup").toDispatch();         return this.pageSetup;     }       /**      * 把选中内容或插入点向上移动      *       * @param count      *            移动的距离      */    public void moveUp(int count) {         for (int i = 0; i < count; i++)             Dispatch.call(this.selection, "MoveUp");     }       /**      * 把选中内容或插入点向下移动      *       * @param count      *            移动的距离      */    public void moveDown(int count) {         for (int i = 0; i < count; i++)             Dispatch.call(this.selection, "MoveDown");     }       /**      * 把选中内容或插入点向左移动      *       * @param count      *            移动的距离      */    public void moveLeft(int count) {         for (int i = 0; i < count; i++)             Dispatch.call(this.selection, "MoveLeft");     }       /**      * 把选中内容或插入点向右移动      *       * @param count      *            移动的距离      */    public void moveRight(int count) {         for (int i = 0; i < count; i++)             Dispatch.call(this.selection, "MoveRight");     }       /**      * 执行硬换行(回车键)      *       * @param count      *            换行数      */    public void enterDown(int count) {         for (int i = 0; i < count; i++)             Dispatch.call(this.selection, "TypeParagraph");     }       /**      * 把插入点移动到文件首位置      */    public void moveStart() {         Dispatch.call(this.selection, "HomeKey", new Variant(6));     }       /**      * 把插入点移动到文件末尾      */    public void moveEnd() {         Dispatch.call(selection, "EndKey", new Variant(6));     }                   /**      * 从选定内容或插入点开始查找文本      *       * @param toFindText      *            要查找的内容      * @return 查询到的内容并选中      */    public boolean find(String toFindText) {         // 从selection所在位置开始查询         Dispatch find = Dispatch.call(this.selection, "Find").toDispatch();         // 设置要查找的內容         Dispatch.put(find, "Text", toFindText);         // 向前查找         Dispatch.put(find, "Forward", "True");         // 设置格式         Dispatch.put(find, "Format", "True");         // 大小写匹配         Dispatch.put(find, "MatchCase", "True");         // 全字匹配         Dispatch.put(find, "MatchWholeWord", "True");         // 查找并选中         return Dispatch.call(find, "Execute").getBoolean();     }       /**      * 替换选定的内容      *       * @param newText      *            要替换的内容      */    public void replace(String newText) {         // 设置替换文本         Dispatch.put(this.selection, "Text", newText);     }       /**      * 全局替换      *       * @param oldText      *            要替换的内容      * @param replaceObj      *            被替换的内容      */    public void replaceAll(String oldText, Object replaceObj) {         // 将插入点移到文件开头         moveStart();         // 表格替换方式         String newText = (String) replaceObj;         // 图片替换方式         if (oldText.indexOf("image") != -1 || newText.lastIndexOf(".bmp") != -1 || newText.lastIndexOf(".jpg") != -1 || newText.lastIndexOf(".gif") != -1) {             while (find(oldText)) {                 insertImage(newText);                 Dispatch.call(this.selection, "MoveRight");             }             // 文本方式         } else {             while (find(oldText)) {                 replace(newText);                 Dispatch.call(this.selection, "MoveRight");             }         }     }           /**      * 将指定的内容替换成图片      * @param replaceText 指定的内容      * @param imgPath 图片路径      */    public void replaceText2Image(String replaceText,String imgPath){         moveStart();         while(find(replaceText)){             insertImage(imgPath);             moveEnd();             enterDown(1);         }     }     /**      * 向当前插入点替换图片      *       * @param imagePath      *            图片的路径      */    public void insertImage(String imagePath) {         Dispatch.call(Dispatch.get(selection, "InLineShapes").toDispatch(), "AddPicture", imagePath);     }       /**      * 合并单元格      *       * @param tableIndex      *            表格下标,从1开始      * @param fstCellRowIdx      *            开始行      * @param fstCellColIdx      *            开始列      * @param secCellRowIdx      *            结束行      * @param secCellColIdx      *            结束列      */    public void mergeCell(int tableIndex, int fstCellRowIdx, int fstCellColIdx,             int secCellRowIdx, int secCellColIdx) {         getTable(tableIndex);         Dispatch fstCell = Dispatch.call(table, "Cell",                 new Variant(fstCellRowIdx), new Variant(fstCellColIdx))                 .toDispatch();         Dispatch secCell = Dispatch.call(table, "Cell",                 new Variant(secCellRowIdx), new Variant(secCellColIdx))                 .toDispatch();         Dispatch.call(fstCell, "Merge", secCell);     }       /**      * 拆分当前单元格      *       * @param numRows      *            拆分的行数,如果不想拆分行,请指定为1      * @param numColumns      *            拆分的列数,如果不想拆分列,请指定为1      */    public void splitCell(int numRows, int numColumns) {         Dispatch.call(this.cell, "Split", new Variant(numRows), new Variant(                 numColumns));     }       /**      * 向表格中写入内容      *       * @param list      *            要写入的内容<br/>      *            注:list.size() 应该与表格的rows一致,String数组的length属性应与表格的columns一致      */    public void insertToTable(List<String[]> list) {         if (list == null || list.size() <= 0)             return;         if (this.table == null)             return;         for (int i = 0; i < list.size(); i++) {             String[] strs = list.get(i);             for (int j = 0; j < strs.length; j++) {                 // 遍历表格中每一個单元格,遍历次数所要填入的內容数量相同                 Dispatch cell = this.getCell(i + 1, j + 1);                 // 选中此单元格                 Dispatch.call(cell, "Select");                 // 写入內容到此单元格中                 Dispatch.put(this.selection, "Text", strs[j]);                 // 将插入点移动至下一個位置             }             this.moveDown(1);         }         // 换行         this.enterDown(1);     }       /**      * 向当前插入点插入文本内容      *       * @param list      *            要插入的内容,list.size()代表行数      */    public void insertToDocument(List<String> list) {         if (list == null || list.size() <= 0)             return;         if (this.document == null)             return;         for (String str : list) {             Dispatch.put(this.selection, "Text", str);             this.moveDown(1);             this.enterDown(1);         }     }       /**      * 在当前插入点插入文本      *       * @param insertText      *            要插入的文本      */    public void insertToText(String insertText) {         Dispatch.put(this.selection, "Text", insertText);     }       /**      * 在当前插入点插入字符串,利用此方法插入一行text后,Word会默认选中它,如果再调用此方法,会将原来的内容覆盖掉,所以调用此方法后,记得调用moveRight,将偏移量向右边移动一个位置 。      * @param newText 要插入的新字符串      */    public void insertText(String newText) {         Dispatch.put(selection, "Text", newText);     }       /**      * 创建新的表格      *       * @param rowCount      *            行      * @param colCount      *            列      * @param width      *            表格边框      *            <ul>      *            <li>0 无边框</li>      *            <li>1 有边框</li>      *            </ul>      * @return 表格对象      */    public Dispatch createNewTable(int rowCount, int colCount, int width) {         if (this.tables == null)             this.getTables();         this.getRange();         if (rowCount > 0 && colCount > 0)             this.table = Dispatch.call(this.tables, "Add", this.range,                     new Variant(rowCount), new Variant(colCount),                     new Variant(width)).toDispatch();         return this.table;     }       /**      * 获取当前document对象中的所有表格对象      *       * @return tables      */    public Dispatch getTables() {         if (this.document == null)         
复制代码

论坛徽章:
0
2 [报告]
发表于 2011-12-20 16:43 |只看该作者
思路清晰  排版受不鸟
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP