FreemarkerJavaDemo【Android將表單數據生成Word文檔的方案之一(基於freemarker2.3.28,只能java生成)】

来源:https://www.cnblogs.com/whycxb/archive/2019/04/26/9781839.html
-Advertisement-
Play Games

版權聲明:本文為HaiyuKing原創文章,轉載請註明出處! 前言 這個方案只能在java中運行,無法在Android項目中運行。所以此方案是:APP將表單數據發送給後臺,後臺通過freemarker將表單數據根據模板ftl文件生成Word文件,然後返回給APP,由APP進行展現。 前期準備 1、下 ...


版權聲明:本文為HaiyuKing原創文章,轉載請註明出處!

前言

這個方案只能在java中運行,無法在Android項目中運行。所以此方案是:APP將表單數據發送給後臺,後臺通過freemarker將表單數據根據模板ftl文件生成Word文件,然後返回給APP,由APP進行展現。

前期準備

1、下載freemarker.jar文件

官網下載地址:https://freemarker.apache.org/freemarkerdownload.html

 

後續將freemarker.jar文件添加到項目中。

2、製作模板ftl文件

(1)先用office2003或更高版本word軟體編輯好word模版文件【版本要2003以上,2003以下的不支持另存為xml格式功能】

註意:

  • 在word模板中寫入相對真實的數據【註意,不要使用英文,儘量使用中文、數字,見附錄1】;
  • 對於對勾樣式的數據,在word模板文件中統一用安卓代替(後續需要通過java代碼傳入帶有對勾樣式的數據);
  • 需要設置圖片的話,需要在word模板文件中放入真實的圖片占位;請儘量選擇小於50K的圖片,並且把圖片的大小和位置調整好。選擇小圖片的原因是避免xml文件過大導致打開時緩慢甚至卡死。

例子:

 

(2)另存為Word 2003 XML文檔

對於Word2016,另存為後會自動打開xml文件,所以需要先關閉xml文件,然後再使用FirstObject XML Editor軟體打開xml文件!

(3)下載FirstObject XML Editor軟體

 下載FirstObject XML Editor軟體(免安裝版):下載地址:http://www.firstobject.com/dn_editor.htm

   

官網下載的軟體打開文件的時候可能會出現崩潰的問題建議使用foxe_CHS.exe軟體進行編輯。下載地址見項目Demo下載地址。

(4)使用FirstObject XML Editor軟體將xml打開,將真實數據換成FreeMarker標記

首先進行“縮進排版”

查找真實數據,替換成FreeMarker標記,其實就是Map<String, Object>中key,如${writeDate},對應Map的key值就是writeDate。

替換成:

對於文本按照上面的方式進行替換,而對於圖片需要這樣替換:

圖片是以base64編碼存在的,且這些編碼放在<w:binData>標簽之中。將這些base64編碼使用占位符代替,然後java代碼中將圖片生成base64編碼,傳入值就能正常顯示了。

替換成

(5)然後保存,直接將文件尾碼修改為.ftl(FreeMarker模板)

 

註意:一定不要用word打開ftl模板文件查看,否則xml內容會發生變化,導致前面的工作白做了;可以使用EditPlus打開查看。

使用步驟

一、項目組織結構圖

二、導入步驟

1、在項目中引入freemarker.jar

2、將製作的模板文件leaveTemplet.ftl和圖片資源複製到D:/temp目錄下

3、將DocumentHandler.java文件複製到項目中

package com.why.main;

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.InputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import sun.misc.BASE64Encoder;

/**
 * 生成Doc文檔
 */
public class DocumentHandler {

    //測試
    public static void main(String[] args) {
        DocumentHandler documentHandler = new DocumentHandler();
        documentHandler.createDoc();
    }

    // 配置實例:只需要一個實例(單例模式)
    private Configuration configuration = null;

    private String tempDirPath = "D:/temp";

    public DocumentHandler() {
        // 通過Freemaker的Configuration讀取相應的ftl
        configuration = new Configuration(Configuration.VERSION_2_3_28);
        configuration.setDefaultEncoding("UTF-8");// 設置預設編碼方式
    }

