精华内容
下载资源
问答
  • poi操作word文档总结

    万次阅读 2014-06-05 17:18:43
    POI分段落生成纯Word动态模板并导入数据 导出数据,可以用word另存为xml格式的ftl文件,变量用${变量名}表示,然后在类中通过 freemarker去替换变量。...后来找到方法可以分段落读入纯word文档。要找到了word基

    POI分段落生成纯Word动态模板并导入数据


    导出数据,可以用word另存为xml格式的ftl文件,变量用${变量名}表示,然后在类中通过

    freemarker去替换变量。

    但是怎么导入word数据。发现如果是xml格式,数据格式很易变。如一个标题中如果有中文,

    后面是个数字,另存成xml时就变成了2个元素了。太郁闷了。

    后来找到方法可以分段落读入纯word文档。要找到了word基于模板替换的相关例子。于是方

    案如下。

    纯word文件变量用${变量名}表示。导出动态模板时,把业务数据替换变量。导入是分段落读入数据。

    注意模板中的KEY最好在文本中写好,然后复制到模板中。
    否则可以出现解析问题(比如:${user}代码写解析成三段文本1.${  2.user  3.})

     

    POIReportUtil.java文件
    package com.sunrise.wbmp.manage.project.report.util;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.util.*;
    import org.apache.poi.hwpf.HWPFDocument;
    import org.apache.poi.hwpf.model.StyleDescription;
    import org.apache.poi.hwpf.model.StyleSheet;
    import org.apache.poi.hwpf.usermodel.CharacterProperties;
    import org.apache.poi.hwpf.usermodel.Paragraph;
    import org.apache.poi.hwpf.usermodel.Range;
    import org.apache.poi.hwpf.usermodel.Table;
    import org.apache.poi.hwpf.usermodel.TableCell;
    import org.apache.poi.hwpf.usermodel.TableIterator;
    import org.apache.poi.hwpf.usermodel.TableRow;


    public class POIReportUtil {
        public static void main(String[] args) throws Exception {
            Map<String, POIText> replaces = new HashMap<String, POIText>();
            System.out.println("导出数据:");
           
            replaces.put("${projectName}", POIText.str("CMMI"));       
            replaces.put("${graph1}", POIText.str("rongzhi_li"));
            replaces.put("${内容1}", POIText.str("1123456"));

            replaces.put("${graph2}", POIText.str("graph"));
            replaces.put("${内容2}", POIText.str("2222"));

            replaces.put("${graph3}", POIText.str("graph"));
            replaces.put("${内容3}", POIText.str("33333"));

            replaces.put("${graph4}", POIText.str("<END>"));
            replaces.put("${内容4}", POIText.str(""));
           
            for (int i=5;i<10;i++){
                replaces.put("${graph"+i+"}", POIText.str(""));
                replaces.put("${内容"+i+"}", POIText.str(""));
            }

        // 读入模板文件并替换参数 
        HWPFDocument hwpf=poiWordTableReplace

    ("E:\\temp\\template\\templateTest.doc",replaces);

        // 另存模板文件为exportTestg.doc
        FileOutputStream out = new FileOutputStream("E:\\temp\\template\\exportTestg.doc");
        hwpf.write(out);
        out.flush();
        out.close(); 
       
        // 把exportTestg.doc文件内容读出来
        System.out.println("读入数据:");
        FileInputStream in = new FileInputStream("E:\\temp\\template\\exportTestg.doc");
        HWPFDocument hwpf2 = new HWPFDocument(in);
        Map<String,String> map=readWord(hwpf2);   
        for (Iterator iter=map.entrySet().iterator();iter.hasNext();){
        java.util.Map.Entry entry=(java.util.Map.Entry)iter.next();
        System.out.println(entry.getKey()+":"+entry.getValue());
        }
        }


        // 读取文件内容反回MAP
        public static Map<String,String> readWord(HWPFDocument hwpf
                ) throws Exception {
    //        FileInputStream in = new FileInputStream(sourceFile);
    //        HWPFDocument hwpf = new HWPFDocument(in);
        Map<String, String> oldMap=new HashMap<String, String>();
            Range r = hwpf.getRange();
            List<String> list = new ArrayList<String>();
            for (int i = 0; i < r.numParagraphs(); i++) {
                Paragraph p = r.getParagraph(i);
                // check if style index is greater than total number of styles
                int numStyles =hwpf.getStyleSheet().numStyles();
                int styleIndex = p.getStyleIndex();
                if (numStyles > styleIndex) {
                    StyleSheet style_sheet = hwpf.getStyleSheet();
                    StyleDescription style = style_sheet.getStyleDescription(styleIndex);
                    String styleName = style.getName();
                    if (styleName!=null&&styleName.contains("标题 3")) {
                        // write style name and associated text
                        System.out.println(styleName + " -> " + p.text());
                        //System.out.println(p.text());
                        String text = p.text();
                        text=text.substring(0,text.length()-1);
                        list.add(text);
                        oldMap.put(text, null);
                        if ("<END>".equals(text)){
                        break;
                        }
                    }else{
                    if (list.size()>0){
                    String key=list.get(list.size()-1);
                    String oldS=oldMap.get(list.get(list.size()-1));
                    String s=( p.text()==null)?"": p.text();
                    oldS=(oldS==null)?s:(oldS+s);
                    if (oldS!=null && oldS.trim().length()>0){
                    oldMap.put(key, oldS);
                    }
                    }
                    }
                }
            }
            return oldMap;
        }   


        public static HWPFDocument poiWordTableReplace(String sourceFile,
                Map<String, POIText> replaces) throws Exception {
            FileInputStream in = new FileInputStream(sourceFile);
            HWPFDocument hwpf = new HWPFDocument(in);
    //        Range range = hwpf.getRange();// 得到文档的读取范围
    //        TableIterator it = new TableIterator(range);
    //        // 迭代文档中的表格
    //        while (it.hasNext()) {
    //            Table tb = (Table) it.next();
    //            // 迭代行,默认从0开始
    //            for (int i = 0; i < tb.numRows(); i++) {
    //                TableRow tr = tb.getRow(i);
    //                // 迭代列,默认从0开始
    //                for (int j = 0; j < tr.numCells(); j++) {
    //                    TableCell td = tr.getCell(j);// 取得单元格
    //                    // 取得单元格的内容
    //                    for (int k = 0; k < td.numParagraphs(); k++) {
    //                        Paragraph para = td.getParagraph(k);
    //
    //                        String s = para.text();
    //                        final String old = s;
    //                        for (String key : replaces.keySet()) {
    //                            if (s.contains(key)) {
    //                                s = s.replace(key, replaces.get(key).getText());
    //                            }
    //                        }
    //                        if (!old.equals(s)) {// 有变化
    //                            para.replaceText(old, s);
    //                            s = para.text();
    //                            System.out.println("old:" + old + "->" + "s:" + s);
    //                        }
    //
    //                    } // end for
    //                } // end for
    //            } // end for
    //        } // end while


            Range r = hwpf.getRange();
            CharacterProperties props = new CharacterProperties();
            props.setFontSize(10);
           
            List<String> list = new ArrayList<String>();
            for (int i = 0; i < r.numParagraphs(); i++) {
                Paragraph p = r.getParagraph(i);
                // check if style index is greater than total number of styles
                int numStyles =hwpf.getStyleSheet().numStyles();
                int styleIndex = p.getStyleIndex();
                if (numStyles > styleIndex) {
                    StyleSheet style_sheet = hwpf.getStyleSheet();
                    StyleDescription style = style_sheet.getStyleDescription(styleIndex);
                    String styleName = style.getName();
    //                if (styleName!=null&&styleName.contains("标题")) {
    //                    // write style name and associated text
    //                    //System.out.println(styleName + " -> " + p.text());
    //                    System.out.println(p.text());
    //                    String text = p.text();
    //                    list.add(text);
    //                }else{
    //                    System.out.println(  p.text());
    //                }
                   
                    System.out.println(  styleName);
                   
                    String s = p.text();
                    final String old = s;
                    for (String key : replaces.keySet()) {
                        if (s.contains(key)) {
                            s = s.replace(key, replaces.get(key).getText());
                        }
                    }
                    if (!old.equals(s)) {// 有变化
                        p.replaceText(old, s);
                        s = p.text();
                        System.out.println("old:" + old + "->" + "s:" + s);
                    }
                }
            }
            return hwpf;
        }
    }

     

    POIReportUtil.java文件
    package com.sunrise.wbmp.manage.project.report.util;


    public abstract class POIText {


        public abstract String getText();


        public static POIText str(final String string) {
            return new POIText() {
                @Override
                public String getText() {
                    return string;
                }
            };
        }
    }

     


    利用poi操作word文档


    一:利用POI提取Word文本内容及批注
    97-2003:

    import org.apache.poi.POITextExtractor;
    import org.apache.poi.hwpf.extractor.WordExtractor;
    //得到.doc文件提取器
    org.apache.poi.hwpf.extractor.WordExtractor doc = new WordExtractor(new

    FileInputStream(filePath));
    //提取.doc正文文本
    String text = doc.getText();
    //提取.doc批注
    String[] comments = doc. getCommentsText();

    2007

    import org.apache.poi.POITextExtractor;
    import org.apache.poi.xwpf.extractor.XWPFWordExtractor;
    import org.apache.poi.xwpf.usermodel.XWPFComment;
    import org.apache.poi.xwpf.usermodel.XWPFDocument;
    //得到.docx文件提取器
    org.apache.poi.xwpf.extractor.XWPFWordExtractor docx = new XWPFWordExtractor

    (POIXMLDocument.openPackage(filePath));
    //提取.docx正文文本
    String text = docx.getText();
    //提取.docx批注
    org.apache.poi.xwpf.usermodel.XWPFComment[] comments = docx.getDocument

    ()).getComments();
    for(XWPFComment comment:comments){
    comment.getId();//提取批注Id
    comment.getAuthor();//提取批注修改人
    comment.getText();//提取批注内容
    }

    二:利用POI提取Word总页数、总字符数...
    97-2003
    WordExtractor doc = new WordExtractor(new FileInputStream(filePath));//.doc格式Word文

    件提取器
    int pages = doc.getSummaryInformation().getPageCount();//总页数
    int wordCount = doc.getSummaryInformation().getWordCount();//总字符数
    2007:

    XWPFDocument docx = nnew XWPFDocument(POIXMLDocument.openPackage(filePath));
    int pages = docx.getProperties().getExtendedProperties().getUnderlyingProperties

    ().getPages();//总页数
    int characters = docx.getProperties().getExtendedProperties().getUnderlyingProperties

    ().getCharacters();// 忽略空格的总字符数 另外还有getCharactersWithSpaces()方法获取带空

    格的总字数。


    小技巧:
    2007采用了全新的OFFICE OPEN XML格式来存储,跟以前二进制文件格式的office 97-2003

    (.doc、.xls...)不同,所以可以直接重命名xx.docx的文件为xx.zip,用WinRar打开可以看到

    office2007的存储文件,其中word/document.xml里面保存了最重要的正文内容,

    word/comments.xml保存的是批注内容,可以多研究一下这些文件,有助于开发~



    POI word模板 文字 图片替换


    Word模板:


    替换后效果:

     

    代码:
    1、入口文件
    public class Test { 
         
        public static void main(String[] args) throws Exception { 
             
            Map<String, Object> param = new HashMap<String, Object>(); 
            param.put("${name}", "huangqiqing"); 
            param.put("${zhuanye}", "信息管理与信息系统"); 
            param.put("${sex}", "男"); 
            param.put("${school_name}", "山东财经大学"); 
            param.put("${date}", new Date().toString()); 
             
            Map<String,Object> header = new HashMap<String, Object>(); 
            header.put("width", 100); 
            header.put("height", 150); 
            header.put("type", "jpg"); 
            header.put("content", WordUtil.inputStream2ByteArray(new FileInputStream

    ("c:\\new.jpg"), true)); 
            param.put("${header}",header); 
             
    Map<String,Object> twocode = new HashMap<String, Object>(); 
            twocode.put("width", 100); 
            twocode.put("height", 100); 
            twocode.put("type", "png"); 
            twocode.put("content", ZxingEncoderHandler.getTwoCodeByteArray("测试二维

    码,huangqiqing", 100,100)); 
            param.put("${twocode}",twocode); 
             
            CustomXWPFDocument doc = WordUtil.generateWord(param, "c:\\1.docx"); 
            FileOutputStream fopts = new FileOutputStream("c:/2.docx"); 
            doc.write(fopts); 
            fopts.close(); 
        } 

    2、封装的工具类WordUtil.java
    import java.io.ByteArrayInputStream; 
    import java.io.IOException; 
    import java.io.InputStream; 
    import java.util.Iterator; 
    import java.util.List; 
    import java.util.Map; 
    import java.util.Map.Entry; 
    import org.apache.poi.POIXMLDocument; 
    import org.apache.poi.openxml4j.opc.OPCPackage; 
    import org.apache.poi.xwpf.usermodel.XWPFParagraph; 
    import org.apache.poi.xwpf.usermodel.XWPFRun; 
    import org.apache.poi.xwpf.usermodel.XWPFTable; 
    import org.apache.poi.xwpf.usermodel.XWPFTableCell; 
    import org.apache.poi.xwpf.usermodel.XWPFTableRow; 
     
    /**
    * 适用于word 2007
    * poi 版本 3.7
    */ 
    public class WordUtil { 
     
        /**
         * 根据指定的参数值、模板,生成 word 文档
         * @param param 需要替换的变量
         * @param template 模板
         */ 
        public static CustomXWPFDocument generateWord(Map<String, Object> param, String

    template) { 
            CustomXWPFDocument doc = null; 
            try { 
                OPCPackage pack = POIXMLDocument.openPackage(template); 
                doc = new CustomXWPFDocument(pack); 
                if (param != null && param.size() > 0) { 
                     
                    //处理段落 
                    List<XWPFParagraph> paragraphList = doc.getParagraphs(); 
                    processParagraphs(paragraphList, param, doc); 
                     
                    //处理表格 
                    Iterator<XWPFTable> it = doc.getTablesIterator(); 
                    while (it.hasNext()) { 
                        XWPFTable table = it.next(); 
                        List<XWPFTableRow> rows = table.getRows(); 
                        for (XWPFTableRow row : rows) { 
                            List<XWPFTableCell> cells = row.getTableCells(); 
                            for (XWPFTableCell cell : cells) { 
                                List<XWPFParagraph> paragraphListTable =  cell.getParagraphs(); 
                                processParagraphs(paragraphListTable, param, doc); 
                            } 
                        } 
                    } 
                } 
            } catch (Exception e) { 
                e.printStackTrace(); 
            } 
            return doc; 
        } 
        /**
         * 处理段落
         * @param paragraphList
         */ 
        public static void processParagraphs(List<XWPFParagraph> paragraphList,Map<String,

    Object> param,CustomXWPFDocument doc){ 
            if(paragraphList != null && paragraphList.size() > 0){ 
                for(XWPFParagraph paragraph:paragraphList){ 
                    List<XWPFRun> runs = paragraph.getRuns(); 
                    for (XWPFRun run : runs) { 
                        String text = run.getText(0); 
                        if(text != null){ 
                            boolean isSetText = false; 
                            for (Entry<String, Object> entry : param.entrySet()) { 
                                String key = entry.getKey(); 
                                if(text.indexOf(key) != -1){ 
                                    isSetText = true; 
                                    Object value = entry.getValue(); 
                                    if (value instanceof String) {//文本替换 
                                        text = text.replace(key, value.toString()); 
                                    } else if (value instanceof Map) {//图片替换 
                                        text = text.replace(key, ""); 
                                        Map pic = (Map)value; 
                                        int width = Integer.parseInt(pic.get("width").toString()); 
                                        int height = Integer.parseInt(pic.get("height").toString()); 
                                        int picType = getPictureType(pic.get("type").toString()); 
                                        byte[] byteArray = (byte[]) pic.get("content"); 
                                        ByteArrayInputStream byteInputStream = new

    ByteArrayInputStream(byteArray); 
                                        try { 
                                            int ind = doc.addPicture(byteInputStream,picType); 
                                            doc.createPicture(ind, width , height,paragraph); 
                                        } catch (Exception e) { 
                                            e.printStackTrace(); 
                                        } 
                                    } 
                                } 
                            } 
                            if(isSetText){ 
                                run.setText(text,0); 
                            } 
                        } 
                    } 
                } 
            } 
        } 
        /**
         * 根据图片类型,取得对应的图片类型代码
         * @param picType
         * @return int
         */ 
        private static int getPictureType(String picType){ 
            int res = CustomXWPFDocument.PICTURE_TYPE_PICT; 
            if(picType != null){ 
                if(picType.equalsIgnoreCase("png")){ 
                    res = CustomXWPFDocument.PICTURE_TYPE_PNG; 
                }else if(picType.equalsIgnoreCase("dib")){ 
                    res = CustomXWPFDocument.PICTURE_TYPE_DIB; 
                }else if(picType.equalsIgnoreCase("emf")){ 
                    res = CustomXWPFDocument.PICTURE_TYPE_EMF; 
                }else if(picType.equalsIgnoreCase("jpg") || picType.equalsIgnoreCase("jpeg")){ 
                    res = CustomXWPFDocument.PICTURE_TYPE_JPEG; 
                }else if(picType.equalsIgnoreCase("wmf")){ 
                    res = CustomXWPFDocument.PICTURE_TYPE_WMF; 
                } 
            } 
            return res; 
        } 
        /**
         * 将输入流中的数据写入字节数组
         * @param in
         * @return
         */ 
        public static byte[] inputStream2ByteArray(InputStream in,boolean isClose){ 
            byte[] byteArray = null; 
            try { 
                int total = in.available(); 
                byteArray = new byte[total]; 
                in.read(byteArray); 
            } catch (IOException e) { 
                e.printStackTrace(); 
            }finally{ 
                if(isClose){ 
                    try { 
                        in.close(); 
                    } catch (Exception e2) { 
                        System.out.println("关闭流失败"); 
                    } 
                } 
            } 
            return byteArray; 
        } 
    }  

     

    3、重写的类 CustomXWPFDocument
       
    import java.io.IOException; 
    import java.io.InputStream; 
    import org.apache.poi.openxml4j.opc.OPCPackage; 
    import org.apache.poi.xwpf.usermodel.XWPFDocument; 
    import org.apache.poi.xwpf.usermodel.XWPFParagraph; 
    import org.apache.xmlbeans.XmlException; 
    import org.apache.xmlbeans.XmlToken; 
    import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps; 
    import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D; 
    import org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTInline; 
       
    /**
    * 自定义 XWPFDocument,并重写 createPicture()方法
    */ 
    public class CustomXWPFDocument extends XWPFDocument {   
        public CustomXWPFDocument(InputStream in) throws IOException {   
            super(in);   
        }   
       
        public CustomXWPFDocument() {   
            super();   
        }   
       
        public CustomXWPFDocument(OPCPackage pkg) throws IOException {   
            super(pkg);   
        }   
       
        /**
         * @param id
         * @param width 宽
         * @param height 高
         * @param paragraph  段落
         */ 
        public void createPicture(int id, int width, int height,XWPFParagraph paragraph) {   
            final int EMU = 9525;   
            width *= EMU;   
            height *= EMU;   
            String blipId = getAllPictures().get(id).getPackageRelationship().getId();   
            CTInline inline = paragraph.createRun().getCTR().addNewDrawing().addNewInline();   
            String picXml = ""   
                    + "<a:graphic xmlns:a=\"http://schemas.openxmlformats.org/drawingml/2006/main\">"   
                    + "   <a:graphicData uri=\"http://schemas.openxmlformats.org/drawingml/2006/picture\">"   
                    + "      <pic:pic xmlns:pic=\"http://schemas.openxmlformats.org/drawingml/2006/picture\">"   
                    + "         <pic:nvPicPr>" + "            <pic:cNvPr id=\""   
                    + id   
                    + "\" name=\"Generated\"/>"   
                    + "            <pic:cNvPicPr/>"   
                    + "         </pic:nvPicPr>"   
                    + "         <pic:blipFill>"   
                    + "            <a:blip r:embed=\""   
                    + blipId   
                    + "\" xmlns:r=\">"   
                    + "            <a:stretch>"   
                    + "               <a:fillRect/>"   
                    + "            </a:stretch>"   
                    + "         </pic:blipFill>"   
                    + "         <pic:spPr>"   
                    + "            <a:xfrm>"   
                    + "               <a:off x=\"0\" y=\"0\"/>"   
                    + "               <a:ext cx=\""   
                    + width   
                    + "\" cy=\""   
                    + height   
                    + "\"/>"   
                    + "            </a:xfrm>"   
                    + "            <a:prstGeom prst=\"rect\">"   
                    + "               <a:avLst/>"   
                    + "            </a:prstGeom>"   
                    + "         </pic:spPr>"   
                    + "      </pic:pic>"   
                    + "   </a:graphicData>" + "</a:graphic>";   
       
            inline.addNewGraphic().addNewGraphicData();   
            XmlToken xmlToken = null;   
            try {   
                xmlToken = XmlToken.Factory.parse(picXml);   
            } catch (XmlException xe) {   
                xe.printStackTrace();   
            }   
            inline.set(xmlToken);  
             
            inline.setDistT(0);     
            inline.setDistB(0);     
            inline.setDistL(0);     
            inline.setDistR(0);     
             
            CTPositiveSize2D extent = inline.addNewExtent();   
            extent.setCx(width);   
            extent.setCy(height);   
             
            CTNonVisualDrawingProps docPr = inline.addNewDocPr();     
            docPr.setId(id);     
            docPr.setName("图片" + id);     
            docPr.setDescr("测试");  
        }   
    }   

     

    利用POI将word转换成html


    1.      POI介绍:

    Apache POI 是用Java编写的免费开源的跨平台的 Java API,Apache POI提供API给Java程式

    对Microsoft Office格式档案读和写的功能。POI为“Poor Obfuscation Implementation”的首字母

    缩写,意为“可怜的模糊实现”。

    Apache POI 是创建和维护操作各种符合Office Open XML(OOXML)标准和微软的OLE 2复合

    文档格式(OLE2)的Java API。用它可以使用Java读取和创建,修改MS Excel文件.而且,还可以

    使用Java读取和创建MS Word和MSPowerPoint文件。Apache POI 提供Java操作Excel解决方案

    (适用于Excel97-2008)。

    基本结构:

    HSSF -提供读写Microsoft Excel XLS格式档案的功能。

    XSSF -提供读写Microsoft Excel OOXML XLSX格式档案的功能。

    HWPF -提供读写Microsoft Word DOC格式档案的功能。

    HSLF -提供读写Microsoft PowerPoint格式档案的功能。

    HDGF -提供读Microsoft Visio格式档案的功能。

    HPBF -提供读Microsoft Publisher格式档案的功能。

    HSMF -提供读Microsoft Outlook格式档案的功能。

    其实,POI比较拿手的是处理Excel表格,即上面的HSSF及XSSF,我们的很多项目,只要涉及

    报表的,基本上都有用到它吧。用对于HWPF即处理DOC的包,功能就没有那么健全了,且API

    也不完善。

    2.      代码实现

    Word2Html文件
    import java.awt.image.BufferedImage;
    import java.io.BufferedWriter;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.OutputStream;
    import java.io.OutputStreamWriter;
    import javax.imageio.ImageIO;
    import org.apache.poi.hwpf.HWPFDocument;
    import org.apache.poi.hwpf.model.PicturesTable;
    import org.apache.poi.hwpf.usermodel.CharacterRun;
    import org.apache.poi.hwpf.usermodel.Paragraph;
    import org.apache.poi.hwpf.usermodel.Picture;
    import org.apache.poi.hwpf.usermodel.Range;
    import org.apache.poi.hwpf.usermodel.Table;
    import org.apache.poi.hwpf.usermodel.TableCell;
    import org.apache.poi.hwpf.usermodel.TableIterator;
    import org.apache.poi.hwpf.usermodel.TableRow;
    import org.apache.xmlbeans.impl.piccolo.io.FileFormatException;


    /**
     * @Description: 利用poi将word简单的转换成html文件
     * @author 柯颖波
     * @date 2013-12-20 上午09:32:44
     * @version v1.0
     */
    public class Word2Html {
     /**
      * 回车符ASCII码
      */
     private static final short ENTER_ASCII = 13;

     /**
      * 空格符ASCII码
      */
     private static final short SPACE_ASCII = 32;

     /**
      * 水平制表符ASCII码
      */
     private static final short TABULATION_ASCII = 9;

     private static String htmlText = "";
     private static String htmlTextTbl = "";
     private static int counter = 0;
     private static int beginPosi = 0;
     private static int endPosi = 0;
     private static int beginArray[];
     private static int endArray[];
     private static String htmlTextArray[];
     private static boolean tblExist = false;

     /**
      * 项目路径
      */
     private static String projectRealPath = "";
     /**
      * 临时文件路径
      */
     private static String tempPath = "/upfile/" + File.separator + "transferFile" +

    File.separator;
     /**
      * word文档名称
      */
     private static String wordName = "";

     public static void main(String argv[]) {
      try {
       wordToHtml("F:\\SVN\\BobUtil\\web\\", "test.doc");
      } catch (Exception e) {
       e.printStackTrace();
      }
     }

     /**
      * 读取每个文字样式
      *
      * @param fileName
      * @throws Exception
      */

     private static void getWordAndStyle(String fileName) throws Exception {
      FileInputStream in = new FileInputStream(new File(fileName));
      HWPFDocument doc = new HWPFDocument(in);

      Range rangetbl = doc.getRange();// 得到文档的读取范围
      TableIterator it = new TableIterator(rangetbl);

      int num = 100;
      beginArray = new int[num];
      endArray = new int[num];
      htmlTextArray = new String[num];
      tblExist = false;

      // 取得文档中字符的总数
      int length = doc.characterLength();
      // 创建图片容器
      PicturesTable pTable = doc.getPicturesTable();
      // 创建段落容器

      htmlText = "<html><head><meta http-equiv=\"Content-Type\"

    content=\"text/html; charset=utf-8\" /><title>"
        + doc.getSummaryInformation().getTitle()
        + "</title></head><body><div

    style='margin:60px;text-align:center;'><div style='width:620px;text-align:left;line-

    height:24px;'>";
      // 创建临时字符串,好加以判断一串字符是否存在相同格式

      if (it.hasNext()) {
       readTable(it, rangetbl);
      }

      int cur = 0;
      String tempString = "";
      for (int i = 0; i < length - 1; i++) {
       // 整篇文章的字符通过一个个字符的来判断,range为得到文档的

    范围
       Range range = new Range(i, i + 1, doc);
       CharacterRun cr = range.getCharacterRun(0);
       // beginArray=new int[num];
       // endArray=new int[num];
       // htmlTextArray=new String[num];
       if (tblExist) {
        if (i == beginArray[cur]) {
         htmlText += tempString + htmlTextArray

    [cur];
         tempString = "";
         i = endArray[cur] - 1;
         cur++;
         continue;
        }
       }
       if (pTable.hasPicture(cr)) {
        htmlText += tempString;
        // 读写图片
        try {
         readPicture(pTable, cr);
        } catch (Exception e) {
         e.printStackTrace();
        }
        tempString = "";
       } else {

        Range range2 = new Range(i + 1, i + 2, doc);
        // 第二个字符
        CharacterRun cr2 = range2.getCharacterRun(0);
        char c = cr.text().charAt(0);
        // System.out.println(c);
        // /System.out.println(i+"::"+range.getEndOffset()

    +"::"+range.getStartOffset()+"::"+c);

        // 判断是否为回车符
        if (c == ENTER_ASCII) {
         tempString += "<br/>";
        }
        // 判断是否为空格符
        else if (c == SPACE_ASCII)
         tempString += "&nbsp;";
        // 判断是否为水平制表符
        else if (c == TABULATION_ASCII)
         tempString += " &nbsp;&nbsp;&nbsp;";
        // 比较前后2个字符是否具有相同的格式
        boolean flag = compareCharStyle(cr, cr2);
        if (flag)
         tempString += cr.text();
        else {
         String fontStyle = "<span style=\"font-

    family:" + cr.getFontName() + ";font-size:"
           + cr.getFontSize() / 2 +

    "pt;";

         if (cr.isBold())
          fontStyle += "font-weight:bold;";
         if (cr.isItalic())
          fontStyle += "font-style:italic;";
         if (cr.isStrikeThrough())
          fontStyle += "text-

    decoration:line-through;";

         int fontcolor = cr.getIco24();
         int[] rgb = new int[3];
         if (fontcolor != -1) {
          rgb[0] = (fontcolor >> 0) & 0xff;

    // red;
          rgb[1] = (fontcolor >> 8) & 0xff;

    // green
          rgb[2] = (fontcolor >> 16) &

    0xff; // blue
         }
         fontStyle += "color: rgb(" + rgb[0] + "," +

    rgb[1] + "," + rgb[2] + ");";
         htmlText += fontStyle + "\">" +

    tempString + cr.text() + "</span>";
         tempString = "";
        }
       }
      }

      htmlText += tempString + "</div></div></body></html>";
      // System.out.println(htmlText);
     }

     /**
      * 读写文档中的表格
      *
      * @param pTable
      * @param cr
      * @throws Exception
      */
     private static void readTable(TableIterator it, Range rangetbl) throws Exception {

      htmlTextTbl = "";
      // 迭代文档中的表格

      counter = -1;
      while (it.hasNext()) {
       tblExist = true;
       htmlTextTbl = "";
       Table tb = (Table) it.next();
       beginPosi = tb.getStartOffset();
       endPosi = tb.getEndOffset();

       // System.out.println("............"+beginPosi+"...."+endPosi);
       counter = counter + 1;
       // 迭代行,默认从0开始
       beginArray[counter] = beginPosi;
       endArray[counter] = endPosi;

       htmlTextTbl += "<table border='1' cellpadding='0'

    cellspacing='0' >";
       for (int i = 0; i < tb.numRows(); i++) {
        TableRow tr = tb.getRow(i);

        htmlTextTbl += "<tr align='center'>";
        // 迭代列,默认从0开始
        for (int j = 0; j < tr.numCells(); j++) {
         TableCell td = tr.getCell(j);// 取得单元格
         int cellWidth = td.getWidth();

         // 取得单元格的内容
         for (int k = 0; k < td.numParagraphs();

    k++) {
          Paragraph para =

    td.getParagraph(k);
          CharacterRun crTemp =

    para.getCharacterRun(0);
          String fontStyle = "<span

    style=\"font-family:" + crTemp.getFontName() + ";font-size:"
            +

    crTemp.getFontSize() / 2 + "pt;color:" + crTemp.getColor() + ";";

          if (crTemp.isBold())
           fontStyle += "font-

    weight:bold;";
          if (crTemp.isItalic())
           fontStyle += "font-

    style:italic;";

          String s = fontStyle + "\">" +

    para.text().toString().trim() + "</span>";
          if (s == "") {
           s = " ";
          }
          // System.out.println(s);
          htmlTextTbl += "<td width=" +

    cellWidth + ">" + s + "</td>";
          // System.out.println(i + ":" + j +

    ":" + cellWidth + ":" + s);
         } // end for
        } // end for
       } // end for
       htmlTextTbl += "</table>";
       htmlTextArray[counter] = htmlTextTbl;

      } // end while
     }

     /**
      * 读写文档中的图片
      *
      * @param pTable
      * @param cr
      * @throws Exception
      */
     private static void readPicture(PicturesTable pTable, CharacterRun cr) throws

    Exception {
      // 提取图片
      Picture pic = pTable.extractPicture(cr, false);
      BufferedImage image = null;// 图片对象
      // 获取图片样式
      int picHeight = pic.getHeight() * pic.getAspectRatioY() / 100;
      int picWidth = pic.getAspectRatioX() * pic.getWidth() / 100;
      if (picWidth > 500) {
       picHeight = 500 * picHeight / picWidth;
       picWidth = 500;
      }
      String style = " style='height:" + picHeight + "px;width:" + picWidth +

    "px'";

      // 返回POI建议的图片文件名
      String afileName = pic.suggestFullFileName();
      //单元测试路径
      String directory = "images/" + wordName + "/";
      //项目路径
      //String directory = tempPath + "images/" + wordName + "/";
      makeDir(projectRealPath, directory);// 创建文件夹

      int picSize = cr.getFontSize();
      int myHeight = 0;

      if (afileName.indexOf(".wmf") > 0) {
       OutputStream out = new FileOutputStream(new File

    (projectRealPath + directory + afileName));
       out.write(pic.getContent());
       out.close();
       afileName = Wmf2Png.convert(projectRealPath + directory +

    afileName);

       File file = new File(projectRealPath + directory + afileName);

       try {
        image = ImageIO.read(file);
       } catch (Exception e) {
        e.printStackTrace();
       }

       int pheight = image.getHeight();
       int pwidth = image.getWidth();
       if (pwidth > 500) {
        htmlText += "<img style='width:" + pwidth +

    "px;height:" + myHeight + "px'" + " src=\"" + directory
          + afileName + "\"/>";
       } else {
        myHeight = (int) (pheight / (pwidth / (picSize * 1.0))

    * 1.5);
        htmlText += "<img style='vertical-

    align:middle;width:" + picSize * 1.5 + "px;height:" + myHeight
          + "px'" + " src=\"" + directory +

    afileName + "\"/>";
       }

      } else {
       OutputStream out = new FileOutputStream(new File

    (projectRealPath + directory + afileName));
       // pic.writeImageContent(out);
       out.write(pic.getContent());
       out.close();
       // 处理jpg或其他(即除png外)
       if (afileName.indexOf(".png") == -1) {
        try {
         File file = new File(projectRealPath +

    directory + afileName);
         image = ImageIO.read(file);
         picHeight = image.getHeight();
         picWidth = image.getWidth();
         if (picWidth > 500) {
          picHeight = 500 * picHeight /

    picWidth;
          picWidth = 500;
         }
         style = " style='height:" + picHeight +

    "px;width:" + picWidth + "px'";
        } catch (Exception e) {
         // e.printStackTrace();
        }
       }
       htmlText += "<img " + style + " src=\"" + directory +

    afileName + "\"/>";
      }
      if (pic.getWidth() > 450) {
       htmlText += "<br/>";
      }
     }

     private static boolean compareCharStyle(CharacterRun cr1, CharacterRun cr2) {
      boolean flag = false;
      if (cr1.isBold() == cr2.isBold() && cr1.isItalic() == cr2.isItalic()
        && cr1.getFontName().equals(cr2.getFontName())

    && cr1.getFontSize() == cr2.getFontSize()) {
       flag = true;
      }
      return flag;
     }

     /**
      * 写文件(成功返回true,失败则返回false)
      *
      * @param s
      *            要写入的内容
      * @param filePath
      *            文件
      */
     private static boolean writeFile(String s, String filePath) {
      FileOutputStream fos = null;
      BufferedWriter bw = null;
      s = s.replaceAll("EMBED", "").replaceAll("Equation.DSMT4", "");
      try {
       makeDir(projectRealPath, tempPath);// 创建文件夹
       File file = new File(filePath);
       if (file.exists()) {
        return false;
       }
       fos = new FileOutputStream(file);
       bw = new BufferedWriter(new OutputStreamWriter(fos, "utf-

    8"));
       bw.write(s);
       // System.out.println(filePath + "文件写入成功!");
      } catch (FileNotFoundException fnfe) {
       fnfe.printStackTrace();
      } catch (IOException ioe) {
       ioe.printStackTrace();
      } finally {
       try {
        if (bw != null)
         bw.close();
        if (fos != null)
         fos.close();
       } catch (IOException ie) {
        ie.printStackTrace();
       }
      }
      return true;
     }

     /**
      * 根据路径名生成多级路径
      *
      * @param url
      *            参数要以"\classes\cn\qtone\"或者"/classes/cn/qtone/"
      */
     private static String makeDir(String root, String url) {
      String[] sub;
      url = url.replaceAll("

    \\/", "\\\\");
      if (url.indexOf("\\") > -1) {
       sub = url.split("\\\\");
      } else {
       return "-1";
      }

      File dir = null;
      try {
       dir = new File(root);
       for (int i = 0; i < sub.length; i++) {
        if (!dir.exists() && !sub[i].equals("")) {
         dir.mkdir();
        }
        File dir2 = new File(dir + File.separator + sub[i]);
        if (!dir2.exists()) {
         dir2.mkdir();
        }
        dir = dir2;
       }
      } catch (Exception e) {
       e.printStackTrace();
       return "-1";
      }
      return dir.toString();
     }

     /**
      * 将word文档转化,返回转化后的文件路径
      *
      * @param projectPath
      *            项目路径
      * @param relativeFilePath
      *            文件相对路径
      * @return 返回生成的htm路径(如果出错,则返回null)
      */
     public static String wordToHtml(String projectPath, String relativeFilePath) {
      String resultPath = null;
      projectRealPath = projectPath;// 项目路径
      String filePath = "";
      // System.out.println(projectRealPath + tempPath);
      // System.out.println(makeDir(projectRealPath, tempPath));
      try {
       File file = new File(projectPath + relativeFilePath);
       if (file.exists()) {
        if (file.getName().indexOf(".doc") == -1 ||

    file.getName().indexOf(".docx") > 0) {
         throw new FileFormatException("请确认文

    件格式为doc!");
        } else {
         wordName = file.getName();
         wordName = wordName.substring(0,

    wordName.indexOf("."));

         filePath = projectRealPath + tempPath +

    wordName + ".htm";
         synchronized (relativeFilePath) {// 处理线程

    同步问题
          File ff = new File(filePath);
          if (!ff.exists()) {// 如果不存在则进

    行转换
           getWordAndStyle

    (projectPath + relativeFilePath);
           writeFile(htmlText,

    filePath);
          }
         }
         resultPath = tempPath + wordName +

    ".htm";
        }
       } else {
        throw new FileNotFoundException("没找到相关文件!

    ");
       }
      } catch (NullPointerException e) {
       e.printStackTrace();
      } catch (FileNotFoundException e) {
       e.printStackTrace();
      } catch (Exception e) {
       e.printStackTrace();
      }
      return resultPath;
     }
    }

    Wmf2Png文件
    package com;

    import java.io.ByteArrayInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.util.Scanner;
    import java.util.zip.GZIPOutputStream;

    import javax.xml.parsers.DocumentBuilder;
    import javax.xml.parsers.DocumentBuilderFactory;
    import javax.xml.transform.OutputKeys;
    import javax.xml.transform.Transformer;
    import javax.xml.transform.TransformerFactory;
    import javax.xml.transform.dom.DOMSource;
    import javax.xml.transform.stream.StreamResult;

    import net.arnx.wmf2svg.gdi.svg.SvgGdi;
    import net.arnx.wmf2svg.gdi.wmf.WmfParser;

    import org.apache.batik.transcoder.TranscoderInput;
    import org.apache.batik.transcoder.TranscoderOutput;
    import org.apache.batik.transcoder.TranscodingHints;
    import org.apache.batik.transcoder.image.PNGTranscoder;
    import org.apache.batik.transcoder.wmf.tosvg.WMFTranscoder;
    import org.apache.commons.lang.StringUtils;
    import org.w3c.dom.Document;
    import org.w3c.dom.Element;

    public class Wmf2Png {
     public static void main(String[] args) throws Exception {
      // convert("F:\\SVN\\BobUtil\\web\\25177.wmf");
      // System.out.println((20 / (21 * 1.0)));
      // svgToPng("F:\\SVN\\BobUtil\\web\\25177.svg",

    "F:\\SVN\\BobUtil\\web\\25177.png");
     }

     /**
      * @Description: 进行转换
      * @param filePath
      *            文件路径
      * @return 设定文件
      */
     public static String convert(String filePath) {
      String pngFile = "";
      File wmfFile = new File(filePath);
      try {
       if (!wmfFile.getName().contains(".wmf")) {
        throw new Exception("请确认输入的文件类型是

    wmf");
       }
       // wmf -> svg
       String svgFile = filePath.replace("wmf", "svg");
       wmfToSvg(filePath, svgFile);
       // 对svg做预出理
       PreprocessSvgFile(svgFile);
       // svg -> png
       pngFile = filePath.replace("wmf", "png");
       svgToPng(svgFile, pngFile);
       // 删除 svg
       File file = new File(svgFile);
       if (file.exists()) {
        file.delete();
       }
       // 删除 wmf
       if (wmfFile.exists()) {
        wmfFile.delete();
       }

      } catch (Exception e) {
       try {
        e.printStackTrace();
        wmfToJpg(filePath);
       } catch (Exception e1) {
        e1.printStackTrace();
       }
      }
      return wmfFile.getName().replace("wmf", "png");
     }

     /**
      * 将wmf转换为svg
      *
      * @param src
      * @param dest
      */
     public static void wmfToSvg(String src, String dest) throws Exception {
      boolean compatible = false;
      try {
       InputStream in = new FileInputStream(src);
       WmfParser parser = new WmfParser();
       final SvgGdi gdi = new SvgGdi(compatible);
       parser.parse(in, gdi);

       Document doc = gdi.getDocument();
       OutputStream out = new FileOutputStream(dest);
       if (dest.endsWith(".svgz")) {
        out = new GZIPOutputStream(out);
       }

       output(doc, out);
      } catch (Exception e) {
       throw e;
      }
     }

     /**
      * @Description: 输出svg文件
      * @param doc
      * @param out
      * @throws Exception
      *             设定文件
      */
     private static void output(Document doc, OutputStream out) throws Exception {
      TransformerFactory factory = TransformerFactory.newInstance();
      Transformer transformer = factory.newTransformer();
      transformer.setOutputProperty(OutputKeys.METHOD, "xml");
      transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
      transformer.setOutputProperty(OutputKeys.INDENT, "yes");
      transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC,

    "-//W3C//DTD SVG 1.0//EN");
      transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM,
        "http://www.w3.org/TR/2001/REC-SVG-

    20010904/DTD/svg10.dtd");
      transformer.transform(new DOMSource(doc), new StreamResult(out));
      out.flush();
      out.close();
      out = null;
     }

     /**
      * @Description:对svg文件做预处理(这里主要是调整大小,先缩小10倍,如果还大

    于默认值,则按比例缩小)
      * @param svgFile
      * @throws Exception
      *             设定文件
      */
     private static void PreprocessSvgFile(String svgFile) throws Exception {
      int defaultWeight = 500;// 默认宽度
      FileInputStream inputs = new FileInputStream(svgFile);
      Scanner sc = new Scanner(inputs, "UTF-8");
      ByteArrayOutputStream os = new ByteArrayOutputStream();
      while (sc.hasNextLine()) {
       String ln = sc.nextLine();
       if (!ln.startsWith("<!DOCTYPE")) {
        os.write((ln + "\r\n").getBytes());
       }
      }
      os.flush();
      
      DocumentBuilderFactory factory =

    DocumentBuilderFactory.newInstance();
      DocumentBuilder builder;
      builder = factory.newDocumentBuilder();
      Document doc = null;
      try {
       doc = builder.parse(new ByteArrayInputStream

    (os.toByteArray()));
      } catch (Exception e) {
       inputs = new FileInputStream(svgFile);
       os = new ByteArrayOutputStream();
       int noOfByteRead = 0;
       while ((noOfByteRead = inputs.read()) != -1) {
        os.write(noOfByteRead);
       }
       os.flush();
       doc = builder.parse(new ByteArrayInputStream

    (os.toByteArray()));
      } finally {
       os.close();
       inputs.close();
      }
      
      int height = Integer.parseInt(((Element) doc.getElementsByTagName

    ("svg").item(0)).getAttribute("height"));
      int width = Integer.parseInt(((Element) doc.getElementsByTagName

    ("svg").item(0)).getAttribute("width"));
      int newHeight = 0;// 新高
      int newWidth = 0;// 新宽
      newHeight = height / 10;// 高缩小10倍
      newWidth = width / 10; // 宽缩小10倍
      // 如果缩小10倍后宽度还比defaultHeight大,则进行调整
      if (newWidth > defaultWeight) {
       newWidth = defaultWeight;
       newHeight = defaultWeight * height / width;
      }

      ((Element) doc.getElementsByTagName("svg").item(0)).setAttribute

    ("width", String.valueOf(newWidth));
      ((Element) doc.getElementsByTagName("svg").item(0)).setAttribute

    ("height", String.valueOf(newHeight));
      OutputStream out = new FileOutputStream(svgFile);
      output(doc, out);
     }

     /**
      * 将svg图片转成png图片
      *
      * @param filePath
      * @throws Exception
      */
     public static void svgToPng(String svgPath, String pngFile) throws Exception {
      File svg = new File(svgPath);
      FileInputStream wmfStream = new FileInputStream(svg);
      ByteArrayOutputStream imageOut = new ByteArrayOutputStream();
      int noOfByteRead = 0;
      while ((noOfByteRead = wmfStream.read()) != -1) {
       imageOut.write(noOfByteRead);
      }
      imageOut.flush();
      imageOut.close();
      wmfStream.close();

      ByteArrayOutputStream jpg = new ByteArrayOutputStream();
      FileOutputStream jpgOut = new FileOutputStream(pngFile);

      byte[] bytes = imageOut.toByteArray();
      PNGTranscoder t = new PNGTranscoder();
      TranscoderInput in = new TranscoderInput(new ByteArrayInputStream

    (bytes));
      TranscoderOutput out = new TranscoderOutput(jpg);
      t.transcode(in, out);
      jpgOut.write(jpg.toByteArray());
      jpgOut.flush();
      jpgOut.close();
      imageOut = null;
      jpgOut = null;
     }

     /**
      * 将wmf图片转成png图片(备用方法,即当上面的转换失败时用这个)
      *
      * @param filePath
      * @throws Exception
      */
     public static String wmfToJpg(String wmfPath) throws Exception {
      //先wmf-->svg
      File wmf = new File(wmfPath);
      FileInputStream wmfStream = new FileInputStream(wmf);
      ByteArrayOutputStream imageOut = new ByteArrayOutputStream();
      int noOfByteRead = 0;
      while ((noOfByteRead = wmfStream.read()) != -1) {
       imageOut.write(noOfByteRead);
      }
      imageOut.flush();
      imageOut.close();
      wmfStream.close();

      // WMFHeaderProperties prop = new WMFHeaderProperties(wmf);
      WMFTranscoder transcoder = new WMFTranscoder();
      TranscodingHints hints = new TranscodingHints();
      transcoder.setTranscodingHints(hints);
      TranscoderInput input = new TranscoderInput(new

    ByteArrayInputStream(imageOut.toByteArray()));
      ByteArrayOutputStream svg = new ByteArrayOutputStream();
      TranscoderOutput output = new TranscoderOutput(svg);
      transcoder.transcode(input, output);
      
      //再svg-->png
      ByteArrayOutputStream jpg = new ByteArrayOutputStream();
      String jpgFile = StringUtils.replace(wmfPath, "wmf", "png");
      FileOutputStream jpgOut = new FileOutputStream(jpgFile);

      byte[] bytes = svg.toByteArray();
      PNGTranscoder t = new PNGTranscoder();
      TranscoderInput in = new TranscoderInput(new ByteArrayInputStream

    (bytes));
      TranscoderOutput out = new TranscoderOutput(jpg);
      t.transcode(in, out);
      jpgOut.write(jpg.toByteArray());
      jpgOut.flush();
      jpgOut.close();
      return jpgFile;
     }
    }

    重点难点解释探讨:

    1)  读取表格部分:

    a)        找出表格的开始与结束标记;

    b)        遍历整个表格内容,逐个单元格的内容取出并追加到变量中。

    2)  读取图片部分

    a)        图片文件的格式问题。

    如果图片格式为png或者jpg,则可以直接进行处理并加入标签中,前台的html展示没有问题,

    但是,如果图片格式为wmf(详细看附录1),则html无法对基解释,那么我们只能对其进行

    转换格式:

    百度后,网上很多说法都建议用batik工具包进行格式转换,其实思路就是:wmfàsvgàpng。

    查阅相关资料(如附录2),发现其处理svg文件的能力相当的强,即从svg—>png这一步是比

    较完美的。但是,在处理wmf—>svg这一步却导致部分图像丢失,即失真的情况,且很严重。

    查看相关的api看是否参数设置问题,但是无论怎么设置,结果还是不尽人意。一度想放弃,

    找别的包。

    后来,无意中,在csdn中有网友建议先用wmf2svg工具类将wmf转换为svg,再用batik将svg转

    换为png。Very good!!有了这个思路,感觉已经看到署光了。

    类写出来后,进行类型转换测试,确实效果很好,完全没有失真。于是将其嵌入word—>html

    这个工具类中。再用各种包含了wmf图片的文档进行测试。生成的html文件,基本没有问题,

    当时那个开心啊!!(我去,程序员也就这德行)

    好景不长,放到正式项目进行测试过程中,发现有个别文档一进行转换,服务器就跨了,直接

    报内存溢出。通过排查检测,原来就是进行图片转换过程中,将内存给挤爆了。奇怪了,虽然

    知道图片处理是比较耗内存,但也没想到1G的内存,一下子就被挤爆(刚跑起来占去300M左

    右,一跑word转换功能,不过一会就报OutOfMemorry)。

    一度怀疑,是不是batik这个工具包是不是有bug,处理不了大的svg。还将问题放上了bakit的

    官网。后来,查看相关资料后,发现是wmf2svg工具生成的svg的高与宽都太大了,举个例子

    :15040* 13088,宽高都达到上万级别,结果得到的象素是上亿的,不爆内存才怪。

    用dom工具,将每一个生成的svg文件再进行预处理,即将其高与宽都先缩小一倍,如果宽度

    依然比500要大,则将其设成500,并将高也按比例缩小。经过此步骤生成的svg再用batik进行

    转换就没有任何问题了。

    到这里,差不多已经解决图片转换的问题了,但是,在使用过程中,发现wmf2svg这个工具也

    不是很稳定,偶尔会报异常,并且,我测试发现,报异常的这个wmf用之前batik直接进行wmf

    —>svgàpng的方案可以成功生成没有失真的png,于是,在wmf2svg的产生异常进行捕捉,并

    调用了wmfToJpg(String wmfPath)的备用方法。到此,大部分的wmf转换问题已经解决。

    b)        生成html文本的<img />标签的width与height问题。

    如果图片格式原本为png的话,直接用

      // 获取图片样式
      int picHeight = pic.getHeight() * pic.getAspectRatioY() / 100;
      int picWidth = pic.getAspectRatioX() * pic.getWidth() / 100;

    即可以将图片的宽与高设置与word文档一致;但是,发果wmf格式,要分两种情况分析:
    Ø  如果转换生成的png宽度不小于500,则将期作为一般图片处理:
    BufferedImage  image = ImageIO.read(file);
    int pheight = image.getHeight();
    int pwidth = image.getWidth();

    Ø  如果转换生成的png宽度小于500,则认为是一般的公式,则应该与它旁边的字体宽度相近

    ,这里设成字体的1.5倍宽度,高度为:
    myHeight= (int) (pheight / (pwidth / (picSize * 1.0)) * 1.5);

    如果图片即非wmf与非png(如jpg)的情况下,上面获取高与宽的方法不起作用,不知道是不

    是POI的bug。只能按以下方式处理:
    BufferedImage  image = ImageIO.read(file);
    int pheight = image.getHeight();
    int pwidth = image.getWidth();
    即跟上面处理wmf的第一种方式一致。

    结束语

    讲到这,将word转换成html的处理也大体上讲完了。这几天的边学边用,特别是真正能解决问

    题的时候,非常有成就感。其实,上面的处理还存在以下的问题待解决的:

    1)读取表格部分:

    a)        表格中如果再含有表格,POI无法进行很好的区分,比如,有一个两行两列的表格中,

    第一行第一列中又包含了一个两行两列的表格,那POI会将此表格解释成:第一行为2+2*2 =

    6个单元格;第二行为2个单元格,这样解释出来的表格就很怪异了。

    b)        表格中有果有合并单格的情况,程序暂未做此处理(后续看不能优化),表格也很怪

    异。

    c)        表格中如果有图像,程序没有做相应的处理。

    2)读取图片部分:

    a) 有部分wmf->png的方式有个别图片还是没有转换成功,会报异常,但没有影响整体的功能

    b) word有部分公式生成的图片无法识别模式,不知道是不是POI无法将其解释,还是其他原因

    ,就是有文档,生成没有后缀的图片文件,且这部分文件无法读取,用图片工具也打不开,暂

    时未找到很好的解决方案。

    3)读取word的目录:

    在读取目录会出现将格式化符号也解释出来。

    4)其他未知的一些问题,反正,就觉得用POI来解释word是件很坚苦的事情,如果全是文本

    还好,如果里面包含图片,表格,公式等这些对象的时候,POI就显得太弱了。

    附:

    1.       wmf文件:

    MicrosoftOffice 的剪贴画使用的就是这个格式。

    Wmf是WindowsMetafile 的缩写,简称图元文件,它是微软公司定义的一种Windows平台下的

    图形文件格式。

    wmf格式文件的特点如下:

    1)                 wmf格式文件是MicrosoftWindows操作平台所支持的一种图形格式文件,目前

    ,其它操作系统尚不支持这种格式,如Unix、Linux等。

    2)                 与bmp格式不同,wmf格式文件是和设备无关的,即它的输出特性不依赖于具

    体的输出设备。

    3)                 其图象完全由Win32 API所拥有的GDI函数来完成。

    4)                 wmf格式文件所占的磁盘空间比其它任何格式的图形文件都要小得多。

    5)                 在建立图元文件时,不能实现即画即得,而是将GDI调用记录在图元文件中,

    之后,在GDI环境中重新执行,才可显示图象。

    6)                 显示图元文件的速度要比显示其它格式的图象文件慢,但是它形成图元文件的

    速度要远大于其它格式。

    2.      Batik介绍

    Batik是使用svg格式图片来实现各种功能的应用程序以及Applet提供的一个基于java的工具包

    通过Batik,你可以在JAVA可以使用的地方操作SVG文档,您还可以在你的应用程序使用Batik模

    块来生成, 处理和转码SVG图像。Batik很容易让基于Java的应用程序或小程序来处理SVG内容

    。 例如,使用Batik的SVG的发生器模块 ,Java应用程序或小程序可以很轻松地导出SVG格式

    的图形到。用Batik的SVG的查看组件,应用程序或小程序可以很容易地集成SVG的浏览和交互

    功能。另一种可能性是使用Batik的模块转换成各种格式SVG的通过,如光栅图像(JPEG,PNG

    或TIFF格式)或其它矢量格式(EPS或PDF格式,后两者由于转码器由Apache FOP提供)。

    Batik工程创建的目的是为开发者提供一系列可以结合或单独使用来支持特殊的svg解决方案的

    核心模块。模块主要有SVGParser,SVGGernerator,SVGDOM。Batik工程的其他目的是使它具有

    高度的扩展性。

    (SVG的规范:可缩放矢量图形(SVG),是一个W3C的推荐标准。 它定义了丰富的2D图形的

    XML语法,其中包括诸如透明度功能,几何形状,滤镜效果(阴影,灯光效果等),脚本和动

    画)


    POI Word 模板导出教程 

    word2007功能比较完善,2003只有值替换的功能
    功能目标,读取word模板,解析数据导出word,对数据赋值
    功能点1: 值替换
    功能点2: 表格的创建
    功能点3: 图片的插入
    下面将根据这个三个功能点来做讲解
    1.值替换 最基础的功能
    在word中需要插入数据的地方加入{{test}}Or{{obj.test}}
    支持实体对象,和map类型的取值
    例如
    取值的时候就是 {{workers}}

    替换的对象会保留原格式,如加粗,则替换后仍然加粗

    2.表格
    表格也是Word里面经常出现的
    解析是放在一个List里面,这个也是大家经常这样的
    里面的对象同样可以是map也可以是实体

    例如:

    其中in 表示需要变量这个对象 psrsons是一个person的list(需要独占一行)
    紧接着下一行是他的属性
    之后程序会进行迭代,生成表格

    3.图片
    这里就要介绍一个实体了WordImageEntity
    会把这个类型的实体转变成图片,同样准信值替换的原则

    例如
    最后我们看一下效果

    生成的对象

     

    poi操作word模板(word2003,word2007)

    Apache POI是Apache软件基金会的开放源码函式库,POI提供API给Java程序对Microsoft Office格式档案读和写的功能。Word2003的方法比较简单,大致通过Range替换文本,Word2007比较复杂点,遍历替换文本,参考了网上的案例,写了个demo,直接上代码。
    package com.poi.util;

    import java.io.ByteArrayOutputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.OutputStream;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.List;
    import java.util.Map;
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    import org.apache.poi.POIXMLDocument;
    import org.apache.poi.hwpf.HWPFDocument;
    import org.apache.poi.hwpf.extractor.WordExtractor;
    import org.apache.poi.hwpf.usermodel.Range;
    import org.apache.poi.openxml4j.opc.OPCPackage;
    import org.apache.poi.xwpf.extractor.XWPFWordExtractor;
    import org.apache.poi.xwpf.usermodel.XWPFDocument;
    import org.apache.poi.xwpf.usermodel.XWPFParagraph;
    import org.apache.poi.xwpf.usermodel.XWPFRun;
    import org.apache.poi.xwpf.usermodel.XWPFTable;
    import org.apache.poi.xwpf.usermodel.XWPFTableCell;
    import org.apache.poi.xwpf.usermodel.XWPFTableRow;
    import com.poi.model.Person;

    public class WordUtil {
     private Map<String, String> map = new HashMap<String, String>();//存放标签与替换的值
     private String templatePath;//模版路径

     public WordUtil(String templatePath,Person person) {
      this.templatePath = templatePath;
      if (templatePath.endsWith("docx")) {
       try {
        @SuppressWarnings("resource")
        XWPFWordExtractor docx = new XWPFWordExtractor(
          POIXMLDocument.openPackage(templatePath));
        String docxText = docx.getText();
        getValueMap(docxText,person);
       } catch (Exception e) {
        e.printStackTrace();
       }
      } else {
       try {
        @SuppressWarnings("resource")
        WordExtractor doc = new WordExtractor(new FileInputStream(
          templatePath));
        String docText = doc.getText();
        getValueMap(docText,person);
       } catch (Exception e) {
        e.printStackTrace();
       }
      }
     }
     //遍历获取标签与通过对象替代的值
     private void getValueMap(String text,Person person) {
      Pattern pattern = Pattern.compile("%(.*?)%");
      Matcher matcher = pattern.matcher(text);
      while (matcher.find()) {
       String key = matcher.group(1);
       String value = person.getString(key);
       if (value == null) {
        value = "";
       }
       map.put(key, value);
      }
     }
     public void createDoc(String newPath) {
      if (templatePath.endsWith("docx")) {
       replaceDoc2007(newPath);
      } else {
       replaceDoc2003(newPath);
      }
     }

     public void replaceDoc2007(String newPath) {
      try {
       OPCPackage pack = POIXMLDocument.openPackage(templatePath);
       XWPFDocument doc = new XWPFDocument(pack);
       // 处理段落
       List<XWPFParagraph> paragraphList = doc.getParagraphs();
       processParagraphs(paragraphList, map);
       // 处理表格
       Iterator<XWPFTable> it = doc.getTablesIterator();
       while (it.hasNext()) {
        XWPFTable table = it.next();
        List<XWPFTableRow> rows = table.getRows();
        for (XWPFTableRow row : rows) {
         List<XWPFTableCell> cells = row.getTableCells();
         for (XWPFTableCell cell : cells) {
          List<XWPFParagraph> paragraphListTable = cell
            .getParagraphs();
          processParagraphs(paragraphListTable, map);
         }
        }
       }
       FileOutputStream fos = new FileOutputStream(newPath);
       doc.write(fos);
       fos.flush();
       fos.close();
      } catch (Exception e) {
       e.printStackTrace();
      }
     }

     public void replaceDoc2003(String newPath) {
      String[] str = newPath.split(".doc");
      newPath = str[0] + ".doc";
      try {
       FileInputStream fis = new FileInputStream(new File(templatePath));
       HWPFDocument doc = new HWPFDocument(fis);
       Range bodyRange = doc.getRange();
       for (Map.Entry<String, String> entry : map.entrySet()) {
        bodyRange.replaceText("%" + entry.getKey() + "%",
          entry.getValue());
       }
       // 输出word文件
       ByteArrayOutputStream ostream = new ByteArrayOutputStream();
       doc.write(ostream);
       OutputStream outs = new FileOutputStream(newPath);
       outs.write(ostream.toByteArray());
       outs.close();
      } catch (Exception e) {
       e.printStackTrace();
      }
     }

     private void processParagraphs(List<XWPFParagraph> paragraphList,
       Map<String, String> map) {
      for (XWPFParagraph paragraph : paragraphList) {
       List<XWPFRun> runs = paragraph.getRuns();
       for (XWPFRun run : runs) {
        String text = run.getText(0);
        boolean isSetText = false;
        for (Map.Entry<String, String> entry : map.entrySet()) {
         String key = entry.getKey();
         if (text.indexOf(key) != -1) {
          isSetText = true;
          text = text.replace("%" + entry.getKey() + "%",entry.getValue());
         }
        }
        if (isSetText) {
         run.setText(text, 0);
        }
       }
      }
     }


    }

     

    POI处理WORD的另类方式 

     

    大致的思路是先用office2003或者2007编辑好word的样式,然后另存为xml,将xml翻译为FreeMarker模板,最后用java来解析FreeMarker模板并输出Doc。经测试这样方式生成的word文档完全符合office标准,样式、内容控制非常便利,打印也不会变形,生成的文档和office中编辑文档完全一样。

    看看实际效果:

    首先用office【版本要2003以上,以下的不支持xml格式】编辑文档的样式,图中红线的部分就是我要输出的部分:doc1

    将编辑好的文档另存为XML
    doc2

    再用Firstobject free XML editor【Firstobject free XML editor的使用见这里将xml中我们需要填数据的地方打上FreeMarker标记【FreeMarker的语法见这里
    doc3

    最后生成的文档样式
    doc4


    package com.havenliu.document;
     
    import java.io.BufferedWriter;
    import java.io.File;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.OutputStreamWriter;
    import java.io.Writer;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
     
    import freemarker.template.Configuration;
    import freemarker.template.Template;
    import freemarker.template.TemplateException;
     
    public class DocumentHandler {
    private Configuration configuration = null;
     
    public DocumentHandler() {
    configuration = new Configuration();
    configuration.setDefaultEncoding("utf-8");
    }
     
    public void createDoc() {
    //要填入模本的数据文件
    Map dataMap=new HashMap();
    getData(dataMap);
    //设置模本装置方法和路径,FreeMarker支持多种模板装载方法。可以重servlet,classpath,数据库装载,
    //这里我们的模板是放在com.havenliu.document.template包下面
    configuration.setClassForTemplateLoading(this.getClass(), "/com/havenliu/document/template");
    Template t=null;
    try {
    //test.ftl为要装载的模板
    t = configuration.getTemplate("test.ftl");
    } catch (IOException e) {
    e.printStackTrace();
    }
    //输出文档路径及名称
    File outFile = new File("D:/temp/outFile.doc");
    Writer out = null;
    try {
    out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile),"UTF-8"));
    } catch (FileNotFoundException e1) {
    e1.printStackTrace();
    }
     
            try {
    t.process(dataMap, out);
    } catch (TemplateException e) {
    e.printStackTrace();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
     
    /**
    * 注意dataMap里存放的数据Key值要与模板中的参数相对应
    * @param dataMap
    */
    private void getData(Map dataMap)
     {
     dataMap.put("author", "张三");
     dataMap.put("remark", "这是测试备注信息");
     List
     _table1=new ArrayList
    ();
     
     Table1 t1=new Table1();
     t1.setDate("2010-10-1");
     t1.setText("制定10月开发计划内容。");
     _table1.add(t1);
     
     Table1 t2=new Table1();
     t2.setDate("2010-10-2");
     t2.setText("开会讨论开发计划");
     _table1.add(t2);
     
     dataMap.put("table1", _table1);
     
     List
     _table2=new ArrayList
    ();
     for(int i=0;i<5;i++)
     {
     Table2 _t2=new Table2();
     _t2.setDetail("测试开发计划"+i);
     _t2.setPerson("张三——"+i);
     _t2.setBegindate("2010-10-1");
     _t2.setFinishdate("2010-10-31");
     _t2.setRemark("备注信息");
     _table2.add(_t2);
     }
     dataMap.put("table2", _table2);
     }
    }

     

    展开全文
  • 使用Jacob来处理Word文档 Word或Excel程序是以一种COM组件形式存在的。如果能够在Java中调用Word的COM组件,就 能使用它的方法来获取Word文档中的文本信息。目前网上有许多提供这样的工具。 1 Jacob的下载 ...

    使用Jacob来处理Word文档


    Word或Excel程序是以一种COM组件形式存在的。如果能够在Java中调用Word的COM组件,就

    能使用它的方法来获取Word文档中的文本信息。目前网上有许多提供这样的工具。

    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。本书

    采用的是jacob_1.11_zip。解压下载的 Jacob_1.11_zip文件后,

    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转换内容,该函数的代码如下。

    public static void extractDoc(String inputFIle, String outputFile) {

       boolean flag = false; 

       // 打开Word应用程序
       ActiveXComponent app = new ActiveXComponent("Word.Application");
       try {
          // 设置word不可见
          app.setProperty("Visible", new Variant(false));

          // 打开word文件
          Dispatch doc1 = app.getProperty("Documents").toDispatch();

          Dispatch doc2 = Dispatch.invoke(
                doc1,
                "Open",
                Dispatch.Method,
                new Object[] { inputFIle, new Variant(false),
                      new Variant(true) }, new int[1]).toDispatch();

          // 作为txt格式保存到临时文件
          Dispatch.invoke(doc2, "SaveAs", Dispatch.Method, new Object[] {
                outputFile, new Variant(7) }, new int[1]);

          // 关闭word
          Variant f = new Variant(false);
          Dispatch.call(doc2, "Close", f);
          flag = true;

       } catch (Exception e) {
          e.printStackTrace();
       } finally {
          app.invoke("Quit", new Variant[] {});
       }

       if (flag == true) {
          System.out.println("Transformed Successfully");
       } else {
          System.out.println("Transform Failed");
       }

    }

    (5)创建一个main函数来测试WordReader类,该main函数代码如下。

    public static void main(String[] args) {
            WordReader.extractDoc("c:/test.doc","c:/jacob.txt");
    }

    (6)新生成的txt文件被保存到c:/jacob.txt下

    在使用Jacob时,很重要的一点是,用户本地系统中必须安装有Word的应用程序。否则也就无

    法建立Java-COM桥,进而无法解析了。

     

    解决jacob调用word处理doc文件的内存溢出问题


    背景:
    有个项目在系统后台用Jacob调用Word进程的API做doc文件处理。在进行压力测试的时候,发现运行一段时间后,内存占用奇高,大约7.4G。由于JVM占用内存限制为2G,因此怀疑多出来的内存应当是Jacob泄露的。

    在网路上搜索解决办法,都是要这样调用
    [java] view plaincopyprint?ComThread.InitSTA();   
    // do something    
    ComThread.Release(); 
    ComThread.InitSTA();
    // do something
    ComThread.Release();
    但是在项目中,使用了线程池进行DOC文件处理,也就是同一时间,会有多个WORD进程在跑,使用ComThread.InitSTA();之后,Jacob仅允许线程池里面的一个线程执行,其他线程都被锁住。

    最后修改成ComThread.InitMTA(true);来初始化,经过24小时压力测试,可以同时有多个WORD进程运行,另外也解决了Jacob内存溢出问题。

     

    使用JACOB进行Word编程示例

     

    import java.util.ArrayList;   
    import java.util.List;    
      
    import com.jacob.activeX.ActiveXComponent;    
    import com.jacob.com.ComThread;    
    import com.jacob.com.Dispatch;    
    import com.jacob.com.Variant;   
      
    import org.apache.log4j.Logger;   
      
    /**  
     *   
     *作用:利用jacob插件生成word 文件!   
     *   
     *
     */  
    public class DOCWriter {   
      
        /** 日志记录器 */  
        static private Logger logger = Logger.getLogger(DOCWriter.class);   
      
        /** word文档  
         *   
         * 在本类中有两种方式可以进行文档的创建,<br>  
         * 第一种调用 createNewDocument  
         * 第二种调用 openDocument   
         */    
        private Dispatch document = null;    
      
        /** word运行程序对象 */    
        private ActiveXComponent word = null;    
      
        /** 所有word文档 */    
        private Dispatch documents = null;    
      
        /**  
         *  Selection 对象 代表窗口或窗格中的当前所选内容。 所选内容代表文档中选定(或突出

    显示)的区域,如果文档中没有选定任何内容,则代表插入点。  
         *  每个文档窗格只能有一个Selection 对象,并且在整个应用程序中只能有一个活动的

    Selection 对象。  
         */  
        private Dispatch selection = null;    
      
        /**  
         *   
         * Range 对象 代表文档中的一个连续区域。 每个 Range 对象由一个起始字符位置和一个

    终止字符位置定义。  
         * 说明:与书签在文档中的使用方法类似,Range 对象在 Visual Basic 过程中用来标识文

    档的特定部分。  
         * 但与书签不同的是,Range对象只在定义该对象的过程运行时才存在。  
         * 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;   
      
        /**  
         * 构造方法  
         */  
        public DOCWriter() {    
      
            if(this.word == null){   
                /* 初始化应用所要用到的对象实例 */  
                this.word = new ActiveXComponent("Word.Application");    
                /* 设置Word文档是否可见,true-可见false-不可见 */  
                this.word.setProperty("Visible",new Variant(true));   
                /* 禁用宏 */  
                this.word.setProperty("AutomationSecurity", new Variant(3));   
            }   
            if(this.documents == null){   
                this.documents = word.getProperty("Documents").toDispatch();   
            }   
        }   
      
        /**  
         * 设置页面方向和页边距  
         *  
         * @param orientation  
         *            可取值0或1,分别代表横向和纵向  
         * @param leftMargin  
         *            左边距的值  
         * @param rightMargin  
         *            右边距的值  
         * @param topMargin  
         *            上边距的值  
         * @param buttomMargin  
         *            下边距的值  
         */  
        public void setPageSetup(int orientation, int leftMargin,int rightMargin, int topMargin, int

    buttomMargin) {   
               
            logger.debug("设置页面方向和页边距...");   
            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);   
        }   
      
        /**   
         * 打开文件   
         *   
         * @param inputDoc   
         *            要打开的文件,全路径   
         * @return Dispatch   
         *            打开的文件   
         */    
        public Dispatch openDocument(String inputDoc) {    
      
            logger.debug("打开Word文档...");   
            this.document = Dispatch.call(documents,"Open",inputDoc).toDispatch();   
            this.getSelection();   
            this.getRange();   
            this.getAlignment();   
            this.getFont();   
            this.getPageSetup();   
            return this.document;    
        }    
      
        /**  
         * 创建新的文件  
         *   
         * @return Dispache 返回新建文件  
         */  
        public Dispatch createNewDocument(){   
               
            logger.debug("创建新的文件...");   
            this.document = Dispatch.call(documents,"Add").toDispatch();   
            this.getSelection();   
            this.getRange();   
            this.getPageSetup();   
            this.getAlignment();   
            this.getFont();   
            return this.document;   
        }   
      
        /**   
         * 选定内容   
         * @return Dispatch 选定的范围或插入点   
         */    
        public Dispatch getSelection() {    
      
            logger.debug("获取选定范围的插入点...");   
            this.selection = word.getProperty("Selection").toDispatch();   
            return this.selection;    
        }    
      
        /**  
         * 获取当前Document内可以修改的部分<p><br>  
         * 前提条件:选定内容必须存在  
         *   
         * @param selectedContent 选定区域  
         * @return 可修改的对象  
         */  
        public Dispatch getRange() {   
      
            logger.debug("获取当前Document内可以修改的部分...");   
            this.range = Dispatch.get(this.selection, "Range").toDispatch();   
            return this.range;   
        }   
      
        /**  
         * 获得当前文档的文档页面属性  
         */  
        public Dispatch getPageSetup() {   
               
            logger.debug("获得当前文档的文档页面属性...");   
            if(this.document == null){   
                logger.warn("document对象为空...");   
                return this.pageSetup;   
            }   
            this.pageSetup = Dispatch.get(this.document, "PageSetup").toDispatch();   
            return this.pageSetup;   
        }   
      
        /**   
         * 把选定内容或插入点向上移动   
         * @param count 移动的距离   
         */    
        public void moveUp(int count) {    
      
            logger.debug("把选定内容或插入点向上移动...");   
            for(int i = 0;i < count;i++) {   
                Dispatch.call(this.selection,"MoveUp");   
            }   
        }    
      
        /**   
         * 把选定内容或插入点向下移动   
         * @param count 移动的距离   
         */    
        public void moveDown(int count) {    
      
            logger.debug("把选定内容或插入点向下移动...");   
            for(int i = 0;i < count;i++) {   
                Dispatch.call(this.selection,"MoveDown");   
            }   
        }    
      
        /**   
         * 把选定内容或插入点向左移动   
         * @param count 移动的距离   
         */    
        public void moveLeft(int count) {    
      
            logger.debug("把选定内容或插入点向左移动...");   
            for(int i = 0;i < count;i++) {   
                Dispatch.call(this.selection,"MoveLeft");   
            }   
        }    
      
        /**   
         * 把选定内容或插入点向右移动   
         * @param count 移动的距离   
         */    
        public void moveRight(int count) {    
      
            logger.debug("把选定内容或插入点向右移动...");   
            for(int i = 0;i < count;i++) {   
                Dispatch.call(this.selection,"MoveRight");   
            }   
        }   
           
        /**  
         * 回车键  
         */  
        public void enterDown(int count){   
               
            logger.debug("按回车键...");   
            for(int i = 0;i < count;i++) {   
                Dispatch.call(this.selection, "TypeParagraph");   
            }   
        }   
      
        /**   
         * 把插入点移动到文件首位置   
         */    
        public void moveStart() {    
      
            logger.debug("把插入点移动到文件首位置...");   
            Dispatch.call(this.selection,"HomeKey",new Variant(6));    
        }    
      
        /**   
         * 从选定内容或插入点开始查找文本   
         * @param selection 选定内容   
         * @param toFindText 要查找的文本   
         * @return boolean true-查找到并选中该文本,false-未查找到文本   
         */    
        public boolean find(String toFindText) {    
      
            logger.debug("从选定内容或插入点开始查找文本"+" 要查找内容:  "+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 selection 选定内容   
         * @param newText 替换为文本   
         */    
        public void replace(String newText) {    
      
            logger.debug("把选定内容替换为设定文本...");   
            /* 设置替换文本 */  
            Dispatch.put(this.selection,"Text",newText);    
        }    
      
        /**   
         * 全局替换   
         * @param selection 选定内容或起始插入点   
         * @param oldText 要替换的文本   
         * @param replaceObj 替换为文本  
         */    
        public void replaceAll(String oldText,Object replaceObj) {    
      
            logger.debug("全局替换...");   
            /* 移动到文件开头 */  
            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 selection 图片的插入点   
         * @param imagePath 图片文件(全路径)   
         */    
        public void insertImage(String imagePath) {    
      
            logger.debug("插入图片...");   
            Dispatch.call(this.selection, "TypeParagraph");   
            Dispatch.call(Dispatch.get(this.selection,"InLineShapes").toDispatch

    (),"AddPicture",imagePath);    
        }    
      
        /**  
         * 合并表格  
         *  
         * @param selection 操作对象  
         * @param tableIndex 表格起始点  
         * @param fstCellRowIdx 开始行  
         * @param fstCellColIdx 开始列  
         * @param secCellRowIdx 结束行  
         * @param secCellColIdx 结束列  
         */  
        public void mergeCell(int tableIndex, int fstCellRowIdx, int fstCellColIdx, int

    secCellRowIdx, int secCellColIdx){   
      
            logger.debug("合并单元格...");   
            if(this.table == null){   
                logger.warn("table对象为空...");   
                return;   
            }   
            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);   
        }   
      
        /**  
         * 想Table对象中插入数值<p>  
         *     参数形式:ArrayList<String[]>List.size()为表格的总行数<br>  
         *     String[]的length属性值应该与所创建的表格列数相同  
         *   
         * @param selection 插入点  
         * @param tableIndex 表格起始点  
         * @param list 数据内容  
         */  
        public void insertToTable(List<String[]> list){   
      
            System.out.println("向Table对象中插入数据...");   
            logger.debug("向Table对象中插入数据...");   
            if(list == null || list.size() <= 0){   
                logger.warn("写出数据集为空...");   
                return;   
            }   
            if(this.table == null){   
                logger.warn("table对象为空...");   
                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 selection 插入点  
         * @param list 数据内容  
         */  
        public void insertToDocument(List<String> list){   
      
            logger.debug("向Document对象中插入数据...");   
            if(list == null || list.size() <= 0){   
                logger.warn("写出数据集为空...");   
                return;   
            }   
            if(this.document == null){   
                logger.warn("document对象为空...");   
                return;   
            }   
            for(String str : list){   
                /* 写出至word中 */  
                this.applyListTemplate(3, 2);   
                Dispatch.put(this.selection, "Text", str);   
                this.moveDown(1);   
                this.enterDown(1);   
            }   
        }   
      
        /**  
         * 创建新的表格  
         *   
         * @param selection 插入点  
         * @param document 文档对象  
         * @param rowCount 行数  
         * @param colCount 列数  
         * @param width 边框数值 0浅色1深色  
         * @return 新创建的表格对象  
         */  
        public Dispatch createNewTable(int rowCount, int colCount, int width){   
      
            logger.debug("创建新的表格...");   
            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对象中的所有Table对象  
         *   
         * @return 所有Table对象  
         */  
        public Dispatch getTables(){   
      
      
            logger.debug("获取所有表格对象...");   
            if(this.document == null){   
                logger.warn("document对象为空...");   
                return this.tables;   
            }   
            this.tables = Dispatch.get(this.document, "Tables").toDispatch();   
            return this.tables;   
        }   
           
        /**  
         * 获取Document中Table的数量  
         *   
         * @return 表格数量  
         */  
        public int getTablesCount(){   
               
            logger.debug("获取文档中表格数量...");   
            if(this.tables == null){   
                this.getTables();   
            }   
            return Dispatch.get(tables, "Count").getInt();   
               
        }   
      
        /**  
         * 获取指定序号的Table对象  
         *   
         * @param tableIndex Table序列  
         * @return  
         */  
        public Dispatch getTable(int tableIndex){   
      
            logger.debug("获取指定表格对象...");   
            if(this.tables == null){   
                this.getTables();   
            }   
            if(tableIndex >= 0){   
                this.table = Dispatch.call(this.tables, "Item", new Variant(tableIndex)).toDispatch();

      
            }   
            return this.table;   
        }   
      
        /**  
         * 获取表格的总列数  
         *   
         * @return 总列数  
         */  
        public int getTableColumnsCount() {   
      
            logger.debug("获取表格总行数...");   
            if(this.table == null){   
                logger.warn("table对象为空...");   
                return 0;   
            }   
            return Dispatch.get(this.cols,"Count").getInt();   
        }   
      
        /**  
         * 获取表格的总行数  
         *   
         * @return 总行数  
         */  
        public int getTableRowsCount(){   
      
            logger.debug("获取表格总行数...");   
            if(this.table == null){   
                logger.warn("table对象为空...");   
                return 0;   
            }   
            return Dispatch.get(this.rows,"Count").getInt();   
        }   
        /**  
         * 获取表格列对象  
         *   
         * @return 列对象  
         */  
        public Dispatch getTableColumns() {   
      
            logger.debug("获取表格行对象...");   
            if(this.table == null){   
                logger.warn("table对象为空...");   
                return this.cols;   
            }   
            this.cols = Dispatch.get(this.table,"Columns").toDispatch();   
            return this.cols;   
        }   
      
      
        /**  
         * 获取表格的行对象  
         *   
         * @return 总行数  
         */  
        public Dispatch getTableRows(){   
      
            logger.debug("获取表格总行数...");   
            if(this.table == null){   
                logger.warn("table对象为空...");   
                return this.rows;   
            }   
            this.rows = Dispatch.get(this.table,"Rows").toDispatch();   
            return this.rows;   
        }   
      
        /**  
         * 获取指定表格列对象  
         *   
         * @return 列对象  
         */  
        public Dispatch getTableColumn(int columnIndex) {   
      
            logger.debug("获取指定表格行对象...");   
            if(this.cols == null){   
                this.getTableColumns();   
            }   
            if(columnIndex >= 0){   
                this.col = Dispatch.call(this.cols, "Item", new Variant(columnIndex)).toDispatch();   
            }   
            return this.col;   
        }   
      
        /**  
         * 获取表格中指定的行对象  
         *   
         * @param rowIndex 行序号  
         * @return 行对象  
         */  
        public Dispatch getTableRow(int rowIndex){   
      
            logger.debug("获取指定表格总行数...");   
            if(this.rows == null){   
                this.getTableRows();   
            }   
            if(rowIndex >= 0){   
                this.row = Dispatch.call(this.rows, "Item", new Variant(rowIndex)).toDispatch();   
            }   
            return this.row;   
        }   
           
        /**  
         * 自动调整表格  
         */  
        public void autoFitTable() {   
               
            logger.debug("自动调整表格...");   
            int count = this.getTablesCount();   
            for (int i = 0; i < count; i++) {   
                Dispatch table = Dispatch.call(tables, "Item", new Variant(i + 1)).toDispatch();   
                Dispatch cols = Dispatch.get(table, "Columns").toDispatch();   
                Dispatch.call(cols, "AutoFit");   
            }   
        }   
      
        /**  
         * 获取当前文档中,表格中的指定单元格  
         *  
         * @param CellRowIdx  单元格所在行  
         * @param CellColIdx 单元格所在列  
         * @return 指定单元格对象  
         */  
        public Dispatch getCell(int cellRowIdx, int cellColIdx) {   
      
               
            logger.debug("获取当前文档中,表格中的指定单元格...");   
            if(this.table == null){   
                logger.warn("table对象为空...");   
                return this.cell;   
            }   
            if(cellRowIdx >= 0 && cellColIdx >=0){   
                this.cell = Dispatch.call(this.table, "Cell", new Variant(cellRowIdx),new Variant

    (cellColIdx)).toDispatch();   
            }   
            return this.cell;   
        }   
      
        /**  
         * 设置文档标题  
         *   
         * @param title 标题内容  
         */  
        public void setTitle(String title){   
               
            logger.debug("设置文档标题...");   
            if(title == null || "".equals(title)){   
                logger.warn("文档标题为空...");   
                return;   
            }   
            Dispatch.call(this.selection, "TypeText", title);    
        }   
           
        /**  
         * 设置当前表格线的粗细  
         *  
         * @param width  
         *        width范围:1<w<13,如果是0,就代表没有框  
         */  
        public void setTableBorderWidth(int width) {   
      
            logger.debug("设置当前表格线的粗细...");   
            if(this.table == null){   
                logger.warn("table对象为空...");   
                return;   
            }   
            /*  
             * 设置表格线的粗细 1:代表最上边一条线 2:代表最左边一条线 3:最下边一条线 4

    :最右边一条线 5:除最上边最下边之外的所有横线  
             * 6:除最左边最右边之外的所有竖线 7:从左上角到右下角的斜线 8:从左下角到右上

    角的斜线  
             */  
            Dispatch borders = Dispatch.get(table, "Borders").toDispatch();   
            Dispatch border = null;   
            for (int i = 1; i < 7; i++) {   
                border = Dispatch.call(borders, "Item", new Variant(i)).toDispatch();   
                if (width != 0) {   
                    Dispatch.put(border, "LineWidth", new Variant(width));   
                    Dispatch.put(border, "Visible", new Variant(true));   
                } else if (width == 0) {   
                    Dispatch.put(border, "Visible", new Variant(false));   
                }   
            }   
        }   
           
        /**  
         * 对当前selection设置项目符号和编号  
         * @param tabIndex  
         *     1: 项目编号  
         *     2: 编号  
         *     3: 多级编号  
         *     4: 列表样式  
         * @param index  
         *     0:表示没有 ,其它数字代表的是该Tab页中的第几项内容  
         */  
        public void applyListTemplate(int tabIndex,int index){   
      
            logger.debug("对当前selection设置项目符号和编号...");   
            /* 取得ListGalleries对象列表 */  
            Dispatch listGalleries = Dispatch.get(this.word, "ListGalleries").toDispatch();   
            /* 取得列表中一个对象 */  
            Dispatch listGallery = Dispatch.call(listGalleries, "Item", new Variant

    (tabIndex)).toDispatch();   
            Dispatch listTemplates = Dispatch.get(listGallery, "ListTemplates").toDispatch();   
            if(this.range == null){   
                this.getRange();   
            }   
            Dispatch listFormat = Dispatch.get(this.range, "ListFormat").toDispatch();   
            Dispatch.call(listFormat,"ApplyListTemplate",Dispatch.call(listTemplates, "Item", new

    Variant(index)), new Variant(true),new Variant(1),new Variant(0));   
        }   
           
        /**  
         * 增加文档目录  
         *  
         * 目前采用固定参数方式,以后可以动态进行调整  
         */  
        public void addTablesOfContents()   
        {   
          /* 取得ActiveDocument、TablesOfContents、range对象 */  
          Dispatch ActiveDocument = word.getProperty("ActiveDocument").toDispatch();   
          Dispatch TablesOfContents = Dispatch.get

    (ActiveDocument,"TablesOfContents").toDispatch();   
          Dispatch range = Dispatch.get(this.selection, "Range").toDispatch();   
          /* 增加目录 */    
          Dispatch.call(TablesOfContents,"Add",range,new Variant(true),new Variant(1),new

    Variant(3),new Variant(true),new Variant(""),new Variant(true),new Variant(true));   
           
        }   
      
           
        /**  
         * 设置当前Selection 位置方式  
         * @param selectedContent 0-居左;1-居中;2-居右。  
         */  
        public void setAlignment(int alignmentType) {   
               
            logger.debug("设置当前Selection 位置方式...");   
            if(this.alignment == null){   
                this.getAlignment();   
            }   
            Dispatch.put(this.alignment, "Alignment", alignmentType);   
        }   
           
        /**  
         * 获取当前选择区域的对齐方式  
         *   
         * @return 对其方式对象  
         */  
        public Dispatch getAlignment(){   
               
            logger.debug("获取当前选择区域的对齐方式...");   
            if(this.selection == null){   
                this.getSelection();   
            }   
            this.alignment = Dispatch.get(this.selection, "ParagraphFormat").toDispatch();   
            return this.alignment;   
        }   
           
        /**  
         * 获取字体对象  
         *   
         * @return 字体对象  
         */  
        public Dispatch getFont(){   
               
            logger.debug("获取字体对象...");   
            if(this.selection == null){   
                this.getSelection();   
            }   
            this.font = Dispatch.get(this.selection, "Font").toDispatch();   
            return this.font;   
        }   
           
        /**  
         * 设置选定内容的字体 注:在调用此方法前,选定区域对象selection必须存在  
         *  
         * @param fontName  
         *            字体名称,例如 "宋体"  
         * @param isBold  
         *            粗体  
         * @param isItalic  
         *            斜体  
         * @param isUnderline  
         *            下划线  
         * @param rgbColor  
         *            颜色,例如"255,255,255"  
         * @param fontSize  
         *            字体大小  
         * @param Scale  
         *            字符间距,百分比值。例如 70代表缩放为70%  
         */  
        public void setFontScale(String fontName, boolean isBold, boolean isItalic, boolean

    isUnderline, String rgbColor, int Scale, int fontSize) {   
               
            logger.debug("设置字体...");   
            Dispatch.put(this.font, "Name", fontName);   
            Dispatch.put(this.font, "Bold", isBold);   
            Dispatch.put(this.font, "Italic", isItalic);   
            Dispatch.put(this.font, "Underline", isUnderline);   
            Dispatch.put(this.font, "Color", rgbColor);   
            Dispatch.put(this.font, "Scaling", Scale);   
            Dispatch.put(this.font, "Size", fontSize);   
        }   
           
        /**   
         * 保存文件   
         * @param outputPath 输出文件(包含路径)   
         */    
        public void saveAs(String outputPath) {    
      
            logger.debug("保存文件...");   
            if(this.document == null){   
                logger.warn("document对象为空...");   
                return;   
            }   
            if(outputPath ==null || "".equals(outputPath)){   
                logger.warn("文件保存路径为空...");   
                return;   
            }   
            Dispatch.call(this.document,"SaveAs",outputPath);    
        }   
           
        public void saveAsHtml(String htmlFile){   
            Dispatch.invoke(this.document,"SaveAs",Dispatch.Method, new Object[]{htmlFile,new

    Variant(8)}, new int[1]);   
        }   
      
        /**   
         * 关闭文件   
         * @param document 要关闭的文件   
         */    
        public void close() {   
      
            logger.debug("关闭文件...");   
            if(document == null){   
                logger.warn("document对象为空...");   
                return;   
            }   
            Dispatch.call(document,"Close",new Variant(0));    
        }   
      
        /**  
         * 列印word文件  
         *  
         */  
        public void printFile(){   
            logger.debug("打印文件...");   
            if(document == null){   
                logger.warn("document对象为空...");   
                return;   
            }   
            Dispatch.call(document,"PrintOut");   
        }   
      
        /**   
         * 退出程序   
         */    
        public void quit() {    
      
            logger.debug("退出程序");   
            word.invoke("Quit",new Variant[0]);    
            ComThread.Release();    
        }   
      
        public static void main(String args[]){   
            DOCWriter writer = new DOCWriter();   
            writer.createNewDocument();   
            List<String[]> listTable = new ArrayList<String[]>();   
            for(int i = 0 ; i<10; i++){   
                String str[] = new String[4];   
                for(int j = 0 ; j<4; j++){   
                    str[j] = String.valueOf(j);   
                }   
                listTable.add(str);   
            }   
            writer.setFontScale("宋体", false, false,false, "1,1,1,1", 70, 14);   
            List<String> list = new ArrayList<String>();    
            list.add("忘记你我做不到");   
            list.add("不去天涯海角");   
            list.add("在我身边就好");   
            list.add("如果爱是痛苦的泥沼");   
            list.add("让我们一起逃");   
            list.add("忘记你我做不到");   
            list.add("不去天涯海角");   
            list.add("在我身边就好");   
            list.add("如果爱是痛苦的泥沼");   
            list.add("让我们一起逃");   
            writer.moveDown(3);   
            writer.setAlignment(0);   
            writer.setTitle("Test");   
            writer.insertImage("E://test.jpg");   
            writer.enterDown(1);   
            writer.insertToDocument(list);   
            writer.setFontScale("幼圆", true, true,true, "1,1,1,1", 70, 14);   
            writer.createNewTable(10, 5, 0);   
            writer.insertToTable(listTable);   
            writer.setFontScale("华文仿宋", true, true,false, "1,1,1,1", 70, 14);   
            writer.createNewTable(10, 5, 0);   
            writer.insertToTable(listTable);   
            writer.setFontScale("华文新魏", true, false,false, "100,1,1,1", 70, 14);   
            writer.insertToDocument(list);   
    //      writer.saveAsHtml("E://test.html");   
            writer.saveAs("E://TestDocBenjamin.doc");   
    //      writer.close();   
        }   
      

     

    cob操作word

    import java.io.BufferedInputStream;
    import java.io.BufferedOutputStream;
    import java.io.Closeable;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.util.List;
    import java.util.UUID;

    import org.apache.commons.lang.SystemUtils;

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

    /**
     *
     * 类:  <code> WordUtils </code>
     * 功能描述:
     * 创建人: 王星乐
     * 创建日期: 2013-8-2 上午10:02:23
     * 开发环境: JDK6.0
     */
    public class WordUtils {
     /**
      *
      * 功能描述: 将word转换为pdf,注意此方法不会关闭is和os
      * @param is 输入流
      * @param os 输出流
      */
     public static void convertToPdf(InputStream is, OutputStream os) {
      ActionCallBack action = new ActionCallBack() {

       @Override
       public void execute(String srcFilePath, String destFilePath) {
        int wdFormatPDF = 17;// PDF 格式
        ActiveXComponent app = null;
        Dispatch doc = null;
        try {
         app = new ActiveXComponent

    ("Word.Application");
         app.setProperty("Visible", new Variant

    (false));
         Dispatch docs = app.getProperty

    ("Documents").toDispatch();
         doc = Dispatch.call(docs, "Open",

    srcFilePath).toDispatch();
         Dispatch.call(doc, "SaveAs", destFilePath,

    wdFormatPDF);
         Dispatch.call(doc, "Close", false);
        } catch (Throwable e) {
         throw new RuntimeException(e);
        } finally {
         if (app != null) {
          app.invoke("Quit", new Variant[]

    {});
         }

         ComThread.Release();
        }

       }
      };

      process(is, os, ".doc", ".pdf", action);
     }

     /**
      *
      * 功能描述: 将word转换为html,注意此方法不会关闭is和os
      * @param is 输入流
      * @param os 输出流
      */
     public static void convertToHtml(InputStream is, String path) {
      //临时文件目录
      File tempDir = new File(SystemUtils.getJavaIoTmpDir().getAbsolutePath

    (), "wordTemp");

      if (!tempDir.exists()) {
       tempDir.mkdir();
      }

      File srcFile = new File(tempDir, UUID.randomUUID().toString() + ".doc");
      if (srcFile.exists()) {
       srcFile.delete();
      }

      File destFile = new File(tempDir, path);
      if (destFile.exists()) {
       destFile.delete();
      }

      //从输入流生成src文件
      OutputStream srcOs = null;
      try {
       srcOs = new BufferedOutputStream(new FileOutputStream

    (srcFile));
       copy(is, srcOs);
      } catch (Throwable e) {
       throw new RuntimeException(e);
      } finally {
       close(srcOs);
      }

      int wdFormatHTML = 8;// HTML 格式
      ActiveXComponent app = null;
      Dispatch doc = null;
      try {
       app = new ActiveXComponent("Word.Application");
       app.setProperty("Visible", new Variant(false));
       Dispatch docs = app.getProperty("Documents").toDispatch();
       doc = Dispatch.call(docs, "Open", srcFile.getAbsolutePath

    ()).toDispatch();
       Dispatch.call(doc, "SaveAs", path, wdFormatHTML);
       Dispatch.call(doc, "Close", false);
      } catch (Throwable e) {
       throw new RuntimeException(e);
      } finally {
       if (app != null) {
        app.invoke("Quit", new Variant[] {});
       }

       ComThread.Release();
      }

     }

     /**
      *
      * 功能描述: 替换书签,注意此方法不会关闭is和os
      * @param is 输入流
      * @param os 输出流
      * @param bookmarkList 书签集合
      * @param dataList 替换内容集合
      */
     public static void replaceBookmarks(InputStream is, OutputStream os, final

    List<String> bookmarkList,
       final List<String> dataList) {
      ActionCallBack action = new ActionCallBack() {

       @Override
       public void execute(String srcFilePath, String destFilePath) {
        ActiveXComponent app = null;
        Dispatch doc = null;
        try {
         app = new ActiveXComponent

    ("Word.Application");
         app.setProperty("Visible", new Variant

    (false));
         Dispatch documents = app.getProperty

    ("Documents").toDispatch();
         doc = Dispatch.call(documents, "Open",

    srcFilePath).toDispatch();
         Dispatch activeDocument =

    app.getProperty("ActiveDocument").toDispatch();
         Dispatch bookMarks = Dispatch.call

    (activeDocument, "Bookmarks").toDispatch();

         //替换书签
         for (int i = 0; i < bookmarkList.size(); i++)

    {
          boolean bookMarkExist =

    Dispatch.call(bookMarks, "Exists", bookmarkList.get(i)).changeType(
            

    Variant.VariantBoolean).getBoolean();
          if (bookMarkExist == true) {
           Dispatch rangeItem =

    Dispatch.call(bookMarks, "Item", bookmarkList.get(i)).toDispatch();
           Dispatch range =

    Dispatch.call(rangeItem, "Range").toDispatch();
           Dispatch.put(range,

    "Text", new Variant(dataList.get(i)));
          }
         }

         Dispatch.call(doc, "SaveAs", destFilePath);
         Dispatch.call(doc, "Close", false);
        } catch (Throwable e) {
         throw new RuntimeException(e);
        } finally {
         if (app != null) {
          app.invoke("Quit", new Variant[]

    {});
         }

         ComThread.Release();
        }
       }
      };

      process(is, os, ".doc", ".doc", action);
     }

     /**
      *
      * 功能描述: 模板方法,做初始化工作,调用回调函数,执行清理工作。
      * @param is
      * @param os
      * @param srcFileExtension
      * @param destFileExtension
      * @param action
      */
     public static void process(InputStream is, OutputStream os, String srcFileExtension,

    String destFileExtension,
       ActionCallBack action) {
      //临时文件目录
      File tempDir = new File(SystemUtils.getJavaIoTmpDir().getAbsolutePath

    (), "wordTemp");

      if (!tempDir.exists()) {
       tempDir.mkdir();
      }

      File srcFile = new File(tempDir, UUID.randomUUID().toString() +

    srcFileExtension);
      if (srcFile.exists()) {
       srcFile.delete();
      }

      File destFile = new File(tempDir, UUID.randomUUID().toString() +

    destFileExtension);
      if (destFile.exists()) {
       destFile.delete();
      }

      //从输入流生成src文件
      OutputStream srcOs = null;
      try {
       srcOs = new BufferedOutputStream(new FileOutputStream

    (srcFile));
       copy(is, srcOs);
      } catch (Throwable e) {
       throw new RuntimeException(e);
      } finally {
       close(srcOs);
      }

      action.execute(srcFile.getAbsolutePath(), destFile.getAbsolutePath());

      //拷贝dest文件到输出流
      InputStream destIs = null;

      try {
       destIs = new BufferedInputStream(new FileInputStream

    (destFile));
       copy(destIs, os);
      } catch (IOException e) {
       throw new RuntimeException(e);
      } finally {
       close(destIs);
      }

      //删除临时文件
      if (srcFile.exists()) {
       srcFile.delete();
      }

      if (destFile.exists()) {
       destFile.delete();
      }
     }

     private interface ActionCallBack {
      void execute(String srcFilePath, String destFilePath);
     }

     /**
      *
      * 功能描述: 将输入流的数据拷贝到输出流
      * @param is
      * @param os
      * @throws IOException
      */
     private static void copy(InputStream is, OutputStream os) throws IOException {
      int len = 0;
      byte[] buffer = new byte[1024 * 4];
      while (-1 != (len = is.read(buffer))) {
       os.write(buffer, 0, len);
      }
     }

     /**
      *
      * 功能描述: 关闭流
      * @param s
      */
     private static void close(Closeable s) {
      if (s != null) {
       try {
        s.close();
       } catch (IOException e) {
        //忽略
       }
      }
     }
    }

    //0:Microsoft Word 97 - 2003 文档 (.doc)
        //1:Microsoft Word 97 - 2003 模板 (.dot)
        //2:文本文档 (.txt)
        //3:文本文档 (.txt)
        //4:文本文档 (.txt)
        //5:文本文档 (.txt)
        //6:RTF 格式 (.rtf)
        //7:文本文档 (.txt)
        //8:HTML 文档 (.htm)(带文件夹)
        //9:MHTML 文档 (.mht)(单文件)
        //10:MHTML 文档 (.mht)(单文件)
        //11:XML 文档 (.xml)
        //12:Microsoft Word 文档 (.docx)
        //13:Microsoft Word 启用宏的文档 (.docm)
        //14:Microsoft Word 模板 (.dotx)
        //15:Microsoft Word 启用宏的模板 (.dotm)
        //16:Microsoft Word 文档 (.docx)
        //17:PDF 文件 (.pdf)
        //18:XPS 文档 (.xps)
        //19:XML 文档 (.xml)
        //20:XML 文档 (.xml)
        //21:XML 文档 (.xml)
        //22:XML 文档 (.xml)
        //23:OpenDocument 文本 (.odt)
        //24:WTF 文件 (.wtf)


     

    用Java操作Office 2007 

    转自:http://www.infoq.com/cn/articles/cracking-office-2007-with-java

    Office 2007平台作为一个构建富客户端应用程序的基本平台,并通过不同的手段使用Java来进行互操作。 但是,有一个Office/Java互操作的方面没有考虑到,那就是使Office和Java共同工作,也就是说让Java应用程序来操作Office文档:比如创建文档,编辑文档,收集数据等等。

    从以往看来,这其中经常会出现一些问题,这是由于Office文档(主要是Word,Excel和PowerPoint)是存储在一个二进制格式文件中,在COM中被称为结构化存储格式, 是一个通过COM接口的层次化二进制格式。 对COM开发者(或者其他使用COM相关语言的开发者,如Visual Basic, Delphi 和C++/ATL)而言非常方便,但产生的文件对于那些不能“讲COM”的语言是无法访问的。有许许多多的应用程序都是为了让Java语言可以访问这些文件的内容;比如大家都知道Excel可以读取逗号分隔符文件(CSV),因此,Java应用程序相应将数据导出到Excel友好的格式时一般会选用CSV格式(或是其他丑陋的格式)。Word则是可以读取富文本格式(RTF)文件,而RTF标准是公开和有详细文档的。Office的后来者,Office 2003,引入了一个新的XML格式(WordML),Java开发者可以用它来读写Office文档,但是这些格式并没有很好的文档,Java开发者频繁的发现自己是通过试错法来进行WordML格式的学习。 各种各样的开源项目都参与进来想要解决这个问题,比如Apache的POI框架,可以用来读写Excel文档,还有各种各样的Java-COM解决方案,这些解决方案一般倾向于使用和Office自己使用的结构化存储应用程序接口相同的应用程序接口进行Excel文档的读写,但很难满足需要,直到现在,开发者不得不指出Office文档格式的内部结构是一个非常复杂的结构,另外一点毋庸置疑的是它是一个没有完整文档的结构。

    总体上来说,如果温和一点说的话,Java/Office的故事是一个非常讨厌的境况。对于Java的开发人员而言,他们要么一边嘴里说着“Office这种破东西怎么还会有人想去用它”一边用记忆里的伊索寓言来安慰自己,要么干脆告诉那些使用Office的客户由于Microsoft和Sun两家公司之间的诉讼,Java不能操作Office。

    对于Office 2007来说,微软毫无疑问的迈出了解决这些问题的一大步。没有比原始的JDK更复杂的东西---也就是说并不要求使用一些第三方的库---Java应用程序现在可以读写任何Office 2007的文档,这是由于Office 2007文档现在使用的是XML文档的ZIP格式文件。 这种格式被称作“OpenMXL”规范并且已经被提交到欧洲计算机制造商协会(ECMA),这个协会同样拥有C#语言和CLI运行时规范,所有的OpenXML规范现在都可以被任何人自由的从ECMA的网站下载。 除了这些,再安装好Office 2007(为了验证和作一些测试)和一个标准的Java6 JDK安装,Java现在可以打开任何的Office 2007文档,找出来文档中间的内容,操作它们,并且再次保存这些数据。

    与上篇文章不同,在这篇文章中,除了创建一个简单的应用程序之外,代码将会使用一种首先由Stuart Halloway提出的、被称作探索测试(exploration testing)的技术。在一个探索测试中,开发者编写单元测试用来探索应用程序接口,使用单元测试世界中的断言验证结果的正确性。探索测试带来的好处是当一个新版本的应用程序接口可用时---在这个例子中,可能是一个新版本的Office---运行这些测试可以用来确认新版本的采用不会影响到原本对应用程序接口的使用。

    对于初学者来说,让我们首先快速的了解一下Office 2007文档。首先看一个仅仅包含文本的Word 2007文档,就像下面一样:


    当保存的时候,使用Word 2007将它保存为“Hello.docx”,除非你使用了向后兼容格式,比如说Office 2003的WordML格式,或者是更老的Word 97二进制结构化存储格式。“.docx”文件是OpenXML格式的,微软的文档中声称该格式是XML文档的ZIP压缩格式文件,这些文件中包含了文档中的数据和格式,存储的方式与之前的Office版本中的二进制结构化存储应用程序接口存储数据的方式有些类似。如果这是真的,那么使用Java中提供的用来处理ZIP和TAR格式的“jar”实用工具应该可以展示这些内容,而事实上,它的确可以:


    Word 2007文档的基本格式已经非常明显了,仅仅通过控制台的输出就可以看到。(事实上,“jar”实用工具所展示的这激动人心的一切,说明java.util.jar和/或 java.util.zip包同样可以简单的访问这些内容。)几乎没有对规范作任何的破解,很明显,文档中的主要内容应该被存储到了“document.xml”文件中,剩余的其他XML文件则应该是各种各样的辅助部分,比如文档中应用到的字体(fontTable.xml)和使用到的Office主题(theme/theme1.xml),等等。

    是时间来编写一些探索测试了。(我们鼓励感兴趣的读者打开一个文本编辑器或者集成开发环境,并将下面的内容填入你的JUnit 4测试类当中,并且扩展这些测试。) 使用JUnit 4,第一个测试是为了简单的确认文件在我们预想的位置(显然这是下面测试可以运行的一个必要的需求)。

    @Test public void verifyFileIsThere() {
      assertTrue(new File("hello.docx").exists());
      assertTrue(new File("hello.docx").canRead());
      assertTrue(new File("hello.docx").canWrite());
    } 

    下面的测试简单的验证了我们可以使用Java库中的java.util.zip.ZipFile来打开这个文件:

    @Test public void openFile()
      throws IOException, ZipException
    {
      ZipFile docxFile =
        new ZipFile(new File("hello.docx"));
      assertEquals(docxFile.getName(), "hello.docx");
    } 

    现在一切看来都非常不错。Java的ZipFile类正确的识别了我们的文件,一个zip文件,如果我们还能继续保持这样的运气,让我们继续我们的测试,来遍历一下,识别文档中的内容并找出其中的数据。让我们编写一个快速的测试来从“document.xml”文件中找出所有的内容。

    @Test public void listContents()
      throws IOException, ZipException
    {
      boolean documentFound = false;
    
      ZipFile docxFile = 
        new ZipFile(new File("hello.docx"));
      Enumeration entriesIter =
        docxFile.entries();
      while (entriesIter.hasMoreElements())
      {
        ZipEntry entry = entriesIter.nextElement();
    
        if (entry.getName().equals("document.xml"))
          documentFound = true;
      }
      assertTrue(documentFound);
    }

    令人诧异的是,当我们运行测试的时候,测试过程产生了一个失败;并没有找到“document.xml”文件,这是由于ZipFile/ZipEntry 应用程序接口需要压缩文件中完整的路径名称。将测试中的路径改为“word/document.xml”,测试就通过了。

    很好,我们已经找到文件了,下面让我们打开这个文件看看XML里面是什么。这非常简单,因为ZipFile有一个返回ZipEntry的应用程序接口。

    @Test public void getDocument()
      throws IOException, ZipException
    {
      ZipFile docxFile = 
        new ZipFile(new File("hello.docx"));
      ZipEntry documentXML =
        docxFile.getEntry("word/document.xml");
      assertNotNull(documentXML);
    }

    ZipFile代码可以返回它包含的实体内容,通过调用getInputStream()方法即可,不要对InputStream产生任何怀疑。将InputStream发送到一个DOM节点中就可以创建一个关于该文档的DOM。

    @Test public void fromDocumentIntoDOM()
      throws IOException, ZipException, SAXException,
             ParserConfigurationException
    {
      ZipFile docxFile =
        new ZipFile(new File("hello.docx"));
      ZipEntry documentXML =
        docxFile.getEntry("word/document.xml");
      InputStream documentXMLIS =
        docxFile.getInputStream(documentXML);
      DocumentBuilderFactory dbf =
        DocumentBuilderFactory.newInstance();
      Document doc =
        dbf.newDocumentBuilder().parse(documentXMLIS);
    
      assertEquals("[w:document: null]",
                   doc.getDocumentElement().toString());
    }

    事实上,与其他支持各种Word所需格式的XML文档相比,document.xml文件的内容(为了明显起见,将命名空间声明等内容去除)看起来也相当乏味:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
     <w:document ...>
     <w:body>
     <w:p w:rsidR="00DE36E5" w:rsidRDefault="00DE36E5">
     <w:r>
     <w:t>Hello, from Office 2007!</w:t>
     </w:r>
     </w:p>
     <w:sectPr w:rsidR="00DE36E5">
     <w:pgSz w:w="12240" w:h="15840"/>
     <w:pgMar w:top="1440" w:right="1440" w:bottom="1440" w:left="1440" w:header="720" w:footer="720" w:gutter="0"/>
     <w:cols w:space="720"/>
     <w:docGrid w:linePitch="360"/>
     </w:sectPr>
     </w:body>
     </w:document> 

    关于文档中各个元素具体代表什么内容的细节已经超出了这篇文章的讨论范围,读者可以查阅OpenXML文档的具体内容来获得参考,但是文档中的主要内容是十分明显的。比如说文档中包括“p”元素(段落),包括“r”元素(文本区),包括“t”元素(文本),在本例的hello.docx文档中,单句“Hello from Office 2007”就是由这些元素构成的。

    读过文件的内容后,现在可以来修改这些内容了,将其写到文件中,并用Word 2007打开它。快速的查看ZipFile和ZipEntry的应用程序接口可以发现这样一个问题:尽管这些类可以用来读取一个zip文件,但它们并不能写入或创建它们。

    有很多可用的方法可以用于解决这个问题。一个简单的方法是将XML文件的内容文本写到一个字符串中,并将这个字符串存储到document.xml文件中,然后重新使用ZipOutStream类压缩所有的内容。另一个方法是使用一些可以编辑zip文件内容的第三方工具(或创建一个),但这些已经脱离了JDK的基本内容,所以在这篇文章中我们将使用ZipOutStream方法。

    为了达到我们的目的,我们需要做很多事情。首先,Java应用程序必须定位到DOM的层次结构中,找到“t”节点,然后将它的文本内容替换为我们要写入到Word文档中的内容。(“Hello,Office 2007,from Java6!”是个不错的选择)产生的新DOM实例必须要保存到磁盘中,使用Java XML 应用程序接口时这并不是一个简单的任务。(简单的说来,开发者需要从javax.xml.transform包中创建一个Transformer,然后将XML转换为一个StreamResult,再交由ByteArrayOutputStream处理。)

    一旦上面这些事情都处理完毕后,代码必须要产生一个ZIP格式的文件,是时候使用ZipOutputStream了,但由于只需要改变文档的内容,而不需要改变它的样式、字体以及格式,其他的部分可以从原始的文件中拷贝过来。使用一个简单的循环,遍历原始文件中的ZipEntries中所有的内容(除了word/document.xml,该文件中的内容需要被改变)并将其导出到一个新的ZipEntry中并写入该实体就足够了。当所有的工作都完成后,代码将会是以下的样子:

    @Test public void modifyDocumentAndSave()
      throws IOException, ZipException, SAXException,
             ParserConfigurationException,
             TransformerException,
             TransformerConfigurationException
    {
      ZipFile docxFile =
        new ZipFile(new File("hello.docx"));
      ZipEntry documentXML =
        docxFile.getEntry("word/document.xml");
      InputStream documentXMLIS =
        docxFile.getInputStream(documentXML);
      DocumentBuilderFactory dbf =
        DocumentBuilderFactory.newInstance();
      Document doc =
        dbf.newDocumentBuilder().parse(documentXMLIS);
    
      Element docElement = doc.getDocumentElement();
      assertEquals("w:document", docElement.getTagName());
    
      Element bodyElement = (Element)
        docElement.getElementsByTagName("w:body").item(0);
      assertEquals("w:body", bodyElement.getTagName());
    
      Element pElement = (Element)
        bodyElement.getElementsByTagName("w:p").item(0);
      assertEquals("w:p", pElement.getTagName());
    
      Element rElement = (Element)
        pElement.getElementsByTagName("w:r").item(0);
      assertEquals("w:r", rElement.getTagName());
    
      Element tElement = (Element)
        rElement.getElementsByTagName("w:t").item(0);
      assertEquals("w:t", tElement.getTagName());
    
      assertEquals("Hello, from Office 2007!",
                   tElement.getTextContent());
    
      tElement.setTextContent(
        "Hello, Office 2007, from Java6!");
    
      Transformer t =
        TransformerFactory.newInstance().newTransformer();
      ByteArrayOutputStream baos =
        new ByteArrayOutputStream();
      t.transform(new DOMSource(doc),
        new StreamResult(baos));
    
      ZipOutputStream docxOutFile = new ZipOutputStream(
        new FileOutputStream("response.docx"));
      Enumeration entriesIter =
        docxFile.entries();
      while (entriesIter.hasMoreElements())
      {
        ZipEntry entry = entriesIter.nextElement();
    
        if (entry.getName().equals("word/document.xml"))
        {
          byte[] data = baos.toByteArray();
          docxOutFile.putNextEntry(
            new ZipEntry(entry.getName()));
          docxOutFile.write(data, 0, data.length);
          docxOutFile.closeEntry();
        }
        else
        {
          InputStream incoming =
            docxFile.getInputStream(entry);
          byte[] data = new byte[1024 * 16];
          int readCount =
            incoming.read(data, 0, data.length);
          docxOutFile.putNextEntry(
            new ZipEntry(entry.getName()));
          docxOutFile.write(data, 0, readCount);
          docxOutFile.closeEntry();
        }
      }
      docxOutFile.close();
    
    }

    很抱歉这里展示了这么多代码,但是说实在的,这也是Java相比其他语言或者库的一个弱点。幸运的是我们的努力得到了以下的回报:


    显然我们可以作很多事情来改善上面的场景。

    首先,一个更好的XML操作库,可以更好的支持XPath技术,能够原生的序列化XML DOM结构到磁盘的库会对减少大量的代码有所帮助。JDOM,一个开源的Java/XML库(可以在jdom.org中找到),是一个可用的选择。Apache的XMLBeans也不错。一个必然的结果是我们可以获得更好的描述OpenXML格式的模式文档,并使用它们来产生一系列的Java类来更好的反映OpenXML文档的格式。开发者则可以更好的使用原生的Java类工作,而不是通过“Document”类和“Element”类。

    其次,这些方法可以被绑定到一个更加针对Office的应用程序接口当中,可以改善针对实际存储的Word(或是Excel,PowerPoint)文档的XML文件操作的抽象层,关注那些拥有段落,字体等等其他的文档。实质上,像POI那样的库应该可以通过更新类反映Office XML格式的改动,理想的话,可以同时支持写入二进制结构化存储格式和新的OpenXML格式。

    再次,Java可以对其ZIP文件格式的支持进行一些改动,同样,这样的目的也可以由使用一些第三方的库来完成。

    尽管使用了一些笨重的应用程序接口调用,但是当想到Office平台对Java开发人员有多开放时还是非常的令人激动和振奋。在Java和Office应用程序的互操作性上,在Java应用程序中使用Office,还有在Java中创建和读写Office文件格式上,Office平台对Java社区的开发人员比以往任何时候都更加开放了。

    本文附带的示例代码可以在此处下载

     

    Java无需解压直接读取Zip文件和文件内容

     

    简单例子:
    package test;

    import java.io.BufferedInputStream; 
    import java.io.BufferedReader; 
    import java.io.FileInputStream; 
    import java.io.InputStream; 
    import java.io.InputStreamReader; 
    import java.util.zip.ZipEntry; 
    import java.util.zip.ZipFile; 
    import java.util.zip.ZipInputStream; 


    public class aaaa {

        public static void main(String[] args) throws Exception {
            try { 
                   readZipFile("D:\\ztree.zip"); 
               } catch (Exception e) { 
                   // TODO Auto-generated catch block 
                   e.printStackTrace(); 
               } 
        }
       
        public static void readZipFile(String file) throws Exception { 
               ZipFile zf = new ZipFile(file); 
               InputStream in = new BufferedInputStream(new

    FileInputStream(file)); 
               ZipInputStream zin = new ZipInputStream(in); 
               ZipEntry ze; 
               while ((ze = zin.getNextEntry()) != null) { 
                   if (ze.isDirectory()) {
                   } else { 
                       System.err.println("file - " + ze.getName() + " : " 
                               + ze.getSize() + " bytes"); 
                       long size = ze.getSize(); 
                       if (size > 0) { 
                           BufferedReader br = new BufferedReader( 
                                   new InputStreamReader

    (zf.getInputStream(ze))); 
                           String line; 
                           while ((line = br.readLine()) != null) { 
                               System.out.println(line); 
                           } 
                           br.close(); 
                       } 
                       System.out.println(); 
                   } 
               } 
               zin.closeEntry(); 
           } 
    }

     

     POI解决word2007中字符替换问题

    首先就是要明白解决的方案是:先删后添。就是利用Paragraph创建run,在创建完毕后循环遍历tableàrowàcell,获得到cell里的值,即cell.getText();在这里注意cell中value的长度,建议打出来看看已在后面于替换后的cell的值做对比。同时我们应该多多关注底层文件和源码,这样可以更加方便的了解他的底层构造。可以将word的后缀名改为zip然后打开找到word/document.xml文件,查看构造尤其是表的结构(比如说多关注关注

     <w:tc>
      <w:tcPr>
        <w:tcW w:w="852" w:type="dxa" />
      </w:tcPr>
      <w:p w:rsidR="00B2466A" w:rsidRDefault="004E26BC">
      <w:r>
      <w:rPr>
         <w:rFonts w:hint="eastAsia" />
      </w:rPr>
         <w:t>02</w:t>
      </w:r>
      </w:p>
      </w:tc>
    )这样有助于思维的扩展;

     

    (现在d盘建立一个word,里面要有表格的哦,切记word文档是2007版的,如果2003版可以使用range对象就能轻松解决哦,网上很多的)

    package test;

    import java.io.FileOutputStream;
    import java.util.Iterator;
    import java.util.List;

    import org.apache.poi.POIXMLDocument;
    import org.apache.poi.openxml4j.opc.OPCPackage;
    import org.apache.poi.xwpf.usermodel.XWPFDocument;
    import org.apache.poi.xwpf.usermodel.XWPFParagraph;
    import org.apache.poi.xwpf.usermodel.XWPFRun;
    import org.apache.poi.xwpf.usermodel.XWPFTable;
    import org.apache.poi.xwpf.usermodel.XWPFTableCell;
    import org.apache.poi.xwpf.usermodel.XWPFTableRow;

     

    public class Test {
        /**
         * @param args
         */
        public static void main(String[] args) {
           try {
                OPCPackage pack = POIXMLDocument.openPackage("d:/c.docx");
                XWPFDocument doc = new XWPFDocument(pack);
                Iterator<XWPFTable> it = doc.getTablesIterator();
               while(it.hasNext()){
                  XWPFTable table = it.next();
                  List<XWPFTableRow> rows=table.getRows();
                  for(XWPFTableRow row : rows){
                       List<XWPFTableCell> cells = row.getTableCells();
                        for(XWPFTableCell cell: cells){
                           /*System.out.println(cell.getText());
                           System.out.println(cell.getText().length()+":length");*/
    //   System.out.println(cell.addParagraph().getText().length()+":--------------");//xx

                         //   获得传过来的字符串的长度

                             //这里是判断替换的条件,

                        if(cell.getText().equals("00")){

    //关键的一步,删掉原有的段落

                           cell.removeParagraph(0);

    //给段落重新赋值,不用担心要重新创建段落,他会自动创建的

                               cell.setText("爱爱");
                              /* System.out.println(cell.getText().length()+"====================");
                               */                          

                           } 

    //在这里,主要问题不是判断的问题。而是在判断后如何把原有的之用心之替换掉的问题,

                          /* if(cell.getText().equals("00")){
                               System.out.println();
                               cell.setText("啊啊"); 
    // System.out.println(cell.getText().length()+"====================");

                           } */ 

                         //===========================段落可以不要
                         List<XWPFParagraph> pars = cell.getParagraphs();
                              for(XWPFParagraph par:pars){
                              List<XWPFRun> runs = par.getRuns();
                              for(XWPFRun run:runs){
                                  run.removeBreak(); 
                              }

                               /* System.out.println(par.getText());
                                System.out.println(par.getFootnoteText()+"NO1");
                                System.out.println(par.getParagraphText()+"NO2");
                                System.out.println(par.getPictureText()+"NO3");
                                System.out.println(par.getStyle()+"NO4");
                                System.out.println(par.getStyleID()+"NO5");
                                System.out.println(par.getAlignment()+"NO6");
                                System.out.println(par.getCTP()+"NO7");
                                System.out.println(par.getDocument()+"NO8");
                                System.out.println(par.getElementType()+"NO9");*/
                               }
                        }
                  }
               }

               FileOutputStream fos = new FileOutputStream("d:/bbb.docx");
               doc.write(fos);
               fos.flush();
               fos.close();
           } catch (Exception e) {
               // TODO Auto-generated catch block
               e.printStackTrace();
           }
        }
    }

     

     

    展开全文
  • 这篇文章主要是讲述Word通过宏函数设置一些操作,比如在Word全文中替换一些符号;再如对Word上角表进行编号,如果删除中间某个值,运行宏函数自动编号;对Word中所有图片进行大小统一整合;文章竖着排版等操作。Word...

    这篇文章主要是作为李老师《算法设计与分析》助教课程中,与她交流,学到的一些基础知识。它主要是讲述Word通过宏函数设置一些操作,比如在Word全文中替换一些符号;再如对Word上角表进行编号,如果删除中间某个值,运行宏函数自动编号;对Word中所有图片进行大小统一整合;文章竖着排版等操作。Word宏函数主要是基础VB编写的,希望这篇文章对你有所帮助~


    一. WPS实现宏函数可用

    Office中Word的宏函数直接可以使用,而WPS需要安装一个软件后才能使用。打开WPS Word如下图所示,宏是不能使用的。



    这时需要下载VBA for WPS并安装才能使用。下载地址:
    https://yun.baidu.com/share/link?shareid=2773182689&uk=892671164
    下载安装如下图所示:


    安装完后可以设置宏函数,如下图所示:


    点击"宏",然后"创建"宏函数,如下图所示,取名为test。



    创建后如下图所示,可以看到是VB代码进行编写的。

    WPS需要保存为带宏函数的格式,如下图所示。


    然后运行宏函数如下图所示,点击"运行"即可,如下图所示。


    这里,如果想好好研究这个,可以看看VB一些基础书籍,程序就那回事。我简单看了《VB从入门到精通》后,开始写相应功能的。



    二. 编写宏函数实现自编号

    Visual Basic支持一个对象集合,该集合中的对象直接对应于Microsoft Word 97中的元素,并且通过用户界面,用户熟悉这些元素中的绝大多数。

    例如,Document 对象代表了一个打开的文档,Bookmark对象代表了一个文档中的书签,而Selection对象则代表了在一个文档窗口窗格中的选定内容。在Word中,每一类元素-文档、表格、段落、书签、域等等-都可以用Visual Basic的对象来表示。要在Word中自动执行任务,可以使用这些对象的方法和属性。


    下面简单讲解宏函数实现一些功能。

    Sub test()
    '
    ' test Macro
    '
    
        Dim sLineNum3 As String     '行号(文字)
        Dim nLineNum                '行号(数值)
        Dim i As Long
     
        Title = "输入编号信息"
        a1 = "请输入总编号开始号:"
        b1 = InputBox(a1, Title)
         
    End Sub
    
    运行宏函数如下图所示:


    运行结果如下图所示,弹出界面输入:



    下面是完整的代码,如下所示:

    Sub test()
    '
    ' test Macro
    '
    
        '定义变量
        Dim sLineNum3 As String     '行号(文字)
        Dim nLineNum                '行号(数值)
        Dim sLineNum As String      '行号(文字)
        Dim sLineNum1 As String     '行号(文字)
        Dim sLineNum2 As String     '行号(文字)
        Dim selRge As Range
        Dim i As Long
        Dim x As Long
        Dim y As Long
        Dim k As Long
     
     
        '输入行号对话框
        Title = "输入编号信息"
        a1 = "请输入总编号开始号:"
        b1 = InputBox(a1, Title)
    
        'Val函数将数字字符串换成数值
        y = 200000 + Val(b1) - 1
        
        
        i = 1
        For k = 1 To 20
            sLineNum1 = Str(i + y)            '200001
            sLineNum1 = LTrim(sLineNum1)      '移除字符串最左边的空白字符
            sLineNum1 = Right(sLineNum1, 5)   '生成行号格式"00001"
            
            '行号前加"/"
            'sLineNum = "/" & b2 & sLineNum
            'sLineNum2 = sLineNum1 + sLineNum
            sLineNum2 = sLineNum1
            
       
            '移动光标至当前行首 Selection.HomeKey wdLine
            Selection.HomeKey Unit:=wdLine
            '选择从光标至当前行首的内容 Selection.HomeKey wdLine, wdExtend
            Selection.EndKey Unit:=wdLine, Extend:=wdExtend
        
            sLineNum3 = Selection.Text
            sLineNum3 = Left(sLineNum3, 3)    '从左边获取每行前3个字符
            If sLineNum3 = "%%%" Then         '替换行号
                Selection.Find.Execute FindText:="%%%", ReplaceWith:=sLineNum2
                i = i + 1
            End If
            Selection.MoveDown Unit:=wdLine, Count:=1
     
           Next k
         
    End Sub
    
    现在Word中内容如下所示:

    然后运行"宏",运行如下所示:



    运行结果如下图所示:


    下面补充一些代码,常见的操作Word宏的 函数。
    参考:http://wangye.org/blog/archives/135/
              http://blog.sina.com.cn/s/blog_5e646c1f0100u24w.html
     

    Sub MoveToCurrentLineStart()
      ' 移动光标至当前行首
      ' Selection.HomeKey wdLine
      Selection.HomeKey unit:=wdLine
    End Sub
    Sub MoveToCurrentLineEnd()
      ' 移动光标至当前行尾
      ' Selection.EndKey wdLine
      Selection.EndKey unit:=wdLine
    End Sub
    Sub SelectToCurrentLineStart()
      ' 选择从光标至当前行首的内容
      ' Selection.HomeKey wdLine, wdExtend
      Selection.HomeKey unit:=wdLine, Extend:=wdExtend
    End Sub
    Sub SelectToCurrentLineEnd()
      ' 选择从光标至当前行尾的内容
      ' Selection.EndKey wdLine, wdExtend
      Selection.EndKey unit:=wdLine, Extend:=wdExtend
    End Sub
    Sub SelectCurrentLine()
      ' 选择当前行
      ' Selection.HomeKey wdLine
      ' Selection.EndKey wdLine, wdExtend
      Selection.HomeKey unit:=wdLine
      Selection.EndKey unit:=wdLine, Extend:=wdExtend
    End Sub
    Sub MoveToDocStart()
      ' 移动光标至文档开始
      ' Selection.HomeKey wdStory
      Selection.HomeKey unit:=wdStory
    End Sub
    Sub MoveToDocEnd()
      ' 移动光标至文档结尾
      ' Selection.EndKey wdStory
      Selection.EndKey unit:=wdStory
    End Sub
    Sub SelectToDocStart()
      ' 选择从光标至文档开始的内容
      ' Selection.HomeKey wdStory, wdExtend
      Selection.HomeKey unit:=wdStory, Extend:=wdExtend
    End Sub
    Sub SelectToDocEnd()
      ' 选择从光标至文档结尾的内容
      ' Selection.EndKey wdStory, wdExtend
      Selection.EndKey unit:=wdStory, Extend:=wdExtend
    End Sub
    Sub SelectDocAll()
      ' 选择文档全部内容(从WholeStory可猜出Story应是当前文档的意思)
      Selection.WholeStory
    End Sub
    Sub MoveToCurrentParagraphStart()
      ' 移动光标至当前段落的开始
      ' Selection.MoveUp wdParagraph
      Selection.MoveUp unit:=wdParagraph
    End Sub
    Sub MoveToCurrentParagraphEnd()
      ' 移动光标至当前段落的结尾
      ' Selection.MoveDown wdParagraph
      Selection.MoveDown unit:=wdParagraph
    End Sub
    Sub SelectToCurrentParagraphStart()
      ' 选择从光标至当前段落开始的内容
      ' Selection.MoveUp wdParagraph, wdExtend
      Selection.MoveUp unit:=wdParagraph, Extend:=wdExtend
    End Sub
    Sub SelectToCurrentParagraphEnd()
      ' 选择从光标至当前段落结尾的内容
      ' Selection.MoveDown wdParagraph, wdExtend
      Selection.MoveDown unit:=wdParagraph, Extend:=wdExtend
    End Sub
    Sub SelectCurrentParagraph()
      ' 选择光标所在段落的内容
      ' Selection.MoveUp wdParagraph
      ' Selection.MoveDown wdParagraph, wdExtend
      Selection.MoveUp unit:=wdParagraph
      Selection.MoveDown unit:=wdParagraph, Extend:=wdExtend
    End Sub
    Sub DisplaySelectionStartAndEnd()
      '显示选择区的开始与结束的位置,注意:文档第1个字符的位置是0
      MsgBox ("第" & Selection.Start & "个字符至第" & Selection.End & "个字符")
    End Sub
    Sub DeleteCurrentLine()
      ' 删除当前行
      ' Selection.HomeKey wdLine
      ' Selection.EndKey wdLine, wdExtend
      Selection.HomeKey unit:=wdLine
      Selection.EndKey unit:=wdLine, Extend:=wdExtend
      Selection.Delete
    End Sub
    Sub DeleteCurrentParagraph()
      ' 删除当前段落
      ' Selection.MoveUp wdParagraph
      ' Selection.MoveDown wdParagraph, wdExtend
      Selection.MoveUp unit:=wdParagraph
      Selection.MoveDown unit:=wdParagraph, Extend:=wdExtend
      Selection.Delete
    End Sub


            最后希望文章对你有所帮助,如果文章中存在错误或不足之处,还请海涵~后面肯恩会补充一些实用的功能, 娜美人生,精彩人生。
          (By:Eastmount 2017-03-15 中午1点    http://blog.csdn.net/eastmount/  


    展开全文
  • Jacob全称位java com bridge,通过该插件,可以使用Java...该程序核心部分,仅仅是调用了Jacob的几个类,实现了调用Word打开指定的word文档,并在指定的目的路径中将其另存为指定的文档格式,简而言之,就是“Open”

    Jacob全称位java com bridge,通过该插件,可以使用Java语言编写程序,调用COM、ActiveX组件来操作Windows本地程序。

    参考一位网友的例子,我写了一个程序,用来将word批量转换为txt等格式的文档。

    该程序核心部分,仅仅是调用了Jacob的几个类,实现了调用Word打开指定的word文档,并在指定的目的路径中将其另存为指定的文档格式,简而言之,就是“Open”,“save As”。

    Jacob能够实现的远不止这点,操作word的Java插件有不少,功能强大的Jacob可以为首。

    因为程序是调用本地Office进行的打开、另存为操作,所以需要本地安装有word,并且,不同的office版本操作的结果自然是不同的。

    我使用的是word2010,在word2010下可以打开97-2003doc文档和2007-2010docx文档,保存的格式也有docx、pdf,而在word2003版本下,该功能实习不了。如果有兴趣测试的话,在word2003的环境下,可以把相关的代码注释掉。

    下边附上源代码:

        /** 
         *@author eyuan 
         */  
        package per.eyuan.word2txt.core;  
          
        import com.jacob.*;  
        import com.jacob.com.*;  
        import com.jacob.activeX.*;  
        import java.io.*;  
        import java.util.Scanner;  
          
        public class Core {  
         /** 
          * 实现转换的函数 
          * @param sourceFilesPath 
          * @param destinationFilesPath 
          * @param destinationFilesType 
          * @return void 
          * @see import com.jacob.activeX.*; 
          */  
         public boolean change(String sourceFilesPath,String destinationFilesPath,int destinationFilesType){  
          //使用word文件所在的目录(源路径)建立目录文件  
          File sourcePathFile=new File(sourceFilesPath);  
          //取得word文件(源文件列表)  
          File sourceFilesList[]=sourcePathFile.listFiles();  
          System.out.println("共有"+sourceFilesList.length+"个文件(文件夹)");  
          //指定要转换的文件所在的目录下,如果有子目录,  
          //则进入子目录,继续查找word文档并将其转换,  
          //直到将指定目录下的所有word文档转换完。  
          //子目录名  
          String sourceChildPath=new String("");  
          //保持原来的层次关系,将子目录下的文件存放在新建的子目录中  
          String destiNationChildPath=new String("");  
          //检索文件,过滤掉非word文件,通过扩展名过滤  
          for(int i=0;i<sourceFilesList.length;i++){  
           //排除掉子文件夹  
           if(sourceFilesList[i].isFile()){  
            System.out.println("第"+(i+1)+"个文件:");  
            //取得文件全名(包含扩展名)  
            String fileName=sourceFilesList[i].getName();  
            String fileType=new String("");      
            //取得文件扩展名  
            fileType=fileName.substring((fileName.length()-4), fileName.length());  
            //word2007-2010扩展名为docx  
            //判断是否为word2007-2010文档,及是否以docx为后缀名  
            if(fileType.equals("docx")){  
             System.out.println("正在转换。。。");  
             //输出word文档所在路劲  
             System.out.println("目录:"+sourceFilesPath);  
             //输出word文档名  
             System.out.println("文件名:"+fileName);  
             //System.out.println(fileName.substring(0, (fileName.length()-5)));  
             //核心函数  
             //启动word  
             ActiveXComponent app=new ActiveXComponent("Word.Application");  
             //要转换的文档的全路径(所在文件夹+文件全名)  
             String docPath=sourceFilesPath+"\\"+fileName;  
             //转换后的文档的全路径(所在文件夹+文件名)  
             String othersPath=destinationFilesPath+"\\"+fileName.substring(0,(fileName.length()-5));  
             //  
             String inFile=docPath;  
             String outFile=othersPath;  
             //  
             boolean flag=false;  
             //核心代码  
             try{  
              //设置word可见性  
              app.setProperty("Visible", new Variant(false));  
              //  
              Dispatch docs=app.getProperty("Documents").toDispatch();  
              //打开word文档     
              Dispatch doc=Dispatch.invoke(docs, "Open", Dispatch.Method, new Object[]{inFile,new Variant(false),new Variant(true)}, new int[1]).toDispatch();  
              //0:Microsoft Word 97 - 2003 文档 (.doc)  
              //1:Microsoft Word 97 - 2003 模板 (.dot)  
              //2:文本文档 (.txt)  
              //3:文本文档 (.txt)  
              //4:文本文档 (.txt)  
              //5:文本文档 (.txt)  
              //6:RTF 格式 (.rtf)  
              //7:文本文档 (.txt)  
              //8:HTML 文档 (.htm)(带文件夹)  
              //9:MHTML 文档 (.mht)(单文件)  
              //10:MHTML 文档 (.mht)(单文件)  
              //11:XML 文档 (.xml)  
              //12:Microsoft Word 文档 (.docx)  
              //13:Microsoft Word 启用宏的文档 (.docm)  
              //14:Microsoft Word 模板 (.dotx)  
              //15:Microsoft Word 启用宏的模板 (.dotm)  
              //16:Microsoft Word 文档 (.docx)  
              //17:PDF 文件 (.pdf)  
              //18:XPS 文档 (.xps)  
              //19:XML 文档 (.xml)  
              //20:XML 文档 (.xml)  
              //21:XML 文档 (.xml)  
              //22:XML 文档 (.xml)  
              //23:OpenDocument 文本 (.odt)  
              //24:WTF 文件 (.wtf)  
              //另存为指定格式的文档  
              Dispatch.invoke(doc, "SaveAs", Dispatch.Method, new Object[]{outFile,new Variant(destinationFilesType)}, new int[1]);  
              //  
              Variant file=new Variant(false);  
              //关闭文档  
              Dispatch.call(doc, "Close",file);  
              //  
              flag=true;  
             }catch(Exception e){  
              e.printStackTrace();  
              System.out.println("文档转换失败");  
             }finally{  
              app.invoke("Quit",new Variant[]{});  
             }  
             System.out.println("转换完毕");         
            }  
            //word97-2003扩展名为doc  
            //判断是否为word2003-2007文档,及是否以doc为后缀名  
            else if(fileType.equals(".doc")){  
             System.out.println("正在转换。。。");  
             //输出word文档所在路劲  
             System.out.println("目录:"+sourceFilesPath);  
             //输出word文档名  
             System.out.println("文件名:"+fileName);  
             //System.out.println(fileName.substring(0, (fileName.length()-4)));  
             //核心函数  
             //启动word  
             ActiveXComponent app=new ActiveXComponent("Word.Application");  
             //要转换的文档的全路径(所在文件夹+文件全名)  
             String docPath=sourceFilesPath+"\\"+fileName;  
             //转换后的文档的全路径(所在文件夹+文件名)  
             String othersPath=destinationFilesPath+"\\"+fileName.substring(0,(fileName.length()-4));  
             //  
             String inFile=docPath;  
             String outFile=othersPath;  
             //  
             boolean flag=false;  
             //核心代码  
             try{  
              //设置word可见性  
              app.setProperty("Visible", new Variant(false));  
              //  
              Dispatch docs=app.getProperty("Documents").toDispatch();  
              //打开word文档     
              Dispatch doc=Dispatch.invoke(docs, "Open", Dispatch.Method, new Object[]{inFile,new Variant(false),new Variant(true)}, new int[1]).toDispatch();  
              //另存为指定格式的文档  
              Dispatch.invoke(doc, "SaveAs", Dispatch.Method, new Object[]{outFile,new Variant(destinationFilesType)}, new int[1]);  
              //  
              Variant file=new Variant(false);  
              //关闭文档  
              Dispatch.call(doc, "Close",file);  
              //  
              flag=true;  
             }catch(Exception e){  
              e.printStackTrace();  
              System.out.println("文档转换失败");  
             }finally{  
              app.invoke("Quit",new Variant[]{});  
             }  
             System.out.println("转换完毕");         
            }  
            //文档的扩展名不是doc或docx  
            else{  
             System.out.println("非word文档");  
            }  
           }  
           //如果是子文件夹,则递归遍历,将所有的word文档转换  
           else{  
            //  
            sourceChildPath=sourceFilesPath;  
            //该文件是目录  
            sourceChildPath=sourceChildPath+"\\"+sourceFilesList[i].getName()+"\\";  
            System.out.println("源文件所在路径:"+sourceChildPath);  
            //修改目标文件夹,保持原来的层级关系  
            destiNationChildPath=destinationFilesPath;  
            destiNationChildPath=destinationFilesPath+"\\"+sourceFilesList[i].getName()+"\\";  
            System.out.println("转换后文件所在路径"+destiNationChildPath);  
            //  
            mkdir(destiNationChildPath);  
            //递归遍历所有目录,查找word文档,并将其转换  
            change(sourceChildPath, destiNationChildPath,destinationFilesType);  
           }  
          }  
          System.out.println("所有文档转换完毕");  
          return true;  
         }  
         /**  
          * 用于创建文件夹的方法  
          * @param mkdirName  
          */  
         public void mkdir(String mkdirName){  
          try{  
           //使用指定的路径创建文件对象  
           File dirFile = new File(mkdirName);   
           //  
           boolean bFile = dirFile.exists();  
           //已经存在文件夹,操作???提醒是否要替换  
           if( bFile == true ) {   
            System.out.println("已经存在文件夹"+mkdirName);   
           }  
           //不存在该文件夹,则新建该目录  
           else{  
            System.out.println("新建文件夹"+mkdirName);   
            bFile = dirFile.mkdir();   
            if( bFile == true ){  
             System.out.println("文件夹创建成功");   
            }else{  
             System.out.println(" 文件夹创建失败,清确认磁盘没有写保护并且空件足够");   
             System.exit(1);   
            }  
           }  
          }catch(Exception err){  
           System.err.println("ELS - Chart : 文件夹创建发生异常");   
           err.printStackTrace();   
          }finally{  
             
          }  
         }  
         /** 
          * 判断某个文件夹是否存在 
          * @param path 
          */  
         /** 
          * 将形如D:\word的路径转换为D:\\word 
          */  
         public String changePath(String path){  
          String newPath="";  
          StringBuffer sb=new StringBuffer();  
          for(int i=0;i<path.length();i++){  
           sb.append(path.charAt(i));  
           if(path.charAt(i)=='\\')  
            sb.append('\\');  
          }  
          newPath=sb.toString();  
          System.out.println(newPath);  
          return newPath;  
         }  
         public boolean isPathExist(String path){  
          boolean isPathExist=false;  
          try{  
           File pathFile = new File(path);  
           if(pathFile.exists())  
            isPathExist= true;  
           else  
            isPathExist= false;  
          }catch(Exception err){  
           err.printStackTrace();   
          }  
          return isPathExist;  
         }  
         /** 
          * 主函数 
          */  
         public static void main(String[] args){  
          Core c=new Core();  
        //  c.changePath("D:\\word");  
          Scanner sc=new Scanner(System.in);  
          //源文档所在路径  
          String sourceFilesPath="";   
        //  String inputSourcePath="";  
        //  boolean sourcePathFlag=true;  
        //  System.out.println("请输入要转换文档所在的文件夹");  
        //  while(sourcePathFlag){  
        //   inputSourcePath=sc.next();  
        //   if(!isPathExist(inputSourcePath))  
        //    System.out.println("源路径不存在,请输入正确的路径");  
        //   else  
        //    sourcePathFlag=false;  
        //  }  
        //  sourceFilesPath=inputSourcePath;  
          sourceFilesPath="D:\\word";  
          //目标文档要存放的目录  
          String destinationFilesPath="";  
        //  String inputdestinationPath="";  
        //  boolean destinationPathFlag=true;  
        //  System.out.println("请输入转换后文档要存放的文件夹");  
        //  while(destinationPathFlag){  
        //   inputdestinationPath=sc.next();  
        //   //目标文件不存在时,是否要提示用户创建文件  
        //   if(!isPathExist(inputdestinationPath))  
        //    System.out.println("目标路径不存在,请输入正确的路径");  
        //   else  
        //    destinationPathFlag=false;  
        //  }  
        //  destinationFilesPath=inputdestinationPath;    
          destinationFilesPath="D:\\txt";  
          //选择要转换的类型  
          int destinationFilesType=0;  
          int inputNumber=0;  
          boolean numFlag=true;  
          System.out.println("您要将word文档转换为哪种文档格式?");  
          System.out.println("0:doc \t 2:txt \t 6:rtf \t 8:html \t 9:mht \t 11:xml \t 12:docx \t 17:pdf \t 18:xps");  
          while(numFlag){  
           inputNumber=sc.nextInt();  
           if(inputNumber!=2&&inputNumber!=6&&inputNumber!=8&&inputNumber!=9&&inputNumber!=11&&inputNumber!=12&&inputNumber!=17){  
            System.out.println("您的输入有误,请输入要转换的文档类型前的数字");  
           }else  
            numFlag=false;  
          }    
          destinationFilesType=inputNumber;  
          //实行转换  
          c.change(sourceFilesPath, destinationFilesPath,destinationFilesType);  
          //测试各种类型转换  
        //  for(int i=0;i<25;i++){  
        //   destinationFilesType=i;  
        //   System.out.println("文件类型"+destinationFilesType);    
        //   System.out.println("存放目录:"+destinationFilesPath+"\\"+i);  
        //   mkdir(destinationFilesPath+"\\"+i);  
        //   change(sourceFilesPath, destinationFilesPath+"\\"+i,destinationFilesType);  
        //  }  
         }  
        }  


    展开全文
  • 文本文档的信息多是按照行的格式读写的,因此在读取时对提取到每行的文本信息进行关键字的对比找到指定行,然后利用正则表达式提取相应的信息即可。 文本信息示例 positions bitstream size 550216 B (12.5996 ...
  • freemarker内建函数(八)

    千次阅读 2017-12-24 22:51:52
    Freemarker内建函数 1.1 处理字符串的内建函数 1.1.1 substring 取子串 注意: 这个内建函数从 FreeMarker 2.3.7 开始可用。 概要 :exp?substring(from, toExclusive) ,也 可 以 作 为 ...它必须是一个数字
  • python读写word、excel、csv、json文件

    万次阅读 2015-12-21 01:14:58
    python读写word文档 (include wps) 将word文档转换成txt文档 def doc2txt(): ''' 将doc文档转换成txt文档 :return: ''' from win32com import client INPUT_DIR = r'C:\Users\pi\Desktop\New folder'
  • RxJava 驯服数据流之自定义操作函数

    千次阅读 2016-07-08 23:02:28
    RxJava 提供了很多操作函数。加上各种重载函数,一共有 300 多个操作函数。这些函数中只有很少一部分是核心的操作函数,离开这些核心的函数根本就没法使用 RxJava 了。其他的大部分函数只是一些便捷函数,方便开发者...
  • Java中文分词组件 - word分词

    万次阅读 2019-02-10 16:17:50
    API在线文档: 编译好的jar包下载(包含依赖): Maven依赖: 分词使用方法: 分词算法效果评估: 相关文章: word分词是一个Java实现的分布式的中文分词组件,提供了多种基于词典的分词算法,并利用ngram模型...
  •  首先,我们看imread函数,可以在OpenCV官方文档中查到其原型如下:  Mat imread(const string& filename, int flags=1 );其中,第一个参数,const string&类型的filename,填我们需要载入的图片路径名。 在...
  • Python-Class___函数与常用内置函数

    千次阅读 2018-07-22 16:10:03
    一、函数 1.1、定义函数 在Python中,定义一个函数要使用def语句,依次写出函数名、括号、括号中的参数和冒号“ : ”,然后,在缩进块中编写函数体,函数的返回值用return语句返回。 &gt;&gt;def func()...
  • Matlab常用函数

    千次阅读 2014-06-03 10:15:00
    Matlab有没有求矩阵行数/列数/维数的函数? ndims(A)返回A的维数 size(A)返回A各个维的最大元素个数 length(A)返回max(size(A)) [m,n]=size(A)如果A是二维数组,返回行数和列数 nnz(A)返回A中非0元素的个数 ...
  • word使用技巧大全

    热门讨论 2011-03-18 20:37:53
    使Word中的字体变清晰Word文档中使用“仿宋”字体很淡,可按以下方法使字体更清晰: 84 四十一、word和execl使用技巧 84 1、Word下如何使用着重号 84 2、让Word表格快速一分为二 84 3、Word中巧用Alt键 85 4、巧用...
  •  首先,我们看imread函数,可以在OpenCV官方文档中查到其原型如下:  Mat imread(const string& filename, int flags=1 );其中,第一个参数,const string&类型的filename,填我们需要载入的图片路径名。 在...
  • word技巧

    千次阅读 2018-03-01 21:40:22
    word 高效经典教程(整理版)目录一分钟驾驭word 高效经典教程(整理版)... 6A、基础知识... 61、度量单位... 62、WORD中文字字号与磅的对应关系... 63、字体文件格式...... 96、Word文档超级链接知多...
  • 文章目录内容介绍福利Word 文档操作Word 文档编辑Word 文档格式Word 图文混排 内容介绍 对于数据分析师来说,日常工作最重要的环节不是敲代码,做题述师和调参侠,本身忽略了一项工作就是做 文字性的报告 内容。熟练...
  • Matlab相关函数

    千次阅读 2017-04-13 21:49:28
    计算样本集中多个样本两两之间的距离矩阵,dist(pos)输入一个参数,pos——N×S的神经元位置矩阵,返回S×S的距离矩阵,A=[1,2;2,3;3,5;4,2];A1=A’,B=dist(A1),注意要先对A进行转置 B= 0 1.4142 3.6056 3.0000 ...
  • SAP ABAP 函数

    千次阅读 2018-12-11 14:43:27
    函数名 描述 SD_VBAP_READ_WITH_VBELN 根据销售订单读取表vbap中的信息 EDIT_LINES 把READ_TEXT返回的LINES中的行按照TDFORMAT=“*”重新组织 VIEW_MAINTENANCE_CALL 维护表视图   函数名 描述 DY_GET_...
  • matlab函数总结

    千次阅读 2018-07-28 10:38:58
    ndims(A)返回A的维数 size(A)返回A各个维的最大元素个数 length(A)返回max(size(A)) [m,n]=size(A)如果A是二维数组,返回行数和列数 nnz(A)返回A中非0元素的...MATLAB的取整函数:fix(x), floor(x) :,ceil(x) , ro...
  • Keras函数式模型

    千次阅读 2019-01-20 11:37:01
    快速开始函数式(Functional)模型 我们起初将Functional一词译作泛型,想要表达该类模型能够表达任意张量映射的含义,但表达的不是很精确,在Keras 2里我们将这个词改译为“函数式”,对函数式编程有所了解的同学...
  • PHP 函数大全

    千次阅读 2018-03-02 18:48:48
    a函数 说明abs 绝对值acos 反余弦acosh 反双曲余弦addcslashes 以 C 语言风格使用反斜线转义字符串中的字符addslashes 使用反斜线引用字符串apache_child_terminate 在本次请求结束后终止 apache 子进程...
  • php函数大全

    千次阅读 多人点赞 2013-11-14 15:53:52
    在 PHP 中,提供了超过 700 个内建的函数
  • Keras学习笔记:函数式模型

    千次阅读 2018-08-05 13:40:55
    目录: 目录: 函数式(Functional)模型 第一个模型:全连接网络 ...本系列参考官方文档官方文档 这就是keras可以参考前篇:这就是keras 学习笔记 Keras:一些基本概念 一些基本概念 Keras:常见问...
  • Word 2003域应用完全手册

    千次阅读 2014-01-24 19:50:08
     简单地讲,域就是引导Word文档中自动插入文字、图形、页码或其他信息的一组代码 。每个域都有一个唯一的名字,它具有的功能与Excel中的函数非常相似。下面以Seq和Dat e域为例,说明有关域的一些基本概念。 ...
  • word2vec和word embedding有什么区别?

    千次阅读 2017-12-18 11:26:29
    作者:Scofield链接:...很好,正好可借此机会介绍词向量、word2vec以及DeepNLP整套相关的东西:文章很长,是从CSDN上写好复制过来的,亦可直接跳到博客观看:深度学习(Deep Learning)
  • PHP字符串函数 查找字符位置函数

    千次阅读 2016-11-22 08:55:38
    PHP字符串函数查找字符位置函数 ...stripos($str,search,[int]):函数返回字符串在另一个字符串中第一次出现的位置。该函数对大小写不敏感 strrpos($str,search,[int]):查找search在$str中的最后一次出现的位
  • ABAP常用函数总结

    千次阅读 2016-12-28 09:20:23
    函数名 描述 SD_VBAP_READ_WITH_VBELN 根据销售订单读取表vbap中的信息 EDIT_LINES 把READ_TEXT返回的LINES中的行按照TDFORMAT=“*”重新组织 VIEW_MAINTENANCE_CALL 维护表视图 函数名 描述 DY_GET_FOCUS 获得...
  • Excel函数教程

    千次阅读 2018-10-10 18:57:27
    一、Excel函数应用之函数简介 Excel的数据处理功能在现有的文字处理软件中可以说是独占鳌头,几乎没有什么软件能够与它匹敌。在您学会了Excel的基本操作后,是不是觉得自己一直局限在Excel的操作界面中,而对于Excel...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 33,794
精华内容 13,517
关键字:

word文档输入数字出现函数