天天看點

vue使用jquery.wordexport導出word文檔(批量導出為zip)前言前提準備正文jquery.wordexport代碼

前言

網上查了很多jquery.wordexport的文章都是隻支援單獨導出word,不符合業務需求。是以修改了jquery.wordexport、利用jszip、file-saver批量導出word。

前提準備

包的版本分别為[email protected]、[email protected]。jquery版本随意,本文使用的為@3.2.1

npm i [email protected] -D
           
npm i [email protected] -D
           

正文

html部分

注意:導出word文檔識别不了css中的樣式,隻能将樣式寫為行内樣式或者添加在wordExport()方法的第二個參數中。jquery.wordexport無法使用flex布局,position等

<div class="wordForm-box">
      <div class="wordForm"
           v-for="(item,index) in exportWordList"
           :key="index"
           :id="'word'+index">
           <p align="center"
           style="font-size:32px;line-height: 40px;font-weight: 900;">{{ item.formTitle }}</p>
           <table style="margin-top:20px">
          <thead>
            <th>操作時間</th>
            <th>操作人員</th>
            <th>操作節點</th>
            <th>操作類型</th>
            <th>操作結果</th>
            <th>回報詳情</th>
          </thead>
          <tbody>
            <tr v-for="(record) in item.records"
                :key="record.id">

              <td>{{ record.create_time | dateFormat}}</td>
              <td>{{ record.operator.nickname}}</td>
              <td>{{ record.level_from | formatAuditNode}}</td>
              <td>{{ record.type | formatState}}</td>
              <td>{{ record | formatResult}}</td>
              <td>{{ record.remark}}</td>
            </tr>
          </tbody>
        </table>
      </div>
 </div>
           

script部分

jquery的引用應放在wordexport前

注意:批量壓縮時 同名檔案将隻會存在一個,請注意命名

