当前位置:  编程技术>java/j2ee

一个JAVA小项目--Web应用自动生成Word

    来源: 互联网  发布时间:2014-11-06

    本文导语:  前段时间接到一个Web应用自动生成Word的需求,现整理了下一些关键步骤拿来分享一下。 思路:(注:这里只针对WORD2003版本,其它版本大同小异。) 因为WORD文件内部的数据及格式等是通过XML文件的形式存储的,所以WORD文件可...

前段时间接到一个Web应用自动生成Word的需求,现整理了下一些关键步骤拿来分享一下。

思路:(注:这里只针对WORD2003版本,其它版本大同小异。)

因为WORD文件内部的数据及格式等是通过XML文件的形式存储的,所以WORD文件可以很方便的实现由DOC到XML格式的相互转换,而操作XML文件就方便的多了,这样就实现了与平台无关的各种操作,通过节点的查询、替换、删除、新增等生成Word文件。所以,根据模板生成WORD文件实质就是由用户数据替换XML文件中特殊标签,然后另存为一个DOC文件的过程。

下面列举涉及到的一些关键步骤(以介绍信为例)

第一步:根据需求制作WORD模板

新建一个DOC格式的WORD文件,根据需要填写好模板内容,设置好模板的格式,包括字体,样式,空行等等,需要填充的数据使用特殊标签(如:【※单位名称※】)预先占位,然后将新建的WORD文件另存为XML格式文件。这样, WORD模板就制作完成了,代码如下:

 第二步:在配置文件中配置好模板信息

新增名为template-rule.xml的配置文件,每个template节点对应一个模板类型。每个template中有一个taglist节点,该节点包含的所有子节点包含了模板所有将要替换、删除节点信息,节点信息包括:节点值,节点属性英文名称,中文描述,字段类型,可否删除等信息。在设置这个配置文件时候,需要注意desc属性的值必须与模板XML中的占位符一致。比如:模板XML中设置的年份这个录入项【※年※】需与template-rule.xml中的desc="年"名称对应,代码如下:

代码如下:




   
   
       
            #ToPartment
            #OwnerName
            #CountNum
            #Business
            #UsefulDays
            #Year
            #Month
            #Day
       
   

第三步:编写java代码

代码如下:

/**
 * 参数及规则
 */
public class RuleDTO {
    /**
     * tag名称
     */
    private String parmName;
    /**
     * tag描述
     */
    private String parmDesc;
    /**
     * tag序号
     */
    private String parmSeq;
    /**
     * tag值类型
     */
    private String parmType;
    /**
     * tag参数名称
     */
    private String parmRegular;
    /**
     * tag值
     */
    private String parmValue;    
    /**
     * tag值为空删除该属性
     */
    private String ifEmptyDelete;

}

代码如下:

/**
 * 描述: Word模板信息
 */
public class Template {

    private String name;//模板名

    private String desc;//模板描述

    private String templateFile;//模板文件

    private Vector rules;//模板规则

}

代码如下:

public class WordBuilder {

