zoukankan      html  css  js  c++  java
  • java导出word[xml方式]

    xml方式导出word优缺点:

    优点:

             1、代码量少,样式、内容容易控制,打印不变形,符合office标准;

             2、支持Linux平台,不要求安装office;

             3、可以实现固定格式文档输出;

             4、支持添加图片;

    缺点:

             1、需要提前设计好word模板,把需要替换的地方用特殊标记标出来;

             2、若要在word中添加图片,需要在设计模板时加入一张图片进行占位,然后手动编辑xml模板文档;

    1、XmlWord类的使用(使用org.w3c.dom操作XML)

    XmlWord类源码:XmlWord.txt

    示例代码所用模板:2.xml

    【注】:创建模板的office需2003及以上版本。

    使用步骤:

    1、创建一个需要导出word模板;

    2、创建一个XmlWord对象;

    3、若模板标记有多个,存储至list中;存储替换值;

    4、生成word文档;

    [示例代码]

           XmlWord test = new XmlWord();

           //1、载入模板

           Document doc = test.LoadXml("2.xml");

           //2、设置标记,tagList中存放的标记要同模板中的标记一致;

           List<String> tagList = new ArrayList<String>();

           tagList.add("${test_name}");

           tagList.add("${test_no}");

           //3、设置填充标记的值,dataList中存放数据顺序与tagList存放标记顺序一致;

           List<String> dataList = new ArrayList<String>();

           dataList.add("----用例名");

           dataList.add("----用例编号");

           //4、将标记和标记值存入dataMap

           test.setData(tagList, dataList);

           //5、替换值

           /*添加图片*/

           test.replacePic(doc.getDocumentElement(), "${img}", "8.jpg", imgStr);

           test.replaceTagContext(doc.getDocumentElement());

           //6、写入文档

           test.doc2DocFile(doc, "xmlword.doc");

     

    2、特殊说明

    1、word模板制作:

             使用office 2003及以上版本写一个需要导出的word模板,然后编辑文档的样式,将需要动态填充的内容,使用特殊标记替换,如实例代码中的标记(${test_name}),最后将编辑后的word文档另存为为“Word 2003 XML 文档(*.xml)”格式,将模板放置在工程下。

     

    2、添加图片:

             如果需要在word中添加图片,在第一步制作模板时,加入一张图片占位,然后打开xml文档,可以看到如下的一片base64编码后的代码:

    <w:binData w:name="wordml://03001.png" xml:space="preserve">iVBO……CC</w:binData>

    只要将base64的代码替换成例如:${image},如下:

    <w:binData w:name="wordml://03001.png" xml:space="preserve">${image}</w:binData>

             这里要注意“>${image}<”这尖括号中间不能加任何其他的诸如空格,tab,换行等符号,否则导出的word将会出错。

    3、XmlWord类说明

    Properties

    变量

    说明

    Map<String,String> dataMap

    用于当模板中有多个标记时存放标记值及替换数据。

    Methods

    方法

    参数

    返回值

    LoadXml(String filename):Document

    载入一个xml文档

    filename:模板路径

    成功返回Document对象;

    失败返回null

    getImageStr(String imgFile):String

    图片转码

    ImgFile:图片全路径名

    返回图片base64字符串

    doc2DocFile(Document document,String   filename):boolean

    将Document对象保存为一个Doc文件

    filename:保存的文件名

    document:需要保存的Document对象

    true:保存成功

    false:保存失败

    replaceTagContext(Element element,String tag,String data):Element

    替换标识内容:单个标记(仅用于替换文本)

    element:要填充内容的节点

    tag:模板中标记

    data:数据

    返回替换后的节点

    replaceTagContext(Element element):Element

    替换标识内容:多个标记,调用此方法前,先调用setData方法(仅用于替换文本)

    element:要替换内容的节点

    返回替换后的节点

    replacePic(Object element,String   tag,String imgName,String imgStr):Element

    添加图片,此方法仅适用于单张图片的添加,多图添加可参考该方法源码

    element:要替换内容的节点

    tag:模板中图片标记

    imgName:图片名称,若word中有多张图,图片名必须唯一

    imgStr:图片转码后的base64字符串

    返回替换后的节点

    本类目前仅能支持文本、图片分次替换,未实现文本同图片的同时替换。

    模板:

        

    导出后效果:

      

    XmlWord类代码:

    package com.hxh.test;
    
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.ArrayList;
    import java.util.Date;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.List;
    import java.util.Map;
    import java.util.Set;
    import javax.xml.parsers.DocumentBuilder;
    import javax.xml.parsers.DocumentBuilderFactory;
    import javax.xml.transform.Transformer;
    import javax.xml.transform.TransformerFactory;
    import javax.xml.transform.dom.DOMSource;
    import javax.xml.transform.stream.StreamResult;
    import org.w3c.dom.Document;
    import org.w3c.dom.Element;
    import org.w3c.dom.NodeList;
    import sun.misc.BASE64Encoder;
    
    public class XmlWord {
        
        private Map<String,String> dataMap = new HashMap<String,String>();
        public Map<String, String> getDataMap() {
            return dataMap;
        }
    
        public void setDataMap(Map<String, String> dataMap) {
            this.dataMap = dataMap;
        }
        
        /**
         * 设置标识值
         * @param tagList 标识
         * @param dataList 数据
         * @param dataMap
         */
        public void setData(List<String> tagList,List<String> dataList){
            Iterator<String> it1 = tagList.iterator();
            Iterator<String> it2 = dataList.iterator();
            while(it1.hasNext()){
                this.dataMap.put(it1.next(), it2.next());
            }
        }
    
        /**
         * 载入一个xml文档
         * @param filename 文件路径
         * @return 成功返回Document对象,失败返回null
         */
        public Document LoadXml(String filename){
            
            Document doc = null;
            try {
                DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 
                DocumentBuilder builder = factory.newDocumentBuilder();
                doc = (Document) builder.parse(new File(filename));
            } catch (Exception e) {
                System.out.println("载入xml文件时出错");
                e.printStackTrace();
            }
            return doc;
        }
        
        /**
         * 图片转码
         * @return 返回图片base64字符串
         * @throws Exception
         */
        public String getImageStr(String imgFile){
            InputStream in = null;
            BASE64Encoder encoder = null;
            byte[] data = null;
            try {
                in = new FileInputStream(imgFile);
            } catch (FileNotFoundException e) {
                System.out.println("文件没找到!");
                e.printStackTrace();
            }
            try {
                data = new byte[in.available()];
                in.read(data);
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            encoder = new BASE64Encoder();
            return encoder.encode(data);
        }
        /** 
         * doc2XmlFile 
         * 将Document对象保存为一个xml文件 
         * @return true:保存成功  flase:失败 
         * @param filename 保存的文件名 
         * @param document 需要保存的document对象 
         */ 
        public boolean doc2XmlFile(Document document,String filename) 
        { 
           boolean flag = true; 
           try{
               TransformerFactory transFactory = TransformerFactory.newInstance(); 
                  Transformer transformer = transFactory.newTransformer();
               DOMSource source=new DOMSource();
               source.setNode(document);
               StreamResult result=new StreamResult();
               FileOutputStream fileOutputStream = new FileOutputStream(filename); 
               result.setOutputStream(fileOutputStream);
               transformer.transform(source, result);
               fileOutputStream.close();          
           }catch(Exception ex){ 
               flag = false; 
               ex.printStackTrace(); 
           } 
           return flag;       
        }
        
        /**
         * 替换标识内容:单个文本标记
         * @param element 要替换内容的节点
         * @param tag 标识名称
         * @param data 替换参数
         * @return 返回替换后的节点
         * @throws Exception
         */
        public Element replaceTagContext(Object  element,String tag,String data){
            Element xElement = null;
            xElement = (Element) element;
            NodeList tElements = xElement.getElementsByTagName("w:t");//w:t标签组 
            for(int i=0; i<tElements.getLength(); i++){
                Element tElement = (Element)tElements.item(i);
                if(tElement.getTextContent().equals(tag)){
                     tElement.setTextContent(data);
                 }
            }
            return xElement;
        }
        
        /**
         * 替换标识内容:多个文本标记
         * @param element 要替换内容的节点
         * @return 返回替换后的节点
         * @throws Exception
         */
        public Element replaceTagContext(Element  element){
            Element xElement = element;
            NodeList tElements = xElement.getElementsByTagName("w:t");//w:t标签组 
            Set<String> dataSet = this.dataMap.keySet();
            Iterator<String> it = dataSet.iterator();
            while(it.hasNext()){
                String tag = it.next();
                String data = dataMap.get(tag);
                for(int i=0; i<tElements.getLength(); i++){
                    Element tElement = (Element)tElements.item(i);
                    if(tElement.getTextContent().equals(tag)){
                         tElement.setTextContent(data);
                     }
                }
            }
            return xElement;
        }
        
        /**
         * 添加图片
         * @param element 需要替换内容的节点 
         * @param tag 标识名称
         * @param imgName 图片名称,若word中有多张图,图片名必须唯一
         * @param imgStr 图片转码后的base64字符串
         * @return 返回替换后的节点
         */
        public Element replacePic(Element element,String tag,String imgName,String imgFile){
            Element xElement = element;
            NodeList tElements = xElement.getElementsByTagName("w:binData");//w:t标签组  pkg:binaryData
            String wName = "wordml://"+imgName;
            for(int i=0; i<tElements.getLength(); i++){
                Element picElement = (Element)tElements.item(i);
                if(picElement.getTextContent().equals(tag)){
                     picElement.setTextContent(this.getImageStr(imgFile));/*图片编码*/
                     picElement.setAttribute("w:name",wName);//设置名字
                     Element imagedataElement = (Element) xElement.getElementsByTagName("v:imagedata").item(i);
                     imagedataElement.setAttribute("src",wName);
                 }
            }
            return xElement;
        }
        
        
        /**
         * 插入图片
         * @param parentElement 图片添加至何处
         * @param imgFile 图片路径
         * @param isnewLine 是否换行
         * @return 返回添加图片节点后的节点
         */
        public Element addPic(Element parentElement,String imgFile,boolean isnewLine){
            Document parent = parentElement.getOwnerDocument();
            Element p = null;
            Element pict = null;
            Element binData = null;
            Element shape = null;
            Element imagedata = null;
            String src = "wordml://" + new Date().getTime();
            if(isnewLine){
                p = parent.createElement("w:p");
            }
            pict = parent.createElement("w:pict");
            binData = parent.createElement("w:binData");
            binData.setAttribute("w:name", src);
            binData.setAttribute("xml:space", "preserve");
            binData.setTextContent(this.getImageStr(imgFile));
            shape = parent.createElement("v:shape");
            imagedata = parent.createElement("v:imagedata");
            imagedata.setAttribute("src", src);
            //构造图片节点
            shape.appendChild(imagedata);
            pict.appendChild(binData);
            pict.appendChild(shape);
            if(isnewLine){
                p.appendChild(pict);
                parentElement.appendChild(p);
            }else{
                parentElement.appendChild(pict);
            }
            return parentElement;
        }
        
        /**
         * 插入段落
         * @param parentElement 待添加段落的节点
         * @param data 待插入数据
         * @return
         */
        public Element addParagraph(Element parentElement,String data){
            Document parent = parentElement.getOwnerDocument();
            Element p = null;
            Element r = null;
            Element t = null;
            p = parent.createElement("w:p");
            r = parent.createElement("w:r");
            t = parent.createElement("w:t");
            t.setTextContent(data);
            //构造图片节点
            r.appendChild(t);
            p.appendChild(r);
            parentElement.appendChild(p);
            return parentElement;
        }
    
    }
    只有当知道了全部,你的选择才有意义。
  • 相关阅读:
    Js实现页面跳转的几种方式
    android给View设置上下左右边框
    mac下安装tomcat
    Series.str方法
    loc() iloc() at() iat()函数
    sudo: pip:找不到命令
    杀死进程方法
    unique()与nunique()
    object数据类型
    set_index()与reset_index()函数
  • 原文地址:https://www.cnblogs.com/splvxh/p/2960757.html
Copyright © 2011-2022 走看看