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 表示內容類型
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;


免責聲明!

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



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