echarts圖表轉(zhuǎn)圖片并導(dǎo)出為word文檔

最近對(duì)echarts的使用很多,并且做了很多有意思的,很無解的需求,本文主要講述如何實(shí)現(xiàn)將echarts輸出到word。

  • 實(shí)現(xiàn)方式:
前端:echarts轉(zhuǎn)base64,將base64傳遞給后端

后端:接受base64,配置xml文件,將xml傳遞給前端

前端:接受xml,通過瀏覽器下載,導(dǎo)出word文檔

首先,前端echarts轉(zhuǎn)base64

  • echarts的實(shí)現(xiàn)原理其實(shí)就是通過canvas繪制的,canvas提供了api,可將canvas轉(zhuǎn)換為base64。

前端需要設(shè)置echarts的背景色,否則導(dǎo)出的圖片為白色背景,在word文件中不易查看數(shù)據(jù)。

// 找到繪制echarts的canvas節(jié)點(diǎn)

let canvas = $('#mychart').find('canvas')[0]

// 調(diào)用toDataURL,將canvas轉(zhuǎn)換為base64

let myBase64 = canvas.toDataURL('png')

-----

調(diào)用接口,將base64傳遞給后臺(tái)。base64的有效長(zhǎng)度需要去除前22位,前端/后端都可單獨(dú)處理
-----

后端接收base64資源,配置xml

  • 在項(xiàng)目中添加freemarker的依賴,或者引入jar包
  • 使用word做一個(gè)需要的文件模版,并將其中需要改變的部分編程變量(圖片建議先貼上大小相等的其他圖片)
  • 制作完成之后,將其另存為xml格式。
  • 將轉(zhuǎn)存的 xml 文件使用文本編輯器例如 notepad++ 等打開,將其中紅色區(qū)域的刪除掉,那些是圖片的base64編碼后的信息,然后替換為一個(gè)圖片變量,傳入新的圖片的 base64 編碼即可導(dǎo)出你所要的圖片,一般來說導(dǎo)出的圖片都是由前臺(tái) echarts 等工具生成的
  • 導(dǎo)出列表的話還需要在 xml 中找到 <w:tr> ,在其前加入 <#list list as list> (注意第一個(gè)list 不能變,第二個(gè)list 為變量名,第三個(gè)list 為別名),和</w:tr> 后加入 </#list> ,此外需將 name 改成 list.name,gender 改成 list.gender 。
  • 復(fù)制 xml 粘貼至項(xiàng)目文件中,并將后綴名更改為 .ftl
  • 編寫導(dǎo)出 Word 工具類
//加載模板(路徑)數(shù)據(jù),也可使用setServletContextForTemplateLoading()方法放入到web文件夾下
        config.setClassForTemplateLoading(this.getClass(), "/templates");
        //設(shè)置異常處理器 這樣的話 即使沒有屬性也不會(huì)出錯(cuò) 如:${list.name}...不會(huì)報(bào)錯(cuò)
        config.setTemplateExceptionHandler(TemplateExceptionHandler.IGNORE_HANDLER);
        try {
            if(templateName.endsWith(".ftl")) {
                templateName = templateName.substring(0, 
                templateName.indexOf(".ftl"));
            }
            Template template = config.getTemplate(templateName + ".ftl");
            response.setContentType("application/msword");
            response.setHeader("Content-disposition", "attachment;filename="+ URLEncoder.encode(fileName, StandardCharsets.UTF_8));
            OutputStream outputStream = response.getOutputStream();
            Writer out = new BufferedWriter(new OutputStreamWriter(outputStream));

            //將模板中的預(yù)先的代碼替換為數(shù)據(jù)
            template.process(dataMap, out);
            log.info("由模板文件:" + templateName + ".ftl" + " 生成Word文件 " + fileName + " 成功??!");
            out.flush();
        } catch (TemplateNotFoundException e) {
            log.info("模板文件未找到");
            e.printStackTrace();
        } catch (MalformedTemplateNameException e) {
            log.info("模板類型不正確");
            e.printStackTrace();
        } catch (TemplateException e) {
            log.info("填充模板時(shí)異常");
            e.printStackTrace();
        } catch (IOException e) {
            log.info("IO異常");
            e.printStackTrace();
        }
    }
  • 編寫簡(jiǎn)單的Controller方法
/**
     * @param image 注意該image參數(shù)為前臺(tái)傳過來圖片
     */
    @PostMapping("/exportWord")
    public void exportWord(HttpServletResponse response, @RequestParam("image") MultipartFile image){
        ExportWordUtil ewUtil = new ExportWordUtil();
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("title", "導(dǎo)出word文檔");
        Base64.Encoder base64 = Base64.getEncoder();
        try {
            dataMap.put("image", base64.encodeToString(image.getBytes()));
        } catch (Exception e){
            
        }

        List<User> userList = new ArrayList<>();
        userList.add(new User("張三","男"));
        userList.add(new User("李四","男"));
      userList.add(new User("王五","女"));
        dataMap.put("list", userList);
        ewUtil.exportWord(dataMap, "test.ftl", response, "導(dǎo)出word文檔");
    }
  • 啟動(dòng)項(xiàng)目,傳入某個(gè)圖片進(jìn)行測(cè)試,這里選用的是前端傳圖片的 base64 編碼的字符串。
  • 讀取.ftl文件,返回給前端。

前端接收返回的xml,輸出word文檔

$.get('../url', function (res){
    let xml = res.data // 后端返回的xml。
    let blob = new Blob([xml], {
                type: `application/msword` //word文檔為msword,pdf文檔為pdf,msexcel 為excel
            });
            let objectUrl = URL.createObjectURL(blob);
            let link = document.createElement("a");
            let fname = `echarts.doc`; //下載文件的名字+后綴名
            link.href = objectUrl;
            link.setAttribute("download", fname);
            link.click();
})

本文只是敘述了一種比較簡(jiǎn)易的方式,其實(shí)關(guān)于echarts轉(zhuǎn)圖片或者base64,有echarts自帶的api,以及后端配置xml時(shí)也有其他方式。后續(xù)會(huì)補(bǔ)充一些更加簡(jiǎn)易,正規(guī)的方式。如有錯(cuò)誤,還望指正,如有不懂,可評(píng)論留言,小編一定盡力解答。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容