1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        用JAVA寫的word模板自動生成引擎

        共 9176字,需瀏覽 19分鐘

         ·

        2021-11-09 16:36

        大家好,我是TJ

        一個勵志推薦10000款開源項目與工具的程序員


        TJ君做項目的時候最頭疼什么?當(dāng)然是寫各種文檔啦,尤其是在大公司做項目,各種規(guī)范文檔不可少,雖然說一個成熟的項目管理過程中的確是要依靠各種文檔來明確項目里程碑及具體的設(shè)計確認和需求分工,但是TJ君還是更喜歡把時間花在開發(fā)代碼上。

        尤其是有些文檔的格式都差不多,那是不是我們程序猿可以發(fā)揮特長,用程序來生成輸出指定的word文檔,減少自己的手寫時間呢?

        當(dāng)然是可以的!

        今天TJ君就要給大家分享一款Word專用的模板引擎,Poi-tl(Poi-template-language)。這款引擎基于Apache Poi,可以根據(jù)用戶輸入的內(nèi)容直接生成相應(yīng)的word文檔,很是方便。

        Apache Poi是用Java編寫的一款免費開源的跨平臺的JavaAPI,該API可以通過Java程序?qū)ffice格式文檔進行讀寫操作,可以說是現(xiàn)階段Java庫當(dāng)中最好用的office處理庫了,可能都不用加之一兩個字。所以基于Apache Poi的Poi-tl可以讓你在word文檔的任何地方做任何你想做的事情。

        舉個例子,如果想生成一個名叫TJ君真棒.docx的文檔,并且在文檔里包含文本{{title}},只需要一句代碼,這句代碼也是整個引擎的核心所在:

        //核心API采用了極簡設(shè)計,只需要一行代碼
        XWPFTemplate.compile("TJ君真棒.docx").render(new?HashMap(){{
        ????????put("title",?"Poi-tl?模板引擎");
        }}).writeToFile("out_TJ君真棒.docx");

        Poi-tl整體設(shè)計采用了Template + data-model = output模式.

        Configure提供了模板配置功能,比如語法配置和插件配置:


        /**
        ?*?插件化配置
        ?*?
        ?*?@author?Sayi
        ?*?@version?1.0.0
        ?*/

        public?class?Configure?{

        ????//?defalut?expression
        ????private?static?final?String?DEFAULT_GRAMER_REGEX?=?"[\\w\\u4e00-\\u9fa5]+(\\.[\\w\\u4e00-\\u9fa5]+)*";

        ????//?Highest?priority
        ????private?Map?customPolicys?=?new?HashMap();
        ????//?Low?priority
        ????private?Map?defaultPolicys?=?new?HashMap();

        ????/**
        ?????*?引用渲染策略
        ?????*/

        ????private?List>?referencePolicies?=?new?ArrayList<>();

        ????/**
        ?????*?語法前綴
        ?????*/

        ????private?String?gramerPrefix?=?"{{";
        ????/**
        ?????*?語法后綴
        ?????*/

        ????private?String?gramerSuffix?=?"}}";

        ????/**
        ?????*?默認支持中文、字母、數(shù)字、下劃線的正則
        ?????*/

        ????private?String?grammerRegex?=?DEFAULT_GRAMER_REGEX;

        ????/**
        ?????*?模板表達式模式,默認為POI_TL_MODE
        ?????*/

        ????private?ELMode?elMode?=?ELMode.POI_TL_STANDARD_MODE;

        ????/**
        ?????*?渲染數(shù)據(jù)校驗不通過時的處理策略
        ?????*?

          ?????*?
        • DiscardHandler:?什么都不做

        • ?????*?
        • ClearHandler:?清空標(biāo)簽

        • ?????*?
        • AbortHandler:?拋出異常

        • ?????*?

        ?????*/

        ????private?ValidErrorHandler?handler?=?new?ClearHandler();

        ????private?Configure()?{
        ????????plugin(GramerSymbol.TEXT,?new?TextRenderPolicy());
        ????????plugin(GramerSymbol.IMAGE,?new?PictureRenderPolicy());
        ????????plugin(GramerSymbol.TABLE,?new?MiniTableRenderPolicy());
        ????????plugin(GramerSymbol.NUMBERIC,?new?NumbericRenderPolicy());
        ????????plugin(GramerSymbol.DOCX_TEMPLATE,?new?DocxRenderPolicy());
        ????}

        ????/**
        ?????*?創(chuàng)建默認配置
        ?????*?
        ?????*?@return
        ?????*/

        ????public?static?Configure?createDefault()?{
        ????????return?newBuilder().build();
        ????}

        ????/**
        ?????*?構(gòu)建器
        ?????*?
        ?????*?@return
        ?????*/

        ????public?static?ConfigureBuilder?newBuilder()?{
        ????????return?new?ConfigureBuilder();
        ????}

        ????/**
        ?????*?新增或變更語法插件
        ?????*?
        ?????*?@param?c
        ?????*????????????語法
        ?????*?@param?policy
        ?????*????????????策略
        ?????*/

        ????public?Configure?plugin(char?c,?RenderPolicy?policy)?{
        ????????defaultPolicys.put(Character.valueOf(c),?policy);
        ????????return?this;
        ????}

        ????/**
        ?????*?新增或變更語法插件
        ?????*?
        ?????*?@param?symbol
        ?????*????????????語法
        ?????*?@param?policy
        ?????*????????????策略
        ?????*?@return
        ?????*/

        ????Configure?plugin(GramerSymbol?symbol,?RenderPolicy?policy)?{
        ????????defaultPolicys.put(symbol.getSymbol(),?policy);
        ????????return?this;
        ????}

        ????/**
        ?????*?自定義模板和策略
        ?????*?
        ?????*?@param?tagName
        ?????*????????????模板名稱
        ?????*?@param?policy
        ?????*????????????策略
        ?????*/

        ????public?void?customPolicy(String?tagName,?RenderPolicy?policy)?{
        ????????customPolicys.put(tagName,?policy);
        ????}

        ????/**
        ?????*?新增引用渲染策略
        ?????*?
        ?????*?@param?policy
        ?????*/

        ????public?void?referencePolicy(ReferenceRenderPolicy?policy)?{
        ????????referencePolicies.add(policy);
        ????}

        ????/**
        ?????*?獲取標(biāo)簽策略
        ?????*?
        ?????*?@param?tagName
        ?????*????????????模板名稱
        ?????*?@param?sign
        ?????*????????????語法
        ?????*/

        ????//?Query?Operations

        ????public?RenderPolicy?getPolicy(String?tagName,?Character?sign)?{
        ????????RenderPolicy?policy?=?getCustomPolicy(tagName);
        ????????return?null?==?policy???getDefaultPolicy(sign)?:?policy;
        ????}

        ????public?List>?getReferencePolicies()?{
        ????????return?referencePolicies;
        ????}
        ????
        ????private?RenderPolicy?getCustomPolicy(String?tagName)?{
        ????????return?customPolicys.get(tagName);
        ????}

        ????private?RenderPolicy?getDefaultPolicy(Character?sign)?{
        ????????return?defaultPolicys.get(sign);
        ????}

        ????public?Map?getDefaultPolicys()?{
        ????????return?defaultPolicys;
        ????}

        ????public?Map?getCustomPolicys()?{
        ????????return?customPolicys;
        ????}

        ????public?Set?getGramerChars()?{
        ????????return?defaultPolicys.keySet();
        ????}

        ????public?String?getGramerPrefix()?{
        ????????return?gramerPrefix;
        ????}

        ????public?String?getGramerSuffix()?{
        ????????return?gramerSuffix;
        ????}

        ????public?String?getGrammerRegex()?{
        ????????return?grammerRegex;
        ????}

        ????public?ELMode?getElMode()?{
        ????????return?elMode;
        ????}

        ????public?ValidErrorHandler?getValidErrorHandler()?{
        ????????return?handler;
        ????}

        ????public?static?class?ConfigureBuilder?{
        ????????private?boolean?regexForAll;
        ????????private?Configure?config;

        ????????public?ConfigureBuilder()?{
        ????????????config?=?new?Configure();
        ????????}

        ????????public?ConfigureBuilder?buildGramer(String?prefix,?String?suffix)?{
        ????????????config.gramerPrefix?=?prefix;
        ????????????config.gramerSuffix?=?suffix;
        ????????????return?this;
        ????????}

        ????????public?ConfigureBuilder?buildGrammerRegex(String?reg)?{
        ????????????config.grammerRegex?=?reg;
        ????????????return?this;
        ????????}

        ????????public?ConfigureBuilder?supportGrammerRegexForAll()?{
        ????????????this.regexForAll?=?true;
        ????????????return?this;
        ????????}

        ????????public?ConfigureBuilder?setElMode(ELMode?mode)?{
        ????????????config.elMode?=?mode;
        ????????????return?this;
        ????????}

        ????????public?ConfigureBuilder?setValidErrorHandler(ValidErrorHandler?handler)?{
        ????????????config.handler?=?handler;
        ????????????return?this;
        ????????}

        ????????public?ConfigureBuilder?addPlugin(char?c,?RenderPolicy?policy)?{
        ????????????config.plugin(c,?policy);
        ????????????return?this;
        ????????}

        ????????public?ConfigureBuilder?customPolicy(String?tagName,?RenderPolicy?policy)?{
        ????????????config.customPolicy(tagName,?policy);
        ????????????return?this;
        ????????}

        ????????public?ConfigureBuilder?referencePolicy(ReferenceRenderPolicy?policy)?{
        ????????????config.referencePolicy(policy);
        ????????????return?this;
        ????????}

        ????????public?ConfigureBuilder?bind(String?tagName,?RenderPolicy?policy)?{
        ????????????config.customPolicy(tagName,?policy);
        ????????????return?this;
        ????????}

        ????????public?Configure?build()?{
        ????????????if?(config.elMode?==?ELMode.SPEL_MODE)?{
        ????????????????regexForAll?=?true;
        ????????????}
        ????????????if?(regexForAll)?{
        ????????????????config.grammerRegex?=?RegexUtils.createGeneral(config.gramerPrefix,
        ????????????????????????config.gramerSuffix);
        ????????????}
        ????????????return?config;
        ????????}
        ????}
        }

        Visitor提供了模板解析功能:

        /**
        ?*?模板解析器
        ?*?
        ?*?@author?Sayi
        ?*?@version?1.4.0
        ?*/

        public?class?TemplateVisitor?implements?Visitor?{
        ????private?static?Logger?logger?=?LoggerFactory.getLogger(TemplateVisitor.class);

        ????private?Configure?config;
        ????private?List?eleTemplates;

        ????private?Pattern?templatePattern;
        ????private?Pattern?gramerPattern;

        ????static?final?String?FORMAT_TEMPLATE?=?"{0}{1}{2}{3}";
        ????static?final?String?FORMAT_GRAMER?=?"({0})|({1})";

        ????public?TemplateVisitor(Configure?config)?{
        ????????this.config?=?config;
        ????????initPattern();
        ????}

        ????@Override
        ????public?List?visitDocument(XWPFDocument?doc)?{
        ????????if?(null?==?doc)?return?null;
        ????????this.eleTemplates?=?new?ArrayList();
        ????????logger.info("Visit?the?document?start...");
        ????????visitParagraphs(doc.getParagraphs());
        ????????visitTables(doc.getTables());
        ????????visitHeaders(doc.getHeaderList());
        ????????visitFooters(doc.getFooterList());
        ????????logger.info("Visit?the?document?end,?resolve?and?create?{}?ElementTemplates.",
        ????????????????this.eleTemplates.size());
        ????????return?eleTemplates;
        ????}

        ????void?visitHeaders(List?headers)?{
        ????????if?(null?==?headers)?return;
        ????????for?(XWPFHeader?header?:?headers)?{
        ????????????visitParagraphs(header.getParagraphs());
        ????????????visitTables(header.getTables());
        ????????}
        ????}

        ????void?visitFooters(List?footers)?{
        ????????if?(null?==?footers)?return;
        ????????for?(XWPFFooter?footer?:?footers)?{
        ????????????visitParagraphs(footer.getParagraphs());
        ????????????visitTables(footer.getTables());
        ????????}
        ????}

        ????void?visitParagraphs(List?paragraphs)?{
        ????????if?(null?==?paragraphs)?return;
        ????????for?(XWPFParagraph?paragraph?:?paragraphs)?{
        ????????????visitParagraph(paragraph);
        ????????}
        ????}

        ????void?visitTables(List?tables)?{
        ????????if?(null?==?tables)?return;
        ????????for?(XWPFTable?tb?:?tables)?{
        ????????????visitTable(tb);
        ????????}
        ????}

        ????void?visitTable(XWPFTable?table)?{
        ????????if?(null?==?table)?return;
        ????????List?rows?=?table.getRows();
        ????????if?(null?==?rows)?return;
        ????????for?(XWPFTableRow?row?:?rows)?{
        ????????????List?cells?=?row.getTableCells();
        ????????????if?(null?==?cells)?continue;
        ????????????for?(XWPFTableCell?cell?:?cells)?{
        ????????????????visitParagraphs(cell.getParagraphs());
        ????????????????visitTables(cell.getTables());
        ????????????}
        ????????}
        ????}

        ????void?visitParagraph(XWPFParagraph?paragraph)?{
        ????????if?(null?==?paragraph)?return;
        ????????RunningRunParagraph?runningRun?=?new?RunningRunParagraph(paragraph,?templatePattern);
        ????????List?refactorRun?=?runningRun.refactorRun();
        ????????if?(null?==?refactorRun)?return;
        ????????for?(XWPFRun?run?:?refactorRun)?{
        ????????????visitRun(run);
        ????????}
        ????}

        ????void?visitRun(XWPFRun?run)?{
        ????????String?text?=?null;
        ????????if?(null?==?run?||?StringUtils.isBlank(text?=?run.getText(0)))?return;
        ????????ElementTemplate?elementTemplate?=?parseTemplateFactory(text,?run);
        ????????if?(null?!=?elementTemplate)?eleTemplates.add(elementTemplate);
        ????}

        ????private??ElementTemplate?parseTemplateFactory(String?text,?T?obj)?{
        ????????logger.debug("Resolve?where?text:?{},?and?create?ElementTemplate",?text);
        ????????//?temp?,future?need?to?word?analyze
        ????????if?(templatePattern.matcher(text).matches())?{
        ????????????String?tag?=?gramerPattern.matcher(text).replaceAll("").trim();
        ????????????if?(obj.getClass()?==?XWPFRun.class)?{
        ????????????????return?TemplateFactory.createRunTemplate(tag,?config,?(XWPFRun)?obj);
        ????????????}?else?if?(obj.getClass()?==?XWPFTableCell.class)
        ????????????????//?return?CellTemplate.create(symbol,?tagName,?(XWPFTableCell)
        ????????????????//?obj)
        ;
        ????????????????return?null;
        ????????}
        ????????return?null;
        ????}

        ????private?void?initPattern()?{
        ????????String?signRegex?=?getGramarRegex(config);
        ????????String?prefixRegex?=?RegexUtils.escapeExprSpecialWord(config.getGramerPrefix());
        ????????String?suffixRegex?=?RegexUtils.escapeExprSpecialWord(config.getGramerSuffix());

        ????????templatePattern?=?Pattern.compile(MessageFormat.format(FORMAT_TEMPLATE,?prefixRegex,
        ????????????????signRegex,?config.getGrammerRegex(),?suffixRegex));
        ????????gramerPattern?=?Pattern
        ????????????????.compile(MessageFormat.format(FORMAT_GRAMER,?prefixRegex,?suffixRegex));
        ????}

        ????private?String?getGramarRegex(Configure?config)?{
        ????????List?gramerChar?=?new?ArrayList(config.getGramerChars());
        ????????StringBuilder?reg?=?new?StringBuilder("(");
        ????????for?(int?i?=?0;;?i++)?{
        ????????????Character?chara?=?gramerChar.get(i);
        ????????????String?escapeExprSpecialWord?=?RegexUtils.escapeExprSpecialWord(chara.toString());
        ????????????if?(i?==?gramerChar.size()?-?1)?{
        ????????????????reg.append(escapeExprSpecialWord).append(")?");
        ????????????????break;
        ????????????}?else?reg.append(escapeExprSpecialWord).append("|");
        ????????}
        ????????return?reg.toString();
        ????}

        }

        最后,RenderPolicy是渲染策略擴展點,Render模塊提供了RenderDataCompute表達式計算擴展點,通過RenderPolicy對每個標(biāo)簽進行渲染。

        當(dāng)然,如果想將Poi-tl用的好的話,還是要花一點時間來研究其中具體模塊的語法,好在Poi-tl提供詳細的示例代碼講解,小伙伴們只要用心學(xué)一下,很快就能掌握的

        到底能不能讓小伙伴們減輕寫文檔的壓力呢?記得用過之后來給TJ君反饋哦!想用的小伙伴,完整項目地址在這里:

        點擊下方卡片,關(guān)注公眾號“TJ君

        回復(fù)“生成word”,獲取倉庫地址

        關(guān)注我,每天了解一個牛x、好用、有趣的東東

        往期推薦

        GitHub高贊,一款足以取代迅雷的開源下載工具

        Copilot 爆裂更新,通過注釋自動生成代碼現(xiàn)已支持 IntelliJ IDEA、PyCharm

        可能是你用過最好用的Redis客戶端!

        IDEA中文字符自動轉(zhuǎn)換插件,再也不用擔(dān)心程序因為中文字符報錯了!

        IDEA編碼自動注釋工具,讓你的開發(fā)更有效率

        十萬伏特!讓你的操作終端變成寶可夢!


        瀏覽 82
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            网友自拍-熊猫成人网 | 无遮挡男女一进一出视频真人 | 娇小1213╳yⅹ╳毛片 | 中国女人特级毛片 | 女上男下吃奶100动态图 | 撒尿小便hd性偷窥tube | 女生和女生操 | 黑人性爱视频 | 日本AAA片免费观看 | 性生交大片免费看一女三男 |