<script>
	import JSZip from 'jszip';
	import FileSaver from 'file-saver';
	import $ from '../../../libs/jquery-3.2.1/jquery.min.js';
	import '../../../libs/jquery.wordexport';
	export default {
	data() {
        return {
        exportWordList: [],//需導出word表格清單
        }
        }
	methods: {
	async handleWordExport() {
		this.exportWordList = [];//初始化
	//...資料處理
	// 導出
	//本文資料處理有異步操作,nextTick處理保證頁面已更新
  		this.$nextTick(() => {
  					let wordFiles = [];
                    let wordList = []; // 由于批量壓縮時 同名檔案将隻會存在一個 這裡我們采用[[],[]]包裹同名檔案
                    this.exportWordList.forEach(async (wordItem, index) => {
                        let tmpIndex = wordList.findIndex((tmpWordItem) => {
                            return tmpWordItem[0].formTitle == wordItem.formTitle;
                        });
                        if (tmpIndex == -1) {
                            wordList.push([wordItem]);
                        } else {
                            wordList[tmpIndex].push(wordItem);
                            // wordList[tmpIndex][wordList[tmpIndex].length - 1].formTitle += '' + (wordList[tmpIndex].length - 1);
                            wordItem.formTitle += '(' + (wordList[tmpIndex].length - 1) + ')';
                        }
                        let rules =
                            'table{' +
                            '	border-collapse:collapse;' +
                            '	margin:0 auto;' +
                            '	text-align:center;' +
                            '	width: 100%;' +
                            '}' +
                            'table td,table th{' +
                            '   text-align:center;' +
                            '   border:1px solid #000000;' +
                            '	height:25pt;' +
                            '	width:15%;' +
                            '}' +
                            'table thead th{' +
                            ' 	width:15%' +
                            '}' +
                            'table tr{' +
                            '	background:#fff;' +
                            '}';
                            //可以通過修改wordExport()方法的第二個參數,添加樣式
                        let wordFile = await $('#word' + index).wordExport(wordItem.formTitle, rules);
                        wordFiles.push(wordFile);

                        if (wordFiles.length == this.exportWordList.length) {
                            this.zipWordExport(wordFiles);
                           
                        }
                    });
  }

	},
	//導出zip
	zipWordExport(promises) {
            const zip = new JSZip();
            const _this = this;
            promises.forEach(async (item, index) => {
            //word為blob資料
                const { word, fileName } = item;
                if (promises.length === 1) {
                    FileSaver.saveAs(word, `${fileName}.doc`);
                } else {
                
                    await zip.file(`${fileName}.doc`, word);
                }
                if (promises.length > 1 && promises.length - 1 == index) {
                    _this.$message.warning('正在壓縮請稍後');
                    zip.generateAsync({ type: 'blob' }).then((content) => {
                        FileSaver.saveAs(content, '表單記錄合集' + '.zip');
                    });
                }
            });
        },
	}
	}
</script>
           

jquery.wordexport代碼

注意:jquery.wordexport中導入的jquery檔案應與正文代碼為同一檔案

// 導入js檔案
import $ from './jquery-3.2.1/jquery.min.js';
let jQuery = $;
if (typeof jQuery !== 'undefined') {
    (function () {
        $.fn.wordExport = function (fileName, rules) {
            return new Promise((resolve, reject) => {
                setTimeout(() => {
                    fileName = typeof fileName !== 'undefined' ? fileName : 'jQuery-Word-Export';
                    var static_ = {
                        mhtml: {
                            top: 'Mime-Version: 1.0\nContent-Base: ' + location.href + '\nContent-Type: Multipart/related; boundary="NEXT.ITEM-BOUNDARY";type="text/html"\n\n--NEXT.ITEM-BOUNDARY\nContent-Type: text/html; charset="utf-8"\nContent-Location: ' + location.href + '\n\n<!DOCTYPE html>\n<html>\n_html_</html>',
                            head: '<head>\n<meta http-equiv="Content-Type" content="text/html; charset=utf-8">\n<style>\n_styles_\n</style>\n</head>\n',
                            body: '<body>_body_</body>'
                        }
                    };
                    var options = {
                        maxWidth: 624
                    };
                    // Clone selected element before manipulating it
                    var markup = $(this).clone();
                    // Remove hidden elements from the output
                    markup.each(function () {
                        var self = $(this);
                        if (self.is(':hidden')) {
                            self.remove();
                        }
                    });

                    // Embed all images using Data URLs
                    var images = Array();
                    var img = markup.find('img');
                    for (var i = 0; i < img.length; i++) {
                        // 如果導出的word檔案裡面包含線上的圖檔
                        // Calculate dimensions of output image
                        var width = Math.min(img[i].width, options.maxWidth);
                        var height = img[i].height * (width / img[i].width);
                        // Create canvas for converting image to data URL
                        // 這是添加的代碼--------------------------------------------
                        var img_id = '#' + img[i].id;
                        $('<canvas>').attr('id', 'test_word_img_' + i).width(width).height(height).insertAfter(img_id);


                        // 如果導出的word檔案裡面包含本地圖檔用這一段,如果都包含,要另外研究一下
                        // Calculate dimensions of output image
                        var w = Math.min(img[i].width, options.maxWidth);
                        var h = img[i].height * (w / img[i].width);
                        // Create canvas for converting image to data URL
                        var canvas = document.createElement('CANVAS');
                        canvas.width = w;
                        canvas.height = h;
                        // Draw image to canvas
                        var context = canvas.getContext('2d');
                        context.drawImage(img[i], 0, 0, w, h);
                        // Get data URL encoding of image
                        var uri = canvas.toDataURL('image/png');
                        $(img[i]).attr('src', img[i].src);
                        img[i].width = w;
                        img[i].height = h;
                        // Save encoded image to array
                        images[i] = {
                            type: uri.substring(uri.indexOf(':') + 1, uri.indexOf(';')),
                            encoding: uri.substring(uri.indexOf(';') + 1, uri.indexOf(',')),
                            location: $(img[i]).attr('src'),
                            data: uri.substring(uri.indexOf(',') + 1)
                        };

                    }

                    // Prepare bottom of mhtml file with image data
                    var mhtmlBottom = '\n';
                    for (var i = 0; i < images.length; i++) {
                        mhtmlBottom += '--NEXT.ITEM-BOUNDARY\n';
                        mhtmlBottom += 'Content-Location: ' + images[i].location + '\n';
                        mhtmlBottom += 'Content-Type: ' + images[i].type + '\n';
                        mhtmlBottom += 'Content-Transfer-Encoding: ' + images[i].encoding + '\n\n';
                        mhtmlBottom += images[i].data + '\n\n';
                    }
                    mhtmlBottom += '--NEXT.ITEM-BOUNDARY--';

                    // TODO: load css from included stylesheet
                    var styles = rules;

                    // Aggregate parts of the file together
                    var fileContent = static_.mhtml.top.replace('_html_', static_.mhtml.head.replace('_styles_', styles) + static_.mhtml.body.replace('_body_', markup.html())) + mhtmlBottom;

                    // Create a Blob with the file contents
                    var blob = new Blob([fileContent], {
                        type: 'application/msword;charset=utf-8'
                    });

                    resolve({ word: blob, fileName: fileName });
                }, 10);
            });

        };
    })(jQuery);
} else {
    if (typeof jQuery === 'undefined') {
        console.error('jQuery Word Export: missing dependency (jQuery)');
    }

}
           

繼續閱讀