    /**
     * 生成DOC文檔
     */
    public void createDoc() {
        // 要填入模本的數據文件
        Map<String,Object> dataMap = new HashMap<String,Object>();
        getData(dataMap);
        // 設置模本裝置方法和路徑,FreeMarker支持多種模板裝載方法。可以重servlet,classpath,資料庫裝載,
        // 如果模板是放在程式代碼的包下麵
        //configuration.setClassForTemplateLoading(this.getClass(),"../");
        //如果放到伺服器目錄中,則使用下麵的代碼
        try {
            configuration.setDirectoryForTemplateLoading(new File(tempDirPath));
        } catch (IOException e2) {
            e2.printStackTrace();
        }
        //這裡要設置取消使用Local語言環境
        configuration.setLocalizedLookup(false);
        Template template = null;
        try {
            // leaveTemplet.ftl為要裝載的模板
            template = configuration.getTemplate("leaveTemplet.ftl","UTF-8");
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 輸出文檔路徑及名稱
        File dir = new File(tempDirPath);
        File outFile = new File(tempDirPath + "/請假條.doc");
        if (!dir.isDirectory()) {
            dir.mkdir();
            if (!outFile.exists()) {
                try {
                    outFile.createNewFile();
                } catch (IOException e) {
                    System.out.println("創建文件失敗");
                    e.printStackTrace();
                }
            }
        }
        Writer out = null;
        try {
            try {
                out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "UTF-8"));
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }

        } catch (FileNotFoundException e1) {
            System.out.println("輸出文件失敗");
            e1.printStackTrace();
        }
        try {
            template.process(dataMap, out);
            System.out.println("it's success!");
        } catch (TemplateException e) {
            System.out.println("生成失敗");
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 註意dataMap里存放的數據Key值要與模板中的參數相對應
     */
    private void getData(Map<String,Object> dataMap) {
        String imgBase64Str = getImageStr(tempDirPath + "/leaderopinion_img.png");

        // 使用String的有參構造方法
        dataMap.put("writeDate","2018年10月13日");//填寫日期
        dataMap.put("name","HaiyuKing");//姓名
        dataMap.put("dept","移動組");//部門
        dataMap.put("leaveType","☑倒休 √年假 ✔事假 ☐病假 ☐婚假 ☐產假 ☐其他");//請假類型
        dataMap.put("leaveReason","倒休休息兩天");//請假理由
        dataMap.put("leaveStartDate","2018年10月13日上午");//請假開始日期
        dataMap.put("leaveEndDate","2018年10月14日下午");//請假結束日期
        dataMap.put("leaveDay","2");//請假天數
        dataMap.put("leaveLeader","同意");//直屬領導意見
        dataMap.put("leaveDeptLeaderImg",imgBase64Str);//部門領導意見

    }

    /**
     * 獲取圖片的base64值*/
    private String getImageStr(String imgFile) {
        InputStream in = null;
        byte[] data = null;
        try {
            in = new FileInputStream(imgFile);
            data = new byte[in.available()];
            in.read(data);
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        BASE64Encoder encoder = new BASE64Encoder();
        return encoder.encode(data);
    }
}
DocumentHandler.java

註意:Map數據中的key值,對應ftl文件中的${xxxx}這裡面的xxxx值。

4、運行

5、效果

附錄

1、Word模板中輸入真實數據的技巧

1、不要使用英文;

2、如果想要保證一個整體,不要將中文、數字、標點符號一起使用(這裡指占位區域);

3、日期想要作為一個整體,不要數字+中文輸入,而是通過Enter鍵輸入;

下麵記錄的是不同輸入的效果(使用FirstObject XML Editor軟體打開xml文件)

使用英文:

使用數字:

使用中文:

 日期採用數字+中文:

日期採用Enter鍵輸入:

中文+標點符號:

參考資料

java生成word的幾種方案

沫沫金:使用Java模版引擎FreeMarker生成複雜的Word文檔

模板引擎freemarker的簡單使用教程

使用freemarker生成word,步驟詳解並奉上源代碼

firstobject XML 編輯器

freemarker官網

用Freemarker導出word文檔

Android利用FreeMarker自動生成文件

Freemarker入門案例

freeMarker生成各類文件,含圖片

FreeMaker解析Word模板(含圖片)生成Word文檔

項目demo下載地址

鏈接:https://pan.baidu.com/s/19aPNIYWXt5GMN_KDQjFCRA 提取碼:eo0n


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 物理設計: 選擇合適的資料庫管理系統。 考慮因素:成本,業務場景,開發語言,功能,操作系統等。 選擇合適的資料庫管理系統。 考慮因素:成本,業務場景,開發語言,功能,操作系統等。 Oracle 2.定義資料庫,表及欄位,要符合命名規範。 選擇存儲引擎:這裡以MySQL為例 選擇存儲引擎:這裡以MyS ...
  • 複製集 一、複製集概述: Mongodb複製集(replica set)由一組Mongod實例(進程)組成,包含一個Primary節點和多個Secondary節點,Mongodb Driver(客戶端)的所有數據都寫入Primary,Secondary通過oplog來同步Primary的數據,保證主 ...
  • 可以執行以下語句:select username,serial#, sid from v$session; 查詢用戶會話alter system kill session 'serial#, sid '; 刪除相關用戶會話 建議以後臺登陸刪除用戶會話1、查詢oracle的連接數select coun ...
  • [root@localhost ~]# vi /etc/exports #增加/nfs 192.168.10.132(rw,no_root_squash,no_all_squash,async) [root@testdg ~]# mount -t nfs 192.168.10.20:/nfs /rm ...
  • 有時候在我們開發的過程中並不一定記得資料庫的安裝路徑。比如要查看mysql 資料庫的安裝目錄在哪裡:我們可以通過mysql命令查看mysql的安裝路徑: 上面可以看到基礎的安裝路徑,查看資料庫data的路徑怎麼看,很簡單,把上面的參數變數緩存datadir即可: 當然上面是基於能登錄到mysql視窗 ...
  • 一、概述: AIDL是Android中IPC(Inter-Process Communication)方式中的一種,AIDL是Android Interface definition language的縮寫。 其主要作用是用於進程間額通訊。 在Android系統中,每個進程都運行在一塊獨立的記憶體中, ...
  • i500是一款強大而高效的AIoT平臺,專為攜帶型、家用或商用物聯網應用而設計,這些應用需要大量的邊緣處理、先進的多媒體功能、多台高解析度相機、相連的觸屏顯示器和多任務操作系統。 該平臺集成了Arm Cortex-A73 和 Cortex-A53 的四核集群,每個 CPU 都具備 NEON 引擎,集 ...
  • Hi3516EV300晶元特點: 處理器內核 ARM Cortex A7@ 900MHz,32KB I-Cache,32KB D-Cache /128KB L2 cache 支持 Neon 加速,集成 FPU 處理單元 視頻編碼 H.264 BP/MP/HP,支持 I/P 幀 H.265 Main ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...