    /**
     * 根据模板读取替换规则
     * @param templateName  模板ID
     */
    @SuppressWarnings("unchecked")
    public Template loadRules(Map ruleValue) {
        InputStream in = null;
        Template template = new Template();
        // 规则配置文件路径
        String ruleFile = "template-rule.xml";

        // 模板规则名称
        String templateRuleName = "";
        try {
            templateRuleName = ruleValue.get("ruleName");
            // 读取模板规则文件
            in = this.getClass().getClassLoader().getResourceAsStream(ruleFile);
            // 解析模板规则
            SAXBuilder sb = new SAXBuilder();
            Document doc = sb.build(in);
            Element root = doc.getRootElement(); // 得到根元素
            List templateList = root.getChildren();// 所有模板配置
            Element element = null;
            Vector rules = null;
            for (int i = 0; i < templateList.size(); i++) {// 遍历所有模板
                element = (Element) templateList.get(i);
                String templateName = element.getAttributeValue("name");
                if (templateRuleName.equalsIgnoreCase(templateName)) {// 查找给定的模板配置
                    template.setName(templateName);
                    template.setDesc(element.getAttributeValue("desc"));
                    template.setTemplateFile(element
                            .getAttributeValue("templateFile"));
                    List tagList = ((Element) element.getChildren()
                            .get(0)).getChildren();// tag列表
                    Element tag = null;
                    RuleDTO ruleDTO = null;
                    rules = new Vector();
                    for (int j = 0; j < tagList.size(); j++) {
                        tag = (Element) tagList.get(j);
                        ruleDTO = new RuleDTO();
                        ruleDTO.setParmName(tag.getAttributeValue("name"));
                        ruleDTO.setParmDesc("【※"
                                + tag.getAttributeValue("desc") + "※】");
                        ruleDTO.setParmSeq(tag.getAttributeValue("id"));
                        ruleDTO.setParmType(tag.getAttributeValue("type"));
                        if ("T".equalsIgnoreCase(tag
                                .getAttributeValue("ifEmptyDelete"))) {// 是否可删除标记
                            ruleDTO.setIfEmptyDelete("T");
                        } else {
                            ruleDTO.setIfEmptyDelete("F");
                        }
                        ruleDTO.setParmRegular(tag.getText());
                        // 值
                        // 判断参数类型
                        String value = (String) ((Map) ruleValue)
                                .get(ruleDTO.getParmRegular().replaceAll("#",
                                        ""));
                        ruleDTO.setParmValue(value);
                        rules.add(ruleDTO);
                    }
                    template.setRules(rules);
                    break;
                }
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (JDOMException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                in.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return template;
    }

    /**
     * 查找父节点
     */
    public Element findElement(Element currNode, String parentNodeId) {
        // 节点标示为空
        if (currNode == null || parentNodeId == null) {
            return null;
        }
        Element pNode = null;
        do {
            pNode = currNode.getParent();
            currNode = pNode;
        } while (parentNodeId.equalsIgnoreCase(pNode.getName()));
        return pNode;
    }

    /**
     * 生成Word文件
     */
    @SuppressWarnings("unchecked")
    public String build(Template template) {
        InputStream in = null;
        OutputStream fo = null;
        // 生成文件的路径
        String file = "d:\test\" + template.getDesc() + ".doc";
        try {
            // 读取模板文件
            in = this.getClass().getClassLoader()
                    .getResourceAsStream(template.getTemplateFile());
            SAXBuilder sb = new SAXBuilder();
            Document doc = sb.build(in);
            Element root = doc.getRootElement(); // 得到根元素
            Namespace ns = root.getNamespace();// NameSpace
            // word 03模板存在元素
            List sectList = root.getChild("body", ns).getChildren();
            Element sectElement = (Element) sectList.get(0);
            // 下的标签集合
            List pTagList = sectElement.getChildren("p", ns);
            // 下的标签集合
            List tblTagList = sectElement.getChildren("tbl", ns);
            if (pTagList != null && pTagList.size() > 0) {
                changeValue4PTag(pTagList, template.getRules(), ns, null);
            }
            if (tblTagList != null && tblTagList.size() > 0) {
                changeValue4TblTag(tblTagList, template.getRules(), ns);
            }
            // 写文件
            XMLOutputter outp = new XMLOutputter(" ", true, "UTF-8");
            fo = new FileOutputStream(file);
            outp.output(doc, fo);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (JDOMException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                in.close();
                fo.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return file;
    }

    /**
     * 针对这种层级的WORD模板, 查找及替换下的标签。
     * @param pTagList :集合
     * @param rulesValue :RuleDTO集合
     * @param ns :NameSpace对象
     * @param trChildren :的子节点集合
     */
    @SuppressWarnings("unchecked")
    private boolean changeValue4PTag(List pTagList,
            Vector rulesValue, Namespace ns, List trChildren) {
        Element p = null;
        boolean delFlag = false;
        for (int i = 0; i < pTagList.size(); i++) {
            boolean delCurrNode = false;// 删除当前节点
            boolean delCurrNode4TabWR = false;// 删除table中单行节点
            p = (Element) pTagList.get(i);
            List pChild = p.getChildren("r", ns);
            for (int j = 0; pChild != null && j < pChild.size(); j++) {
                Element pChildren = (Element) pChild.get(j);
                Element t = pChildren.getChild("t", ns);
                if (t != null) {
                    String text = t.getTextTrim();
                    if (text.indexOf("【※") != -1) {
                        for (int v = 0; v < rulesValue.size(); v++) {
                            RuleDTO dto = (RuleDTO) rulesValue.get(v);
                            if (text.indexOf(dto.getParmDesc().trim()) != -1) {
                                // 判断属性值是否为可空删除
                                if ("T".equals(dto.getIfEmptyDelete())
                                        && StringUtils.isBlank(dto
                                                .getParmValue())) {
                                    // 删除该节点顶级节点
                                    text = "";
                                    if (trChildren != null) {// 针对删除该行
                                        Element element = ((Element) p
                                                .getParent()).getParent();
                                        trChildren.remove(element);
                                        delCurrNode4TabWR = true;
                                    } else {// 针对删除段
                                            // pTagList.remove(p);
                                        pTagList.remove(pChildren);
                                        delCurrNode = true;
                                    }
                                    break;
                                } else {
                                    text = text.replaceAll(dto.getParmDesc()
                                            .trim(), dto.getParmValue());
                                }
                            }
                        }
                        t.setText(text);
                    }
                    if (delCurrNode4TabWR) {// TABLE下的行节点已删除
                        delFlag = true;
                        break;
                    } else if (delCurrNode) {// 下的节点已删除
                        i--;
                        delFlag = true;
                        break;
                    }
                }
            }
        }
        return delFlag;
    }

    /**
     * 针对含有表格的WORD模板, 查找及替换下的标签。
     * @param tblTagList :集合
     * @param rulesValue :RuleDTO集合
     * @param ns :NameSpace对象
     */
    @SuppressWarnings("unchecked")
    private void changeValue4TblTag(List tblTagList,
            Vector rulesValue, Namespace ns) {
        Element p = null;
        for (int i = 0; tblTagList != null && i < tblTagList.size(); i++) {
            p = (Element) tblTagList.get(i);
            List trChildren = p.getChildren("tr", ns);
            for (int j = 0; trChildren != null && j < trChildren.size(); j++) {// 循环
                Element pChildren = (Element) trChildren.get(j);
                List tcTagList = pChildren.getChildren("tc", ns);
                for (int c = 0; tcTagList != null && c < tcTagList.size(); c++) {// 循环取集合
                    Element tcChildren = (Element) tcTagList.get(c);
                    List pTagList = tcChildren.getChildren("p", ns);
                    boolean delFlag = changeValue4PTag(pTagList, rulesValue,
                            ns, trChildren);
                    if (delFlag) {// 删除行后需要改变trChildren的指针位置
                        j--;
                    }
                }
            }
        }
    }

    public static void main(String[] args) throws Exception {
        WordBuilder word = new WordBuilder();
        Map map = new HashMap();
        //填充参数
        map.put("ToPartment", "XXX公司");
        map.put("OwnerName", "张三");
        map.put("CountNum", "5");
        map.put("Business", "例行检查");
        map.put("UsefulDays", "15");
        map.put("Year", "2014");
        map.put("Month", "5");
        map.put("Day", "13");
        map.put("ruleName", "RECOMMEND-LETTER");
        Template template = word.loadRules(map);
        //直接打开文件
        Runtime.getRuntime().exec("explorer " + word.build(template));
    }
}

第四步:大功告成

几点总结及注意事项:

1. 定义的元素name必须与template_rule.xml中对应相同的name的值一致,否则需要设置转换规则。

2. 模板xml中定义的占位符【※※】中的文字必须与template_rule.xml中对应的desc相同,否则需要设置转换规则.

3. 在配置好模板XML后,需要检查标签下的子节点是否是标签(与WORD版本有关),如果没有,则必须加上该标签。

4. 如果要动态删除标签节点,则这个节点的内容需要在模板中的同一行,如果不是,则可以手动调整模板XML。

5. 如果需要实现WORD自动换行功能(关于模板中换行的方案暂没有想到更好的),则需要首先计算出对应模板该行的字数,然后采用空格填充来实现。 


    
 
 

您可能感兴趣的文章:

  • Java代码自动生成工具 JunJava
  • 有没有报表自动生成工具for java的,如VB的seagate crystal Reports?
  • 用jdk编译Java能不能让编译生成的.class文件自动保存到一个文件夹下?
  • java 自动生成略缩图示例代码
  • java生成字母数字组合的随机数示例 java生成随机数
  • 用JBuilder能将java程序生成exe可执行文件吗?如何生成?
  • 我想问一下,java生成的.class文件能不能通过某种工具生成.exe文件?
  • Java能调用OLE对象吗?怎样利用Java生成Excel报表?
  • Hibernate映射文件生成工具 hbm2java
  • 请问 Java 里面有生成 Excel 文件的类吗?
  • Java 代码生成工具 JAnnocessor
  • 我要生成java 的文档在dos 下用什么命令.
  • Java的图片展示页面生成工具 Nail6
  • java怎样生成可执行文件?
  • UML类图生成工具 Java UML Generator
  • Java 的解析器代码生成器 AustenX
  • Java验证码生成库 JCaptcha
  • Java条形码生成库 Barcode4J
  • 用rose试图生成java代码,提示如下错误,求教高手!
  • 把java源程序生成应用程序有哪些方法?
  • Java 实体类生成工具 JavaEntityBuilder
  • Java验证码生成库 imageRandom
  • java里有没有什么方法能够生成一个唯一标识的
  • 最快速的java代码生成器 rapid-generator
  •  
    本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
    本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。












  • 相关文章推荐
  • elasticsearch RESTful项目举例说明: java jest
  • 菜鸟问题:企业级是什么?什么样的项目才叫企业级?Java是如何实现企业级的项目的?
  • JAVA初学者,很想知道各位在公司用JAVA具体做什么.有什么小项目适合新手做?
  • JAVA项目在Linux下的开发和部署
  • 我该用Java做些什么项目?
  • 本来想学java但进公司第一个项目作了vb,不知道还能不能学java,各位有什么好的建议么
  • Java项目管理工具 AgileTrack
  • 高薪诚聘java程序员(项目维护,后续开发)
  • 新手如何加入开源项目 有什么好的c++,java 开源适合新手 请指点!
  • 现在要做一个java项目,不知道需要了解哪些技术?
  • 各位学java的朋友,学java的未来是什么,你们学java都用来开发什么项目啊!来者给分!!
  • #######征集:想问问大家,都是用什么工具做java项目的安装程序的######
  • 请问使用java的公司都在做什么项目?
  • Java项目依赖分析工具 Tattletale
  • 老板突然要用java做项目,我一点都不懂,不知道用那本书好点?老板要求不能用microsoft的java.
  • java项目发布到linux环境,启动报错
  • 请各位帮忙:描述一些项目(要能提高编程水平,java水平)
  • 要用JAVA做项目,短期内的上手方法是什么?
  • linux下查看java项目虚拟内存很大,请高手指点下
  • Java报表项目 JMagallanes
  • java 获取项目文件路径实现方法
  • java命名空间java.sql类types的类成员方法: java_object定义及介绍
  • 我想学JAVA ,是买THINK IN JAVA 还是JAVA2核心技术:卷1 好???
  • java命名空间java.awt.datatransfer类dataflavor的类成员方法: imageflavor定义及介绍
  • 请问Java高手,Java的优势在那里??,Java主要适合于开发哪类应用程序
  • java命名空间java.lang.management类managementfactory的类成员方法: getcompilationmxbean定义及介绍
  • 如何将java.util.Date转化为java.sql.Date?数据库中Date类型对应于java的哪个Date呢
  • java命名空间java.lang.management接口runtimemxbean的类成员方法: getlibrarypath定义及介绍
  • 谁有电子版的《Java编程思想第二版(Thinking in java second)》和《Java2编程详解(special edition java2)》?得到给分
  • java命名空间java.lang.management接口runtimemxbean的类成员方法: getstarttime定义及介绍
  • 本人想学java,请问java程序员的待遇如何,和java主要有几个比较强的方向


  • 站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3