• Vue 下载文件及 前端导出Excel 文件


    前端文件下载的几种方式

    // 1. 直接下载 (针对一些浏览器无法识别的文件格式,直接在地址栏上输入URL即可触发浏览器的下载功能)  
    window.location.href = URL;
    window.open(URL);
    
    // 2. 直接下载 使用A标签download属性  
    <a href="file.xlsx" download="文件名">文件下载</a>
    
    // 3. 通过触发JS直接下载
    function dowloadFile(fileName, link) {
    	let DownloadLink= document.createElement('a')
    	DownloadLink.style = 'display: none;'
    	DownloadLink.download = fileName
    	DownloadLink.href = link
    	document.body.appendChild(DownloadLink)
    	DownloadLink.click();
    	document.body.removeChild(DownloadLink)
    }
    
    // 通过 ajax 请求, 获取流数据的方式导出
    // 获取数据时,必须加上(responseType: "blob"), 表示后台穿过来的数据用 'blob' 对象接收  
    axios.post("ajaxUrl", { responseType: "blob" })
    // 下载流文件公共方法
    downloadBlobFile(response, fileName = '') {
    	const fileInfo = response.headers['content-disposition'].split(';')[1]
          let _fileName = fileName || decodeURIComponent(fileInfo && fileInfo.split('=')['1'])
          let blob = new Blob([response.data])
          let href = window.URL.createObjectURL(blob) //创建下载的链接
          if (window.navigator.msSaveBlob) {
            try {
              window.navigator.msSaveBlob(blob, _fileName)
            } catch (e) {
              console.error(e)
            }
          } else {
            // 谷歌浏览器 创建a标签 添加download属性下载
            let downloadElement = document.createElement('a')
            downloadElement.href = href
            downloadElement.target = '_blank'
            downloadElement.download = _fileName //下载后文件名
            document.body.appendChild(downloadElement)
            downloadElement.click() //点击下载
            document.body.removeChild(downloadElement) //下载完成移除元素
            window.URL.revokeObjectURL(href) //释放掉blob对象
          }
    }
    

    SheetJS 生成/解析 Excel 介绍

    SheetJs Github
    使用SheetJSxlsx.js实现生成excel表格
    纯JS即可读取/生成excel,功能强大,支持多种格式,兼容性高

    xlsx.js提供了一个中间层用于操作数据,将不同类型的文件抽象成同一个js对象,从而规避了操作不同种类数据之间的复杂性。

    基本概念

    • 工作簿 workbook 对象:指的是整份 Excel 文档。
    • 工作表 worksheet 对象:指的是 Excel 文档中的表。可以包含很多张表,每张表对应一个 worksheet 对象
    • 单元格 cell 对象:指的就是 worksheet 中的单元格,一个单元格就是一个 cell 对象
    {
    	"SheetNames": ["sheet1"],
    	"Sheets": {
    		"Sheet1": {
    			!ref: “A1:J3”, // 单元格范围
                !rows: [], // 表格行属性
                !cols: [
                    {wpx: 90}
                ], // 单元格属性
    			!merges: [], // 单元格合并规则
    			A1/B1/C1...: {}, // 对应excel中的每一个具体的单元格
    		}
    	}
    }
    

    单元格对象
    sheet中的: A1/B1/C1...: 单元格描述信息

    属性 描述
    t 表示内容类型 { s: ‘string’, n: 'number', b: 'boolean', d: 'date' }
    v 原始值
    f 公式,如: B2 + B3
    h HTML内容
    w 格式化后的内容
    r 富文本内容

    !merges合并单元格

    // 数组的每一项,代表其中一个单元格的合并要求
    ws['!merges'] = [
    	[s: {r: 0, c: 0}, e: {r: 1, c: 0}],
    	[s: {r: 0, c: 1}, e: {r: 1, c: 1}]
    ] 
    // s: 代表合并的起始位置
    // e: 代表合并的结束位置  
    // r: 代表行数
    // c: 代表列数
    // 数组的第一个对象,表达的含义为: 以0行0列(对应单元格A1)作为起始,以1行0列(对应单元格A2)作为结束,合并这些单元格
    

    单元格地址
    xlsx使用有两种方式来描述操作中的单元格区域:

    • 一种是单元格地址对象 (Cell address object)
    // 地址对象描述的是一个起始坐标(从0开始)到结束坐标之间的范围
     const start = { c: 0, r: 0 };
     const end = { c: 1, r: 1 };
    
    • 另一种是地址范围 (Cell range)
    // 地址范围就是Excel中的引用样式
    const range = 'A1:B2'
    

    worksheet Object 工作表对象

    {
    	"sheet1": {
    		"A1": {}, // 单元格对象
    		"!ref": "A1:B5", // 表示工作表范围
    		“!cols”: [
    			[ wpx: 200 ], // 设置第1列列狂为200箱数
    			[ wch: 50 ], // 设置第2列列宽为50字符
    		],
    		"!merges": [
    			{
    				s: { c: 1, r: 1 }, // B2
    				s: { c: 3, r: 3 }, // D4
    			}
    		], // 合并单元格范围数据
    		"!freeze": {
    			"xSplit": "1", // 冻结列
    			“ySplit": "1", // 冻结行
    		}
    	}
    }
    

    xlsx.js 引入

    // 以 script 标签的形式
    <script lang="javascript" src="dist/xlsx.full.min.js"></script>
    
    // 使用 npm 安装 xlsx 模块
    npm install xlsx --save
    // 引入
    import XLSX from 'xlsx'
    // 或
    const XLSX = require('xlsx')
    

    xlsx.js 的一些常用方法

    读取数据并解析:

    方法名 描述
    XLSX.readFile(filename[, opts]) 获取数据
    xlsx.readFileSync(filename[, opts]) 异步获取数据
    XLSX.read(data[, opts]) 解析数据

    数据导出:

    方法名 描述
    XLSX.write(workbook[, opts]) 用来写入工作簿 workbook
    XLSX.writeFile(workbook, filename[, opts]) 把 workbook 写入到特定的文件 filename 中

    XLSX.utils对象中有一些方法可以对单元格和单元格范围进行转化

    // 编码行号
    XLSX.utils.encode_row(2); // "3"
    // 解码行号
    XLSX.utils.decode_row("2"); // 1
    
    // 编码列
    XLSX.utils.encode_col(2); // "C"
    // 解码列 
    XLSX.utils.decode_col("A"); // 0
    
    // 编码单元格
    XLSX.utils.encode_cell({ c: 1, r: 1 }); // "B2"
    // 解码单元格
    XLSX.utils.decode_cell("B1"); // { c: 1, r: 0 }
    
    // 编码单元格范围
    XLSX.utils.encode_range({
    	s: { c:1, r: 0 },
    	e: { c:2, r: 8 }
    }); // "B1:C9"
    // 解码单元格范围
    XLSX.utils.decode_range("B1:C9");
    // {s: {r: 1, r: 0}, e: {c: 2, r: 8}}
    

    操作工作簿

    // 1. 创建一个工作簿
    const workBook = XLSX.utils.book_new();
    
    // 2. 创建工作表对象的几种方式 
    // 使用二维数组创建一个工作表对象
    const workSheet = XLSX.utils.aoa_to_sheet(data); 
    // 使用对象数据创建一个工作表对象
    const workSheet = XLSX.utils.json_to_sheet(data);
    // 根据已渲染好的表格,转成工作表数据,会自动识别对应的单元格合并数据
    const workSheet = XLSX.utils.table_to_sheet("表格ID")
    
    // 向工作簿追加一个工作表
    XLSX.utils.book_append_sheet(workBook, workSheet, "工作表名称")
    

    数据填充 - 创建工作表
    工作表是实际存放数据的地方,大部分情况下我们的操作都是在对工作表对象的小左。
    aoa_to_sheet 根据二维数组创建工作表

    var data1 = [
    	['主要信息', null, null, '其它信息'],  
    	['姓名', '性别', '年龄', '注册时间'],
    	['张三', '男', 18, new Date()],
    	['李四', '女', 22, new Date()]
    ];
    // 1. 新建一个工作簿
    let workbook = XLSX.utils.book_new();
    // 2. 生成一个工作表,
    // 2.1 aoa_to_sheet 把数组转换为工作表
    let sheet1 = XLSX.utils.aoa_to_sheet(data1);
    // 3. 设置单元格合并
    sheet1['!merges'] = [
    	// 设置A1-C1的单元格合并
        { s: {r: 0, c: 0}, e: {r: 0, c: 2 }}
    ]; 
    // 4.在工作簿中添加工作表
    XLSX.utils.book_append_sheet(workbook, sheet1, "工作表名称");  
    // 5.输出工作表,由文件名决定的输出格式
    XLSX.writeFile(workbook, "默认的导出文件名称.xlsx");
    

    **json_to_sheet 根据二维数组创建工作表: **

    const data = [
    	{ L: 8, O: 5, V: 2, E: 7, ID: 'i_8527' },
    	{ L: 1, O: 5, V: 9, E: 2, IDL 'i_15926'}
    ]
    // 基础版: 会自动提起键名作为表头
    let worksheet = XLSX.utils.json_to_sheet(data)
    

    展示结果:

    L O V E ID
    8 5 2 7 i_8527
    1 5 9 2 I_15926

    排序并自定义表头

    // 自定义表格的名称
    const headerDisplay = {
    	L: "L栏", O: "O栏", V: "V栏", E: "E栏", ID: "ID栏" 
    }
    const newData = [headerDisplay, ...data]
    let worksheet = XLSX.utils.json_to_sheet(data, {
        header: ['ID'] // 表格列排序, 示吧ID移动到最前面
        skipHeader: true // 忽略表格原有的表头
    })
    
    ID L O V E
    i_8527 8 5 2 7
    I_15926 1 5 9 2

    数据填充 - 修改工作表数据

    // 创建工作表
    const worksheet = XLSX.utils.json_to_sheet([
    	{ '列1': 1, '列2': 2, '列3': 3 },
    	{ '列1': 4, '列2': 5, '列3': 6 }
    ], {
    	header: ['列3', '列2', '列1'], // 排序
    	skipHeader: true  
    })
    // 修改成新数据 sheet_to_aoa 二维数组方式
    XLSX.utils.sheet_to_aoa(worksheet, [
    	['姓名', '年龄', '地址'],
    	["张三", 26, "北京"],
        ["小右", 18, "成都"]
    ],{
    	origin: 'A1' // 从A1开始增加内容
    })
    
    // -------------------------------
    
    // 修改成新数据 sheet_to_json 方式
    XLSX.utils.sheet_to_json(worksheet, [
    	{ "年龄": 26, "地址": "深圳", "姓名": "张三" },
    	{ "年龄": 18, "地址": "成都", "姓名": "小右" },
    ], {
    	origin: "A1",
    	header: ["姓名", "年龄", "地址"],
    	skipHeader: true
    })
    
    姓名 年龄 地址
    张三 26 深圳
    小右 18 成都

    导出Excel文件

    根据已经渲染好的表格进行导出Excel :会自动识别单元格合并

    /** 
     * arrTableId 传参 多条表示有多个表
     * [ 
     *  {id: 'excel1', sheetName: 'sheet1'}, 
     *  {id: 'excel2', sheetName: 'sheet2'}
     * ]
     */
    export function exportTableToExcel(arrTableId, excelFileName) {
    	const workbook = XLSX.utils.book_new();
    	// 循环得到每一张表的 sheet,并添加到 workbook 中
    	arrTableId.forEach((item) => {
    		const tableEle = document.getElementById(item.id);
    		const ws = XLSX.utils.table_to_sheet(tableEle);
    		XLSX.utils.book_append_sheet(workbook, ws, item.sheetName)
    	})
    	// 导出Excel
    	XLSX.writeFile(workbook, excelFileName)
    }
    
    // 使用 
    const exportParams = [{ id: "xGrid1", sheetName: "工作表名称" }]
    this.exportTableToExcel(exportParams, "导出后保存的文件名称.xlsx");
    

    根据 aoa_to_sheetjson_to_sheet创建的工作表进行导出,复杂表头需要提供合并的 !merges数据

    // 复杂表头示例 
    const workbook = XLSX.utils.book_new();
    const data = [
    	// 特别注意: 合并的地方后面预览 null
    	[ "主要信息", null, null, "其他信息" ],
    	[ "姓名", "性别", "年龄", "注册时间" ],
    	[ "张三", "男", 26, new Date() ],
    	[ "李四", "女", 18, new Date() ]
    ]
    const sheet = XLSX.utils.aoa_to_sheet(data);
    sheet['!merges'] = [
    	// 设置A1-C1的单元格合并
    	{ s: { r: 0, c: 0 }, e: { r: 0, c: 2 }}
    ]
    XLSX.utils.book_append_sheet(workbook, ws, sheet)
    // 导出Excel
    XLSX.writeFile(workbook, excelFileName)
    

    合并单元格方案

    需要自己提供单元格合并范围的数据

    const mergesArr = ['A1:A3', 'B1:F1', 'B2:B3', 'C2:F2']
    const range = ["A1:A3", "B1:F1", "B2:B3", "C2:F2"].map((item) => {
    	return XLSX.utils.decode_range(item);
    });
    sheet1["!merges"] = range;
    
  • 相关阅读:
    Python NameError: name 'include' is not defined [closed]
    Python3 venv 创建虚拟环境
    python编程:从入门到实践读书笔记(一)
    kafka(2.2.1)(kerberos+LDAP+Sentry)访问使用
    实现Base64解码和命令分发器
    装饰器器应用及用途
    __slots__和运算符重载中的反向方法
    python插件化开发
    python分发包管理
    SocketServer模块
  • 原文地址:https://www.cnblogs.com/yuxi2018/p/15508863.html
Copyright © 2020-2023  润新知