• 前端导出word文件的多种方式、前端导出excel文件


    纯前借助word模板端导出word文件 (推荐)

    先看效果:
    这是页面中的table
    在这里插入图片描述
    这是导出后的效果:
    在这里插入图片描述

    使用模板导出

    需要的依赖:
    npm 自行安装,需要看官网的具体参数自行去github上面找对应的参数

     	"docxtemplater": "^3.46.0",
        "pizzip": "^3.1.6",
        "jszip-utils": "^0.1.0",
        "file-saver": "^2.0.5",
    
    • 1
    • 2
    • 3
    • 4

    具体代码:(先看word模板,在看代码,word中的变量和代码中 doc.setData() 是一一对应的)
    在这里插入图片描述

    <template>
      <div class="button-box">
        <a-space>
          <a-button type="danger" @click="downWord2">模板导出word文件</a-button>
        </a-space>
      </div>
    </template>
    
    <script lang="ts">
    import { defineComponent, onMounted, reactive, PropType, ref } from 'vue';
    import { message } from 'ant-design-vue';
    import moment from 'moment';
    import { downloadPDF } from '../../../../utils/utils';
    import { useTable } from './hooks/useTable';
    import xlsx from 'node-xlsx';
    
    import docxtemplater from 'docxtemplater';
    import PizZip from 'pizzip';
    import JSZipUtils from 'jszip-utils';
    import { saveAs } from 'file-saver';
    
    export default defineComponent({
      props: {
        /**
         * 基础数据
         */
        baseData: {
          type: Object as PropType<{
            taskId: string;
            barcodeId: string;
          }>,
          default: {},
        },
        /**
         * 样本名称
         */
        barcodeName: {
          type: String,
        },
      },
    
      setup(props) {
        let width = 100;
        const { barcodeName } = props;
        const { taskId, barcodeId } = props.baseData;
        const { tableConfig, tableConfigLeft, getDta } = useTable();
    
    
    
        onMounted(() => {
          barcodeName ? getDta(taskId, barcodeName) : '';
        });
        
        const tableValue = reactive({
          unit: '中国',
          date: undefined,
          sampleType: '你猜',
          people: '黄种人',
          name: '夜空',
          sex: '男',
          age: '25',
          work: '开发',
          id: '',
          jiance: '商品化试剂盒',
          date2: undefined,
        });
    
       
        const downWord2 = () => {
          let docxname = '导出word.docx';
          JSZipUtils.getBinaryContent('/test.docx', function (error: any, content: any) {
            // test.docx是模板(这里我放到public公共文件夹下面了)。我们在导出的时候,会根据此模板来导出对应的数据
            // 抛出异常
            if (error) {
              throw error;
            }
    
            // 创建一个PizZip实例,内容为模板的内容
            let zip = new PizZip(content);
            // 创建并加载docx templater实例对象
            let doc = new docxtemplater().loadZip(zip);
            // 设置模板变量的值  主要变量替换在这里
            doc.setData({
              name: tableValue.name,
              unit: tableValue.unit,
              date: moment(tableValue.date).format('YYYY-MM-DD'),
              sampleType: tableValue.sampleType,
              sex: tableValue.sex,
              age: tableValue.age,
            });
    
            try {
              // 用模板变量的值替换所有模板变量
              doc.render();
            } catch (error: any) {
              // 抛出异常
              let e = {
                message: error.message,
                name: error.name,
                stack: error.stack,
                properties: error.properties,
              };
              console.log(
                JSON.stringify({
                  error: e,
                }),
              );
              throw error;
            }
    
            // 生成一个代表docxtemplater对象的zip文件(不是一个真实的文件,而是在内存中的表示)
            let out = doc.getZip().generate({
              type: 'blob',
              mimeType: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
            });
            // 将目标文件对象保存为目标类型的文件,并命名
            saveAs(out, docxname);
          });
        };
    
        return {
          downWord2,
          getDta,
          tableConfig,
          tableConfigLeft,
          tableValue,
          downloadPDF,
          value4: ref('less'),
        };
      },
    });
    </script>
    
    <style lang="less" scoped>
    
    </style>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137

    前端通过模板字符串导出word文件

    包依赖:

     "file-saver": "^2.0.5",
    
    • 1

    代码

    import FileSaver from 'file-saver';
    import htmlDocx from "html-docx-js/dist/html-docx"
    import { G } from '@/global';
    const { rootUrl, rbacToken } = G;
    let cycle_info1 = [
      {
        name: '事件类型',
        key: 'eventTypeName',
      },
      {
        name: '地点定位',
        key: 'locationAddress',
      },
      {
        name: '上报时间',
        key: 'reportTime',
      },
      {
        name: '人员姓名',
        key: 'reportUserName',
      },
      {
        name: '联系方式',
        key: 'reportUserPhone',
      },
    ]
    
    const model = (reportInfoDetail: any, list: any, eventState: any) => {
      // console.log(reportInfoDetail, list, eventState);
    
      return (
        `
        
          
    
    
      
    
    
    
      
    上报信息
    上报信息
    事件类型: ${reportInfoDetail['eventTypeName']}
    地点定位: ${reportInfoDetail['locationAddress']}
    上报时间: ${reportInfoDetail['reportTime']}
    人员姓名: ${reportInfoDetail['reportUserName']}
    联系方式: ${reportInfoDetail['reportUserPhone']}
    图片附件
    ${reportInfoDetail['picIds']?.map((res1: any, idx1: any) => { return ` ${rootUrl}/fyVolunteer/file/download/${res1}?rbacToken=${rbacToken}" style='margin-right:5px' /> ${((idx1 + 1) % 2 == 0) ? `
    `
    : ''}
    `
    }) }
    事件描述
    ${reportInfoDetail['description']}
    ${reportInfoDetail.assignInfo.length != 0 ? ` <div class="fromBox"> <div class="formTitle_first">指派信息</div> <div class="formTitle_second display_flex">指派信息</div> <div class="formContent_box"> <div class="formContent_box_title">指派单位: ${reportInfoDetail.assignInfo.map((res: any, idx: any) => { return ` ${res.departmentName} ` }) }
    指派时间: ${!!reportInfoDetail?.assignInfo[0]?.assignTime ? reportInfoDetail?.assignInfo[0]?.assignTime : ""}
    `: '' } <div class="fromBox"> <div class="formTitle_first">处置信息</div> ${reportInfoDetail.handleInfo.length != 0 ? reportInfoDetail.handleInfo.map((itm: any, idx: any) => { return `
    单位${idx + 1}${itm['claimDepartmentName']}
    签收信息
    签收单位:${itm['claimDepartmentName']}
    签收时间:${itm['claimTime']}
    图片附件
    ${itm['handleTime'] != null ? itm['handlePicIds']?.map((res1: any, idx1: any) => { return ` ${rootUrl}/fyVolunteer/file/download/${res1}?rbacToken=${rbacToken}" style="margin-right:5px" /> ${(idx1 + 1) % 2 == 0 ? `
    `
    : ''}
    `
    }) : `` }
    处置描述
    ${itm.handleTime != null ? itm['handleDescription'] : `未上传处置`}
    上报信息
    上报单位:${itm['claimDepartmentName']}
    上报时间:${itm['handleTime'] != null ? itm['handleTime'] : ''}

    `
    }) : '无数据' } </div > <div class="fromBox"> <div class="formTitle_first">其他信息</div> <div class="formContent_box display_flex"> <span class="formContent_box_title">信息状态:</span> <span> ${list[eventState - 1].desc} ${reportInfoDetail?.finishTime != null ? reportInfoDetail?.finishTime : ''} </span> </div> <div class="formContent_box display_flex"> <span class="formContent_box_title">采纳状态:</span> <span>${reportInfoDetail.acceptInfo == null ? "未采纳" : `已采纳(${reportInfoDetail.acceptInfo.integral})`}</span> </div> </div> </div > </body > </html > ` ) } const loadFile = (info: any) => { let html = model(info.reportInfoDetail, info.list, info.eventState) let blob = new Blob([html], { type: "application/msword;charset=utf-8" }); // let blob = htmlDocx.asBlob(html, { orientation: "landscape" }); FileSaver.saveAs(blob, "信息管理文件.doc"); } export { loadFile };
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225

    前端导出 excel文件,node-xlsx导出文件,行列合并

    导出效果:
    在这里插入图片描述

    需要的依赖: node-xlsx

        "node-xlsx": "^0.23.0",
    
    • 1

    代码:

        const downXlsx = () => {
          let data = [
            [1, 222, '', '', '', ''],
            ['', 2, 3, 4, 5, 6],
            ['', 2, 3, 4, 5, 6],
            ['', 2, 3, 4, 5, 6],
            ['', 2, 3, 4, 5, 6],
            [22, 2, 3, 4, 5, 6],
          ];
    
          // 行列合并规则  c:col 列   r:row 行
          const range0 = { s: { c: 0, r: 0 }, e: { c: 0, r: 4 } };
          const range1 = { s: { c: 1, r: 0 }, e: { c: 5, r: 0 } };
          const sheetOptions = {
            '!merges': [range0, range1],
            // cols 列宽大小
            '!cols': [{ wch: 5 }, { wch: 10 }, { wch: 15 }, { wch: 20 }, { wch: 30 }, { wch: 50 }],
          };
          //如果不需要格式,这里的sheetOptions可以省略不写
          let result = xlsx.build([{ name: 'sheet1', data }], { sheetOptions });
          const ab = Buffer.from(result, 'binary');
          const blob = new Blob([ab]);
          const blobUrl = URL.createObjectURL(blob);
          const a = document.createElement('a');
          a.href = blobUrl;
          a.download = '导出excel.xlsx';
          a.click();
          window.URL.revokeObjectURL(blobUrl);
        };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
  • 相关阅读:
    Java 之 CAS 原理及实现是怎样的?
    零拷贝原理与实现
    springboot基础(69):Controller相关注解
    2020华数杯全国大学生数学建模竞赛B题-基于混合模拟退火算法的三维零件的切割模型与计算(附MATLAB代码)
    MySQL查询常见错误及其解决方法
    python中用于web开发的库
    elementUI el-table+树形结构子节点选中后没有打勾?(element版本问题 已解决)
    【Redis学习1】Redis持久化机制详解
    优秀笔记软件盘点(五)—那些强大的卡片笔记写作法软件
    Python 编程规范和软件开发目录规范的重要性
  • 原文地址:https://blog.csdn.net/qq_43940789/article/details/136391534