亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > Java > 正文

一個JAVA小項目--Web應用自動生成Word

2019-11-26 15:29:47
字體:
來源:轉載
供稿:網友

前段時間接到一個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="年"名稱對應,代碼如下:

復制代碼 代碼如下:

<!--?xml version="1.0" encoding="GB2312"?-->
<!-- 模板定義 -->
<templates>
    <!-- 說明: S-字符串; D-日期; E-金額; M-大寫金額; ifEmptyDelete: T-值為空刪除父節點,默認為F -->
    <template name="RECOMMEND-LETTER" desc="介紹信" templatefile="template4.xml">
        <taglist remark="單值標簽列表">
            <tag id="1" name="ToPartment" desc="接收部門" type="S" ifemptydelete="T">#ToPartment</tag><!--接收部門-->
            <tag id="2" name="OwnerName" desc="姓名" type="S">#OwnerName</tag><!--姓名-->
            <tag id="3" name="CountNum" desc="人數" type="S">#CountNum</tag><!--人數-->
            <tag id="4" name="Business" desc="內容" type="S">#Business</tag><!--內容-->
            <tag id="5" name="UsefulDays" desc="有效期" type="S">#UsefulDays</tag><!--有效期-->
            <tag id="6" name="Year" desc="年" type="S">#Year</tag><!--年-->
            <tag id="7" name="Month" desc="月" type="S">#Month</tag><!--月-->
            <tag id="8" name="Day" desc="日" type="S">#Day</tag><!--日-->
        </taglist>
    </template>
</templates>

第三步:編寫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<ruledto> rules;//模板規則

}</ruledto>

復制代碼 代碼如下:

public class WordBuilder {

    /**
     * 根據模板讀取替換規則
     * @param templateName  模板ID
     */
    @SuppressWarnings("unchecked")
    public Template loadRules(Map<string, string=""> 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<element> templateList = root.getChildren();// 所有模板配置
            Element element = null;
            Vector<ruledto> 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<element> tagList = ((Element) element.getChildren()
                            .get(0)).getChildren();// tag列表
                    Element tag = null;
                    RuleDTO ruleDTO = null;
                    rules = new Vector<ruledto>();
                    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<string, string="">) 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模板存在<wx:sect>元素
            List<element> sectList = root.getChild("body", ns).getChildren();
            Element sectElement = (Element) sectList.get(0);
            // <w:p>下的標簽集合
            List<element> pTagList = sectElement.getChildren("p", ns);
            // <w:tbl>下的標簽集合
            List<element> 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;
    }

    /**
     * 針對<w:body><wx:sect><w:p>這種層級的WORD模板, 查找及替換<w:p>下的標簽。
     * @param pTagList :<w:p>集合
     * @param rulesValue :RuleDTO集合
     * @param ns :NameSpace對象
     * @param trChildren :<w:tbl>的子節點<w:tr>集合
     */
    @SuppressWarnings("unchecked")
    private boolean changeValue4PTag(List<element> pTagList,
            Vector<ruledto> rulesValue, Namespace ns, List<element> 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<element> 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) {// 針對<w:tbl>刪除該行
                                        Element element = ((Element) p
                                                .getParent()).getParent();
                                        trChildren.remove(element);
                                        delCurrNode4TabWR = true;
                                    } else {// 針對<w:r>刪除段
                                            // pTagList.remove(p);
                                        pTagList.remove(pChildren);
                                        delCurrNode = true;
                                    }
                                    break;
                                } else {
                                    text = text.replaceAll(dto.getParmDesc()
                                            .trim(), dto.getParmValue());
                                }
                            }
                        }
                        t.setText(text);
                    }
                    if (delCurrNode4TabWR) {// <w:tbl>TABLE下的行節點已刪除
                        delFlag = true;
                        break;
                    } else if (delCurrNode) {// <w:p>下的節點已刪除
                        i--;
                        delFlag = true;
                        break;
                    }
                }
            }
        }
        return delFlag;
    }

    /**
     * 針對含有表格的WORD模板, 查找及替換<w:tbl>下的標簽。
     * @param tblTagList :<w:tbl>集合
     * @param rulesValue :RuleDTO集合
     * @param ns :NameSpace對象
     */
    @SuppressWarnings("unchecked")
    private void changeValue4TblTag(List<element> tblTagList,
            Vector<ruledto> rulesValue, Namespace ns) {
        Element p = null;
        for (int i = 0; tblTagList != null && i < tblTagList.size(); i++) {
            p = (Element) tblTagList.get(i);
            List<element> trChildren = p.getChildren("tr", ns);
            for (int j = 0; trChildren != null && j < trChildren.size(); j++) {// 循環<w:tr>
                Element pChildren = (Element) trChildren.get(j);
                List<element> tcTagList = pChildren.getChildren("tc", ns);
                for (int c = 0; tcTagList != null && c < tcTagList.size(); c++) {// 循環<w:tc>取<w:p>集合
                    Element tcChildren = (Element) tcTagList.get(c);
                    List<element> 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<string, string=""> map = new HashMap<string, string="">();
        //填充參數
        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));
    }
}</string,></string,></element></w:p></w:tc></element></w:tr></element></ruledto></element></w:tbl></w:tbl></w:p></w:tbl></w:r></w:tbl></element></element></ruledto></element></w:tr></w:tbl></w:p></w:p></w:p></wx:sect></w:body></element></w:tbl></element></w:p></element></wx:sect></string,></ruledto></element></ruledto></element></string,>

