"use strict"
* @和表格处理相关的各类方法
* readXlsxFile() 读取XLSX文件为工作簿对象
* sheetToAoa() 从工作簿对象中提取指定工作表的数据为AOA对象
* arrTrim() 剔除标题数组里可能存在的前后空格
* aoaTranspose() 数组转置
* aoaMapToWorkbook() AOA的键值对Map数据转为工作簿对象
* downloadXlsx() 下载工作簿xlsx文件
*/
* @note
* 直接从xlsx表格读取到的文件类型为工作簿:XLSX.WorkBook
* 从工作簿中,可以得到工作表:XLSX.WorkSheet
* 继续处理工作表可以得到AOA数组
*/
* @库导入
*/
import * as XLSX from "xlsx"
import { downloadFile } from "./app-utils.js"
* 读取XLSX文件为工作簿对象
* @async
* @param { File | Response } xlsxFile XLSX文件对象
* @returns { Promise<XLSX.WorkBook> } 工作簿对象
*/
export async function readXlsxFile(xlsxFile) {
const dataBuffer = await xlsxFile.arrayBuffer()
const workbook = XLSX.read(dataBuffer, { type: "file" })
return workbook
}
* 从工作簿对象中提取指定工作表的数据为AOA对象
* @template { Number | String } T
* @param { XLSX.WorkBook } workbook 工作簿对象
* @param { String } sheetName 表格名称
* @returns { T[][] } AOA数组
*/
export function sheetToAoa(workbook, sheetName) {
const workSheet = workbook.Sheets[sheetName]
if (workSheet === undefined) {
throw new Error(`工作簿中找不到名为 ${ sheetName } 的工作表`)
}
const sheetDataAoa = XLSX.utils.sheet_to_json(workSheet, {
header: 1,
blankrows: false
})
return sheetDataAoa
}
* 剔除标题数组里可能存在的前后空格
* @param { String[] } arr 待剔除空格的数组
* @returns { String[] } 剔除空格后的数组
*/
export function arrTrim(arr) {
const arrTrimed = arr.map((str) => {
if (typeof str === "string") {
return str.trim()
} else {
return str
}
})
return arrTrimed
}
* 数组转置
* @param { (number | string)[][] } aoa 待转置的AOA数组
* @param { number } [dataNumber] 需要获取的数据数(列),默认为AOA的最大列数
* @returns { (number | string)[][] } 转置后的AOA数组
*/
export function aoaTranspose(aoa, dataNumber) {
const rowNumber = aoa.length || 0
if (rowNumber === 0) {
throw new Error("表格没数据,请检查")
}
const colNumber =
dataNumber
?? Math.max(...aoa.map((arr) => {
return (arr.length || 0)
}))
const transposedAoa = []
for (let col = 0; col < colNumber; col++) {
transposedAoa[col] = []
for (let row = 0; row < rowNumber; row++) {
transposedAoa[col][row] = aoa[row][col]
}
}
return transposedAoa
}
* AOA的键值对Map数据转为工作簿对象
* @template { Number | String } T
* @param { Map<String, T[][]> } aoaMap AOA数组的Map对象
* @returns { XLSX.WorkBook } 工作簿
*/
export function aoaMapToWorkbook(aoaMap) {
const workbook = XLSX.utils.book_new()
aoaMap.forEach((sheetAoaData, sheetName) => {
const sheet = XLSX.utils.aoa_to_sheet(sheetAoaData)
XLSX.utils.book_append_sheet(workbook, sheet, sheetName)
})
return workbook
}
* 下载工作簿xlsx文件
* @param { XLSX.WorkBook } workbook 工作簿对象
* @param { String } xlsxName 文件名
*/
export function downloadXlsx(workbook, xlsxName) {
const xlsxArrayBuffer = XLSX.write(workbook, { type: "array" })
const fileType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
downloadFile(xlsxArrayBuffer, xlsxName, fileType)
}