-
Notifications
You must be signed in to change notification settings - Fork 905
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
38 changed files
with
1,014 additions
and
138 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import { withInstall } from '@/utils'; | ||
import impExcel from './src/ImportExcel.vue'; | ||
export { useExportExcelModal } from './src/ExportExcelModal'; | ||
|
||
export const ImpExcel = withInstall(impExcel); | ||
// export const ExpExcelModal = withInstall(expExcelModal); | ||
export * from './src/typing'; | ||
export { jsonToSheetXlsx, aoaToSheetXlsx } from './src/Export2Excel'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
import xlsx from 'xlsx'; | ||
import type { WorkBook } from 'xlsx'; | ||
import type { JsonToSheet, AoAToSheet } from './typing'; | ||
|
||
const { utils, writeFile } = xlsx; | ||
|
||
const DEF_FILE_NAME = 'excel-list.xlsx'; | ||
|
||
export function jsonToSheetXlsx<T = any>({ | ||
data, | ||
header, | ||
filename = DEF_FILE_NAME, | ||
json2sheetOpts = {}, | ||
write2excelOpts = { bookType: 'xlsx' }, | ||
}: JsonToSheet<T>) { | ||
let arrData = [...data]; | ||
if (header) { | ||
arrData.unshift(header); | ||
const filterKeys = Object.keys(header); | ||
arrData = arrData.map((item) => filterKeys.reduce<any>((p, k) => ((p[k] = item[k]), p), {})); | ||
json2sheetOpts.skipHeader = true; | ||
} | ||
|
||
const worksheet = utils.json_to_sheet(arrData, json2sheetOpts); | ||
|
||
/* add worksheet to workbook */ | ||
const workbook: WorkBook = { | ||
SheetNames: [filename], | ||
Sheets: { | ||
[filename]: worksheet, | ||
}, | ||
}; | ||
/* output format determined by filename */ | ||
writeFile(workbook, filename, write2excelOpts); | ||
/* at this point, out.xlsb will have been downloaded */ | ||
} | ||
|
||
export function aoaToSheetXlsx<T = any>({ | ||
data, | ||
header, | ||
filename = DEF_FILE_NAME, | ||
write2excelOpts = { bookType: 'xlsx' }, | ||
}: AoAToSheet<T>) { | ||
const arrData = [...data]; | ||
if (header) { | ||
arrData.unshift(header); | ||
} | ||
|
||
const worksheet = utils.aoa_to_sheet(arrData); | ||
|
||
/* add worksheet to workbook */ | ||
const workbook: WorkBook = { | ||
SheetNames: [filename], | ||
Sheets: { | ||
[filename]: worksheet, | ||
}, | ||
}; | ||
/* output format determined by filename */ | ||
writeFile(workbook, filename, write2excelOpts); | ||
/* at this point, out.xlsb will have been downloaded */ | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
import type { ExportModalResult } from './typing'; | ||
import type { FormItemSchema } from '@/components/core/schema-form/types/form'; | ||
|
||
import { useFormModal } from '@/hooks/useModal/useFormModal'; | ||
|
||
import { useI18n } from 'vue-i18n'; | ||
|
||
export type OpenModalOptions = { | ||
onOk: (val: ExportModalResult) => any; | ||
}; | ||
|
||
const getSchemas = (t): FormItemSchema<ExportModalResult>[] => [ | ||
{ | ||
field: 'filename', | ||
component: 'Input', | ||
label: t('component.excel.fileName'), | ||
rules: [{ required: true }], | ||
}, | ||
{ | ||
field: 'bookType', | ||
component: 'Select', | ||
label: t('component.excel.fileType'), | ||
defaultValue: 'xlsx', | ||
rules: [{ required: true }], | ||
componentProps: { | ||
options: [ | ||
{ | ||
label: 'xlsx', | ||
value: 'xlsx', | ||
key: 'xlsx', | ||
}, | ||
{ | ||
label: 'html', | ||
value: 'html', | ||
key: 'html', | ||
}, | ||
{ | ||
label: 'csv', | ||
value: 'csv', | ||
key: 'csv', | ||
}, | ||
{ | ||
label: 'txt', | ||
value: 'txt', | ||
key: 'txt', | ||
}, | ||
], | ||
}, | ||
}, | ||
]; | ||
|
||
export const useExportExcelModal = () => { | ||
const { t } = useI18n(); | ||
const [showModal] = useFormModal(); | ||
|
||
const openModal = ({ onOk }: OpenModalOptions) => { | ||
showModal<ExportModalResult>({ | ||
modalProps: { | ||
title: t('component.excel.exportModalTitle'), | ||
onFinish: async (values) => { | ||
const { filename, bookType } = values; | ||
|
||
onOk({ | ||
filename: `${filename.split('.').shift()}.${bookType}`, | ||
bookType, | ||
}); | ||
}, | ||
}, | ||
formSchema: { | ||
labelWidth: 100, | ||
layout: 'vertical', | ||
schemas: getSchemas(t), | ||
}, | ||
}); | ||
}; | ||
|
||
return { | ||
openModal, | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
<template> | ||
<div> | ||
<input | ||
ref="inputRef" | ||
type="file" | ||
v-show="false" | ||
accept=".xlsx, .xls" | ||
@change="handleInputClick" | ||
/> | ||
<div @click="handleUpload"> | ||
<slot></slot> | ||
</div> | ||
</div> | ||
</template> | ||
<script lang="ts"> | ||
import { defineComponent, ref, unref } from 'vue'; | ||
import XLSX from 'xlsx'; | ||
import { dateUtil } from '@/utils/dateUtil'; | ||
import type { ExcelData } from './typing'; | ||
export default defineComponent({ | ||
name: 'ImportExcel', | ||
props: { | ||
// 日期时间格式。如果不提供或者提供空值,将返回原始Date对象 | ||
dateFormat: { | ||
type: String, | ||
}, | ||
// 时区调整。实验性功能,仅为了解决读取日期时间值有偏差的问题。目前仅提供了+08:00时区的偏差修正值 | ||
// https://github.com/SheetJS/sheetjs/issues/1470#issuecomment-501108554 | ||
timeZone: { | ||
type: Number, | ||
default: 8, | ||
}, | ||
}, | ||
emits: ['success', 'error'], | ||
setup(props, { emit }) { | ||
const inputRef = ref<HTMLInputElement | null>(null); | ||
const loadingRef = ref<Boolean>(false); | ||
/** | ||
* @description: 第一行作为头部 | ||
*/ | ||
function getHeaderRow(sheet: XLSX.WorkSheet) { | ||
if (!sheet || !sheet['!ref']) return []; | ||
const headers: string[] = []; | ||
// A3:B7=>{s:{c:0, r:2}, e:{c:1, r:6}} | ||
const range = XLSX.utils.decode_range(sheet['!ref']); | ||
const R = range.s.r; | ||
/* start in the first row */ | ||
for (let C = range.s.c; C <= range.e.c; ++C) { | ||
/* walk every column in the range */ | ||
const cell = sheet[XLSX.utils.encode_cell({ c: C, r: R })]; | ||
/* find the cell in the first row */ | ||
let hdr = 'UNKNOWN ' + C; // <-- replace with your desired default | ||
if (cell && cell.t) hdr = XLSX.utils.format_cell(cell); | ||
headers.push(hdr); | ||
} | ||
return headers; | ||
} | ||
/** | ||
* @description: 获得excel数据 | ||
*/ | ||
function getExcelData(workbook: XLSX.WorkBook) { | ||
const excelData: ExcelData[] = []; | ||
const { dateFormat, timeZone } = props; | ||
for (const sheetName of workbook.SheetNames) { | ||
const worksheet = workbook.Sheets[sheetName]; | ||
const header: string[] = getHeaderRow(worksheet); | ||
let results = XLSX.utils.sheet_to_json(worksheet, { | ||
raw: true, | ||
dateNF: dateFormat, //Not worked | ||
}) as object[]; | ||
results = results.map((row: object) => { | ||
for (let field in row) { | ||
if (row[field] instanceof Date) { | ||
if (timeZone === 8) { | ||
row[field].setSeconds(row[field].getSeconds() + 43); | ||
} | ||
if (dateFormat) { | ||
row[field] = dateUtil(row[field]).format(dateFormat); | ||
} | ||
} | ||
} | ||
return row; | ||
}); | ||
excelData.push({ | ||
header, | ||
results, | ||
meta: { | ||
sheetName, | ||
}, | ||
}); | ||
} | ||
return excelData; | ||
} | ||
/** | ||
* @description: 读取excel数据 | ||
*/ | ||
function readerData(rawFile: File) { | ||
loadingRef.value = true; | ||
return new Promise((resolve, reject) => { | ||
const reader = new FileReader(); | ||
reader.onload = async (e) => { | ||
try { | ||
const data = e.target && e.target.result; | ||
const workbook = XLSX.read(data, { type: 'array', cellDates: true }); | ||
// console.log(workbook); | ||
/* DO SOMETHING WITH workbook HERE */ | ||
const excelData = getExcelData(workbook); | ||
emit('success', excelData); | ||
resolve(''); | ||
} catch (error) { | ||
reject(error); | ||
emit('error'); | ||
} finally { | ||
loadingRef.value = false; | ||
} | ||
}; | ||
reader.readAsArrayBuffer(rawFile); | ||
}); | ||
} | ||
async function upload(rawFile: File) { | ||
const inputRefDom = unref(inputRef); | ||
if (inputRefDom) { | ||
// fix can't select the same excel | ||
inputRefDom.value = ''; | ||
} | ||
await readerData(rawFile); | ||
} | ||
/** | ||
* @description: 触发选择文件管理器 | ||
*/ | ||
function handleInputClick(e: Event) { | ||
const files = e && (e.target as HTMLInputElement).files; | ||
const rawFile = files && files[0]; // only setting files[0] | ||
if (!rawFile) return; | ||
upload(rawFile); | ||
} | ||
/** | ||
* @description: 点击上传按钮 | ||
*/ | ||
function handleUpload() { | ||
const inputRefDom = unref(inputRef); | ||
inputRefDom && inputRefDom.click(); | ||
} | ||
return { handleUpload, handleInputClick, inputRef }; | ||
}, | ||
}); | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import type { JSON2SheetOpts, WritingOptions, BookType } from 'xlsx'; | ||
|
||
export interface ExcelData<T = any> { | ||
header: string[]; | ||
results: T[]; | ||
meta: { sheetName: string }; | ||
} | ||
|
||
export interface JsonToSheet<T = any> { | ||
data: T[]; | ||
header?: T; | ||
filename?: string; | ||
json2sheetOpts?: JSON2SheetOpts; | ||
write2excelOpts?: WritingOptions; | ||
} | ||
|
||
export interface AoAToSheet<T = any> { | ||
data: T[][]; | ||
header?: T[]; | ||
filename?: string; | ||
write2excelOpts?: WritingOptions; | ||
} | ||
|
||
export interface ExportModalResult { | ||
filename: string; | ||
bookType: BookType; | ||
} |
Oops, something went wrong.