第四步:大功告成

幾點總結及注意事項:

1. 定義的元素name必須與template_rule.xml中對應相同的name的值一致,否則需要設置轉換規則。

2. 模板xml中定義的占位符【※※】中的文字必須與template_rule.xml中對應的desc相同,否則需要設置轉換規則.

3. 在配置好模板XML后,需要檢查標簽下的子節點是否是標簽(與WORD版本有關),如果沒有,則必須加上該標簽。

4. 如果要動態刪除標簽節點,則這個節點的內容需要在模板中的同一行,如果不是,則可以手動調整模板XML。

5. 如果需要實現WORD自動換行功能(關于模板中換行的方案暫沒有想到更好的),則需要首先計算出對應模板該行的字數,然后采用空格填充來實現。 

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产日韩中文字幕在线| 亚洲国产精品悠悠久久琪琪| 亚洲va欧美va国产综合剧情| 91天堂在线观看| 亚洲影影院av| 亚洲欧美国产精品专区久久| 欧美日韩在线观看视频| 亚洲国产精品久久久久秋霞不卡| 91大神福利视频在线| 欧美另类极品videosbest最新版本| 欧美在线观看www| 97超碰国产精品女人人人爽| 国产精品99一区| 国产精品极品在线| 欧美在线观看视频| 国产精品久久久久福利| 国产精品网址在线| 亚洲第一av网站| 亚洲欧美在线第一页| 久久久av一区| 久久亚洲精品视频| 国产精品视频中文字幕91| 亚洲影院色在线观看免费| 亚洲精品720p| 91丝袜美腿美女视频网站| 欧美老女人xx| 日韩精品在线观看视频| 国产视频精品自拍| 尤物yw午夜国产精品视频明星| 色99之美女主播在线视频| 日韩美女av在线免费观看| 国内精品一区二区三区四区| 精品视频在线播放免| 国产欧美日韩亚洲精品| 日韩精品中文字幕在线| 日韩精品免费视频| 91国内揄拍国内精品对白| 九九热视频这里只有精品| 日韩av电影中文字幕| 国产精品精品久久久久久| 精品国偷自产在线视频99| 精品毛片网大全| 国产成人啪精品视频免费网| 国产成人久久久精品一区| 国产视频亚洲视频| 日韩风俗一区 二区| 日韩av电影在线网| 国产一区玩具在线观看| 精品视频久久久| 国产精品成人一区二区| 亚洲福利在线看| 中文字幕欧美专区| 高清欧美一区二区三区| 久久天天躁狠狠躁夜夜爽蜜月| 国产日韩欧美91| 国产在线视频欧美| 国产精品丝袜久久久久久高清| 国产精品免费电影| 在线视频日本亚洲性| 欧美激情视频网址| 欧美一区亚洲一区| 亚洲高清一二三区| 日韩欧美国产中文字幕| 亚洲精品久久久久久久久久久久久| 亚洲国产日韩欧美在线99| 九色91av视频| 成人欧美在线观看| 欧美精品videossex88| 国产亚洲欧洲黄色| 亲爱的老师9免费观看全集电视剧| 欧美专区在线视频| 亚洲精品99久久久久| 91老司机精品视频| 日韩黄在线观看| 日韩高清av一区二区三区| 日韩一区二区福利| 亚洲成人网av| 亚洲国产精品久久精品怡红院| 久久精品国产2020观看福利| 久久久久久有精品国产| 91网站在线免费观看| 一区二区三区无码高清视频| 一本大道久久加勒比香蕉| 日韩高清人体午夜| 亚洲片av在线| 国产丝袜高跟一区| 91精品国产高清久久久久久久久| 丰满岳妇乱一区二区三区| 大胆人体色综合| 日韩在线视频网站| 欧美性视频网站| 国产成人免费91av在线| 韩剧1988在线观看免费完整版| 欧美与黑人午夜性猛交久久久| 国产日韩中文字幕在线| 日韩视频免费大全中文字幕| 亚洲欧美综合v| 亚洲人成免费电影| 成人国产在线激情| 97视频免费观看| 久久99久久99精品免观看粉嫩| 中文字幕精品www乱入免费视频| 大荫蒂欧美视频另类xxxx| 亚洲成色777777在线观看影院| 日韩中文字幕国产| 国产欧美日韩专区发布| 成人av在线天堂| 欧美寡妇偷汉性猛交| 欧美精品成人91久久久久久久| 亚洲一区二区久久久| 亚洲在线观看视频网站| 亚洲日本成人网| 精品福利樱桃av导航| 日韩欧美aⅴ综合网站发布| 亚洲精品短视频| 国产精品美女久久久久av超清| 精品一区二区三区三区| 久久99久国产精品黄毛片入口| 亚洲97在线观看| 亚洲成人激情图| 国产日本欧美一区二区三区| 91po在线观看91精品国产性色| 亚洲激情国产精品| 亚洲另类图片色| 精品久久久免费| 欧美日韩在线视频一区二区| 久久频这里精品99香蕉| 国产成人中文字幕| 亚洲а∨天堂久久精品喷水| 欧美成人手机在线| 国产精品1234| 欧美成人剧情片在线观看| 久久亚洲精品成人| 一区二区三区回区在观看免费视频| 亚洲无线码在线一区观看| 国产精品999| 亚洲va久久久噜噜噜| 成人黄色在线免费| 欧美最猛性xxxx| 热99精品里视频精品| 国产精品看片资源| 欧美一级高清免费| 欧美国产视频日韩| 色悠悠久久88| 久久久久久久久久久久av| 欧美高清电影在线看| 伊人久久久久久久久久久久久| 欧美精品videofree1080p| 一区国产精品视频| 中文字幕亚洲天堂| 午夜精品一区二区三区在线视频| 欧美疯狂xxxx大交乱88av| 亚洲天堂av电影| 欧美高跟鞋交xxxxhd| 国产精品91久久久| 亚洲第一中文字幕在线观看| 欧美乱妇高清无乱码| 国产日韩精品视频| 97人人模人人爽人人喊中文字| 欧美巨大黑人极品精男| 日韩精品视频免费在线观看| 国产精品十八以下禁看| 久久久亚洲成人| 日韩专区在线播放|