1 Star 0 Fork 112

队长别开枪 / layui-excel

forked from Jeffrey-Wang / layui-excel 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
index.js 19.74 KB
一键复制 编辑 原始数据 按行查看 历史
Jeffrey-Wang 提交于 2021-03-25 12:05 . doc: 增加demo
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614
/**
* 阅读指南:
* 导出数据测试:搜索 「exportDataByUser」关键字,找到函数即可
* 导出接口数据:搜索「exportApiDemo」关键字,找到函数即可
* 导出复杂表头:搜索「exportExtendDemo」关键字,找到函数即可
* 批量设置样式:搜索「exportStyleDemo」关键字,找到函数即可
* 简单文件导入:搜索「uploadExcel」可找到导入的处理逻辑,拖拽文件/选择文件回调获取files对象请搜索「#LAY-excel-import-excel」
* upload模块:搜索「uploadInst」查看使用逻辑,导入相关逻辑同上
*/
layui.use(['jquery', 'layer', 'upload', 'excel', 'laytpl', 'element', 'code'], function () {
var $ = layui.jquery;
var layer = layui.layer;
var upload = layui.upload;
var excel = layui.excel;
var laytpl = layui.laytpl;
var element = layui.element;
/**
* 上传excel的处理函数,传入文件对象数组
* @param {FileList} files [description]
* @return {[type]} [description]
*/
function uploadExcel(files) {
try {
excel.importExcel(files, {
// 可以在读取数据的同时梳理数据
/*fields: {
'id': 'A'
, 'username': 'B'
, 'experience': 'C'
, 'sex': 'D'
, 'score': 'E'
, 'city': 'F'
, 'classify': 'G'
, 'wealth': 'H'
, 'sign': 'I'
}*/
}, function (data, book) {
// data: {1: {sheet1: [{id: 1, name: 2}, {...}]}}// 工作表的数据对象
// book: {1: {Sheets: {}, Props: {}, ....}} // 工作表的整个原生对象,https://github.com/SheetJS/js-xlsx#workbook-object
// 也可以全部读取出来再进行数据梳理
/* data = excel.filterImportData(data, {
'id': 'A'
, 'username': 'B'
, 'experience': 'C'
, 'sex': 'D'
, 'score': 'E'
, 'city': 'F'
, 'classify': 'G'
, 'wealth': 'H'
, 'sign': 'I'
})*/
// 如果不需要展示直接上传,可以再次 $.ajax() 将JSON数据通过 JSON.stringify() 处理后传递到后端即可
/**
* 2019-06-21 JeffreyWang 应群友需求,加一个单元格合并还原转换
* 思路:
* 1. 渲染时为每个cell加上唯一的ID,demo里边采用 table-export-文件索引-sheet名称-行索引-列索引
* 2. 根据 book[文件索引].Sheets[sheet名称]['!merge'] 参数,取左上角元素设置 colspan 以及 rowspan,并删除其他元素
*/
layer.open({
title: '文件转换结果'
, area: ['799px', '399px']
, tipsMore: true
, content: laytpl($('#LAY-excel-export-ans').html()).render({data: data, files: files})
, success: function () {
element.render('tab')
layui.code({})
// 处理合并
for (var file_index in book) {
if (!book.hasOwnProperty(file_index)) {
continue
}
// 遍历每个Sheet
for (var sheet_name in book[file_index].Sheets) {
if (!book[file_index].Sheets.hasOwnProperty(sheet_name)) {
continue
}
var sheetObj = book[file_index].Sheets[sheet_name]
// 仅在有合并参数时进行操作
if (!sheetObj['!merges']) {
continue
}
// 遍历每个Sheet中每个 !merges
for (var merge_index = 0; merge_index < sheetObj['!merges'].length; merge_index++) {
var mergeObj = sheetObj['!merges'][merge_index]
// 每个合并参数的 s.c 表示左上角单元格的列,s.r 表示左上角单元格的行,e.c 表示右下角单元格的列,e.r 表示右下角单元格的行,计算时注意 + 1
$('#table-export-' + file_index + '-' + sheet_name + '-' + mergeObj.s.r + '-' + mergeObj.s.c)
.prop('rowspan', mergeObj.e.r - mergeObj.s.r + 1)
.prop('colspan', mergeObj.e.c - mergeObj.s.c + 1)
for (var r = mergeObj.s.r; r <= mergeObj.e.r; r++) {
for (var c = mergeObj.s.c; c <= mergeObj.e.c; c++) {
// 排除左上角
if (r === mergeObj.s.r && c === mergeObj.s.c) {
continue
}
$('#table-export-' + file_index + '-' + sheet_name + '-' + r + '-' + c).remove()
}
}
}
}
}
}
})
})
} catch (e) {
layer.alert(e.message)
}
}
//upload上传实例
var uploadInst = upload.render({
elem: '#LAY-excel-upload' //绑定元素
, url: '/upload/' //上传接口(PS:这里不用传递整个 excel)
, auto: false //选择文件后不自动上传
, accept: 'file'
, choose: function (obj) {// 选择文件回调
var files = obj.pushFile()
var fileArr = Object.values(files)// 注意这里的数据需要是数组,所以需要转换一下
// 用完就清理掉,避免多次选中相同文件时出现问题
for (var index in files) {
if (files.hasOwnProperty(index)) {
delete files[index]
}
}
$('#LAY-excel-upload').next().val('');
uploadExcel(fileArr) // 如果只需要最新选择的文件,可以这样写: uploadExcel([files.pop()])
}
});
$(function () {
// 监听上传文件的事件
$('#LAY-excel-import-excel').change(function (e) {
// 注意:这里直接引用 e.target.files 会导致 FileList 对象在读取之前变化,导致无法弹出文件
var files = Object.values(e.target.files)
uploadExcel(files)
// 变更完清空,否则选择同一个文件不触发此事件
e.target.value = ''
})
// 文件拖拽
document.body.ondragover = function (e) {
e.preventDefault()
}
document.body.ondrop = function (e) {
e.preventDefault()
var files = e.dataTransfer.files
uploadExcel(files)
}
// 2019-08-17 页面直接展示所有demo
renderDemoList()
})
})
/**
* 上传excel的处理函数,传入文件对象数组
* @param {[type]} files [description]
* @return {[type]} [description]
*/
function uploadExcel(files) {
layui.use(['excel', 'layer'], function () {
var excel = layui.excel
var layer = layui.layer
try {
excel.importExcel(files, {
// 读取数据的同时梳理数据
fields: {
'id': 'A'
, 'username': 'B'
, 'experience': 'C'
, 'sex': 'D'
, 'score': 'E'
, 'city': 'F'
, 'classify': 'G'
, 'wealth': 'H'
, 'sign': 'I'
}
}, function (data) {
// 还可以再进行数据梳理
/* data = excel.filterImportData(data, {
'id': 'A'
,'username': 'B'
,'experience': 'C'
,'sex': 'D'
,'score': 'E'
,'city': 'F'
,'classify': 'G'
,'wealth': 'H'
,'sign': 'I'
});
*/
// 如果不需要展示直接上传,可以再次 $.ajax() 将JSON数据通过 JSON.stringify() 处理后传递到后端即可
layer.open({
title: '文件转换结果'
, area: ['800px', '400px']
, tipsMore: true
, content: laytpl($('#LAY-excel-export-ans').html()).render({data: data, files: files})
, success: function () {
element.render('tab')
layui.code({})
}
})
})
} catch (e) {
layer.alert(e.message)
}
})
}
/**
* 导出数据的测试
* @return {[type]} [description]
*/
function exportDataByUser() {
layui.use(['layer'], function () {
layer.ready(function () {
layer.prompt({
title: '请输入测试数据量(9列)'
, value: 3000
}, function (value, index, elem) {
// 使用setTimeout、async、ajax等方式可以实现异步导出
setTimeout(function () {
var num = parseInt(value)
var timestart = Date.now()
exportDataTest(num)
var timeend = Date.now()
var spent = (timeend - timestart) / 1000
layer.alert('耗时 ' + spent + ' s')
}, 0)
layer.close(index)
})
})
})
}
/**
* 导出接口数据的样例
* @return {[type]} [description]
*/
function exportApiDemo(url) {
layui.use(['jquery', 'excel', 'layer'], function () {
var $ = layui.jquery
var layer = layui.layer
var excel = layui.excel
// 模拟从后端接口读取需要导出的数据
$.ajax({
url: url
, dataType: 'json'
, success: function (res) {
var data = res.data
// 重点!!!如果后端给的数据顺序和映射关系不对,请执行梳理函数后导出
data = excel.filterExportData(data, {
id: 'id'
, username: 'username'
, experience: 'experience'
, sex: 'sex'
, score: function (value, line, data, lineIndex, newField) {
// 可以直接指定类型为数字
return {
v: value,
t: 'n'
}
}
, city: function (value, line, data, lineIndex, newField) {
return {
v: value,
s: {
font: {sz: 14, bold: true, color: {rgb: "FFFFAA00"}},
fill: {bgColor: {indexed: 64}, fgColor: {rgb: "FFFF00"}}
}
}
}
, classify: 'classify'
, wealth: 'wealth'
, sign: 'sign'
})
// 重点2!!!一般都需要加一个表头,表头的键名顺序需要与最终导出的数据一致
data.unshift({
id: "ID",
username: "用户名",
experience: '积分',
sex: '性别',
score: '评分',
city: '城市',
classify: '职业',
wealth: '财富',
sign: '签名'
})
var timestart = Date.now()
excel.exportExcel({
sheet1: data
}, '导出接口数据.xlsx', 'xlsx')
var timeend = Date.now()
var spent = (timeend - timestart) / 1000
layer.alert('单纯导出耗时 ' + spent + ' s')
}
, error: function () {
layer.alert('获取数据失败,请检查是否部署在本地服务器环境下')
}
})
})
}
/**
* 导出 total 数据测试
* @param {[type]} total [description]
* @return {[type]} [description]
*/
function exportDataTest(total) {
layui.use(['excel'], function () {
var excel = layui.excel
// 如果数据量特别大,最好直接传入 AOA 数组,减少内存/CPU消耗
var data = [
["ID", "用户名", '积分', '性别', '评分', '城市', '签名', '职业', '财富']
]
if (total > 0) {
// 造 num 条数据
for (var i = 0; i < total; i++) {
data.push([
'LAY-' + i,
'test' + i,
'',
200,
100,
'魔都',
'test' + i,
'程序猿',
100 * i,
])
}
}
excel.exportExcel({
sheet1: data
}, '测试导出' + total + '条数据.xlsx', 'xlsx')
})
}
/**
* 导出复杂表头数据问题
* @return {[type]} [description]
*/
function exportExtendDemo() {
layui.use(['excel'], function () {
var excel = layui.excel
var data = [
{
id: '标志位', username: {
v: '用户信息', s: {
alignment: {
horizontal: 'center',
vertical: 'center'
},
fill: {bgColor: {indexed: 64}, fgColor: {rgb: "FF0000"}}
}
}, age: '', sex: '', score: '', classify: ''
},// 被合并的列数据也需要填充上
{id: 'ID', username: '基础信息', age: '', sex: '', score: '扩展数据', classify: ''},
{id: 'id', username: '用户名', age: '年龄', sex: '性别', score: '积分', classify: '职业'},
{id: 1, username: 'wang', age: 10, sex: '', score: 100, classify: '程序猿'},
{id: 1, username: 'wang', age: 10, sex: '', score: 100, classify: '程序猿'},
{id: 1, username: 'wang', age: 10, sex: '', score: 100, classify: '程序猿'},
{id: 1, username: 'wang', age: 10, sex: '', score: 100, classify: '程序猿'},
{id: 1, username: 'wang', age: 10, sex: '', score: 100, classify: '程序猿'},
{id: 1, username: 'wang', age: 10, sex: '', score: 100, classify: '程序猿'},
{id: 1, username: 'wang', age: 10, sex: '', score: 100, classify: '程序猿'},
]
// 生成配置的辅助函数,返回结果作为扩展功能的配置参数传入即可
// 1. 复杂表头合并[B1,C1,D1][E1,F1]
var mergeConf = excel.makeMergeConfig([
['B1', 'F1'],
['B2', 'D2'],
['E2', 'F2'],
])
// 2. B列宽 150,F列宽200,默认80
var colConf = excel.makeColConfig({
'B': 150,
'F': 200,
}, 80)
// 3. 第1行行高40,第二行行高30,默认20
var rowConf = excel.makeRowConfig({
1: 40,
3: 30
}, 20)
// 4. 公式的用法
data.push({
id: '',
username: '总年龄',
age: {t: 'n', f: 'SUM(C4:C10)'},
sex: '总分',
score: {t: 'n', f: 'SUM(E4:E10)'},
classify: {
v: '注意:保护模式中公式无效,请「启用编辑」',
s: {font: {color: {rgb: 'FF0000'}}}
}
})
excel.exportExcel({
sheet1: data,
sheet2: data
}, '测试导出复杂表头.xlsx', 'xlsx', {
extend: {
// extend 中可以指定某个 sheet 的属性,如果不指定 sheet 则所有 sheet 套用同一套属性
sheet1: {
'!merges': mergeConf
, '!cols': colConf
, '!rows': rowConf
}
}
})
})
}
/**
* 快速设置样式使用方法
*/
function exportStyleDemo() {
layui.use(['excel'], function () {
var excel = layui.excel
var data = [
{username: '520', sex: '', city: 'J', 'score': 100, 'start': '2019-03-11'},
{username: '520', sex: '', city: 'X', 'score': 100, 'start': '2019-03-11'},
{username: '520', sex: '', city: '上海', 'score': 100, 'start': '2019-03-11'},
{username: '520', sex: '', city: '上海', 'score': 100, 'start': '2019-03-11'},
{username: '520', sex: '', city: '上海', 'score': 100, 'start': '2019-03-11'},
{username: '520', sex: '', city: '上海', 'score': 100, 'start': '2019-03-11'},
{username: '520', sex: '', city: '上海', 'score': 100, 'start': '2019-03-11'},
{username: '520', sex: '', city: '上海', 'score': 100, 'start': '2019-03-11'},
{username: '520', sex: '', city: '上海', 'score': 100, 'start': '2019-03-11'},
{username: '520', sex: '', city: '上海', 'score': 100, 'start': '2019-03-11'}
]// 假设的后台的数据
// 1. 使用filter梳理一下
data = excel.filterExportData(data, {
name: 'username',
sex: 'sex',
score: 'score',
start: 'start',
// 这里设置的样式会被合并
city: function (value) {
return {
v: value,
s: {
font: {sz: 14, bold: true, color: {rgb: "FFFFAA00"}},
alignment: {
horizontal: 'center',
vertical: 'center'
}
}
}
},
start2: 'start',
score2: 'score',
sex2: 'sex',
name2: 'username'
})
// 笔芯彩蛋(JeffreyWang 2019-03-11)
var heart = [
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 1, 1, 0, 1, 1, 0, 0],
[0, 1, 1, 1, 1, 1, 1, 1, 0],
[1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1],
[0, 1, 1, 1, 1, 1, 1, 1, 0],
[0, 0, 1, 1, 1, 1, 1, 0, 0],
[0, 0, 0, 1, 1, 1, 1, 0, 0],
[0, 0, 0, 0, 1, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
]
// 2. 调用设置样式的函数,传入设置的范围,支持回调
excel.setExportCellStyle(data, 'A1:I10', {
s: {
fill: {bgColor: {indexed: 64}, fgColor: {rgb: "FF0000"}},
alignment: {
horizontal: 'center',
vertical: 'center'
}
}
}, function (cell, newCell, row, config, currentRow, currentCol, fieldKey) {
// 回调参数,cell:原有数据,newCell:根据批量设置规则自动生成的样式,row:所在行数据,config:传入的配置,currentRow:当前行索引,currentCol:当前列索引,fieldKey:当前字段索引
// return ((currentRow + currentCol) % 2 === 0) ? newCell : cell;// 隔行隔列上色
return (heart[currentRow] && heart[currentRow][currentCol]) ? newCell : cell // 根据阵列,给心形上色
// return newCell;
})
// console.log(data);
// 3. 单元格样式优化为正方形
var colConfig = excel.makeColConfig({
'A': 80,
'I': 80
}, 80)
var rowConfig = excel.makeRowConfig({
1: 40,
10: 40
}, 40)
excel.exportExcel(data, '批量设置样式.xlsx', 'xlsx', {
extend: {
'!cols': colConfig,
'!rows': rowConfig
}
})
})
}
/**
* 加群交流弹窗
* @return {[type]} [description]
*/
function groupAdd() {
layui.use(['laytpl', 'layer', 'jquery'], function () {
var laytpl = layui.laytpl
var layer = layui.layer
var $ = layui.jquery
var content = laytpl($('#LAY-excel-group-add').html()).render({})
layer.open({
title: "加群交流"
, area: ['300px', '450px']
, content: content
})
})
}
function getDemoListContent(callback) {
layui.use(['laytpl', 'jquery'], function () {
var laytpl = layui.laytpl
var $ = layui.jquery
var list = [
{
href: 'demos/tableExport/index.html',
path: 'demos/tableExport/index.html',
person: '雨桐',
email: 'yuton.yao@qq.com',
desc: '导出表格数据的DEMO'
},
{
href: 'https://kingxjs.github.io/layui-excel-merge/',
path: 'kingxjs.github.io/layui-excel-merge/',
person: 'kingxjs',
email: '未知',
desc: 'layui 表格中的复杂表头导出'
},
{
href: 'demos/noLayui/index.html',
path: 'demos/noLayui/index.html',
person: '藏锋入鞘',
email: 'admin@wj2015.com',
desc: '非LAYUI调用及原生表格导出'
},
{
href: 'demos/borderExport/index.html',
path: 'demos/borderExport/index.html',
person: '藏锋入鞘',
email: 'admin@wj2015.com',
desc: '边框设置DEMO'
},
{
href: 'demos/iframeExport/index.html',
path: 'demos/iframeExport/index.html',
person: '藏锋入鞘',
email: 'admin@wj2015.com',
desc: 'iframe子页面调用导出'
},
{
href: 'demos/timeHandle/index.html',
path: 'demos/timeHandle/index.html',
person: '藏锋入鞘',
email: 'admin@wj2015.com',
desc: '时间的导入导出控制'
}
]
var content = laytpl($('#LAY-excel-demo-list').html()).render({
list: list
})
if (typeof callback == 'function' && callback.apply) {
callback.apply(window, [content])
}
})
}
/**
* 弹窗弹出demo列表
*/
function demoList() {
getDemoListContent(function (content) {
layui.use(['layer'], function () {
var layer = layui.layer
layer.open({
title: "使用样例"
, area: ['800px', '250px']
, content: content
})
})
})
}
/**
* 页面上直接展示demo列表
*/
function renderDemoList() {
layui.use(['jquery'], function () {
var $ = layui.jquery;
getDemoListContent(function (content) {
$('#LAY-excel-demo-list-dom').html(content)
})
});
}
JavaScript
1
https://gitee.com/xsklf/layui-excel.git
git@gitee.com:xsklf/layui-excel.git
xsklf
layui-excel
layui-excel
master

搜索帮助