使用XDocReport將HTML格式數據轉換為Word


文檔地址:https://github.com/opensagres/xdocreport/wiki/DocxReportingQuickStart

本文采用XDocReport集合Freemaiker進行處理

1. 引入Maven依賴:

<dependency>
    <groupId>fr.opensagres.xdocreport</groupId>
    <artifactId>xdocreport</artifactId>
    <version>2.0.1</version>
</dependency>
<dependency>
    <groupId>org.apache.velocity</groupId>
    <artifactId>velocity-engine-core</artifactId>
    <version>2.0</version>
</dependency>
<dependency>
    <groupId>org.freemarker</groupId>
    <artifactId>freemarker</artifactId>
    <version>2.3.23</version>
</dependency>

2. 創建Word模版

新建Word,在光標處通過快捷鍵Ctrl+F9 或 工具欄“插入”->“文檔部件或文本”->“域”

根據電腦系統不同出現的界面不同,但內容都差不多,${text} 這個text就是后期要替換的變量了。

3. Java代碼處理邏輯

 1 String templateFilePath = request.getSession().getServletContext().getRealPath("/WEB-INF/templates/freemarkerTest.docx");
 2 File file = new File(templateFilePath);
 3 InputStream in = new FileInputStream(file);
 4 IXDocReport report;
 5 String targetPath = basePath + lawDownDto.getLawsName() + ".docx";
 6 try {
 7     report = XDocReportRegistry.getRegistry().loadReport(in, TemplateEngineKind.Freemarker);
 8     // 設置內容為HTML格式
 9     FieldsMetadata metadata = report.createFieldsMetadata();
10     metadata.addFieldAsTextStyling("text", SyntaxKind.Html);   
11 
12     // 創建內容-text為模版中對應都變量名稱
13     IContext context = report.createContext();
14     context.put("text", content);
15             
16     // 生成文件
17     OutputStream out = new FileOutputStream(targetPath);
18     report.process(context, out);
19 } catch (XDocReportException e) {
20     e.printStackTrace();
21 }

文件下載:在生成文件邏輯后創建讀取流返回即可。

=============================================================

如果文件中有圖片需要處理:

  圖片方案一:單個圖片且位置固定,可通過XDocReport配置模版處理

  圖片方案二:多個圖片且位置不固定,可通過POI結合Freemarker進行處理

圖片方案一:

  1. 在模版中插入臨時圖片,選中圖片並添加“書簽”,書簽名稱是后續作為替換的變量

  

  2. 代碼中追加邏輯

  在上面代碼10后追加

// logo為模版中標簽名稱
metadata.addFieldAsImage("logo");
report.setFieldsMetadata(metadata);

  在上面代碼14行后追加

// IImageProvider可通過3種方式創建(File/IO流/ClassPath下文件)具體可參考頂部文檔-Dynamic Image
IImageProvider logo = new FileImageProvider(new File("1950737_195902644.png"));
context.put("logo", logo);

圖片方案二:

  1. 在上面讀取模版之前進行數據替換

// 處理文本中的圖片,使用imgReplace變量替換
Map<String, Object> param = new HashMap<String, Object>();
if (StringUtils.isNotBlank(content)) {
    content = HtmlUtils.htmlUnescape(content);
    List<HashMap<String, String>> imgs = getImgStrContent(content);
    int count = 0;
    for (HashMap<String, String> img : imgs) {
        count++;
        //處理替換以“/>”結尾的img標簽
        content = content.replace(img.get("img"), "${imgReplace" + count + "}");
        //處理替換以“>”結尾的img標簽
        content = content.replace(img.get("img1"), "${imgReplace" + count + "}");
        Map<String, Object> header = new HashMap<String, Object>();
        String result = "";
        result = img.get("src");
        //如果沒有寬高屬性,默認設置為
        if(img.get("width") == null || img.get("height") == null) {
            header.put("width", 150);
            header.put("height", 150);
        }else {
            header.put("width", (int)(Double.parseDouble(img.get("width"))));
            header.put("height", (int) (Double.parseDouble(img.get("height"))));
        }
        if( StringUtils.isNotBlank(result) ){
            String type1 = result.substring(result.lastIndexOf(".") , result.length());
            header.put("type", type1);
            header.put("content",this.imageToInputStream(result));
        }
        param.put("${imgReplace" + count + "}", header);
    }
}        
//獲取html中的圖片元素信息
private  List<HashMap<String, String>> getImgStrContent(String htmlStr) {
    List<HashMap<String, String>> pics = new ArrayList<HashMap<String, String>>();
    Document doc = Jsoup.parse(htmlStr);
    if( doc != null ){
        Elements imgs = doc.select("img");
        if( imgs != null && imgs.size() > 0 ){
            for (Element img : imgs) {
                HashMap<String, String> map = new HashMap<String, String>();
                if(!"".equals(img.attr("width"))) {
                    map.put("width", img.attr("width"));
                }
                if(!"".equals(img.attr("height"))) {
                    map.put("height", img.attr("height"));
                }
                map.put("img", img.toString().substring(0, img.toString().length() - 1) + "/>");
                map.put("img1", img.toString());
                map.put("src", img.attr("src"));
                pics.add(map);
            }
        }
    }
    return pics;
}
// 讀取生成的文件
readStream = new FileInputStream(targetPath);
ByteArrayOutputStream docxOs = new ByteArrayOutputStream();
int b = 0;
byte[] buf = new byte[1024];
while ((b = readStream.read(buf)) != -1) {
    docxOs.write(buf, 0, b);
}
docxResponseStream = new ByteArrayInputStream(docxOs.toByteArray());
// 創建word 對象
XWPFDocument document = new XWPFDocument(docxResponseStream);
newOS = new ByteArrayOutputStream();
if (document != null && param != null) {
    // 生成帶圖片的word(如需工具類請給我發郵件)
    XWPFDocument customXWPFDocument = WordUtil.getWord(param, document);
    // 設置表格邊框樣式(另外一片文章會介紹)
    // List<XWPFTable> list = formatTableBorder(customXWPFDocument);
    // 處理合並單元格(另外一片文章會介紹)
    // mergeCell(content, list);
    // 寫入輸出流返回
    customXWPFDocument.write(newOS);
    document.close();
    customXWPFDocument.close();
    resultInpu = new ByteArrayInputStream(newOS.toByteArray());
}else{
    resultInpu = docxResponseStream;
}

以上內容即可完成Word中多圖片的動態展示。

后續會寫處理表格邊框、單元格合並及段落都相關內容。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM