一、介绍
Luckysheet是一款纯前端类似excel的在线表格,功能强大、配置简单、完全开源的插件。目前已暂停维护,但是其已有功能大概能满足常见需求的使用。
二、引入
①cdn引入(目前应该已经不支持,可自行尝试)
<link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/luckysheet@latest/dist/plugins/css/pluginsCss.css' />
<link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/luckysheet@latest/dist/plugins/plugins.css' />
<link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/luckysheet@latest/dist/css/luckysheet.css' />
<link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/luckysheet@latest/dist/assets/iconfont/iconfont.css' />
<script src="https://cdn.jsdelivr.net/npm/luckysheet@latest/dist/plugins/js/plugin.js"></script>
<script src="https://cdn.jsdelivr.net/npm/luckysheet@latest/dist/luckysheet.umd.js"></script>
②本地引入
需使用npm或者从其他资源处获取luckysheet包,将dist中全部文件放在项目文件夹中,随后在html页面进行相关文件的引用。
<link rel='stylesheet' href='./plugins/css/pluginsCss.css' />
<link rel='stylesheet' href='./plugins/plugins.css' />
<link rel='stylesheet' href='./css/luckysheet.css' />
<link rel='stylesheet' href='./assets/iconfont/iconfont.css' />
<script src="./plugins/js/plugin.js"></script>
<script src="./luckysheet.umd.js"></script>
三、使用
1、初始化
// 插件配置项
var options = {
container: 'luckysheet', //luckysheet为容器id
title: 'Luckysheet Demo', // 设定表格名称
lang: 'zh' // 设定表格语言
}
window.luckysheet.create(options)
针对个性化的需求,除了允许配置信息栏(showinfobar)、工具栏(showtoolbar)、底部sheet页(showsheetbar)、底部计数栏(showstatisticBar)之外, Luckysheet开放了更细致的自定义配置选项,分别有:
①自定义工具栏(showtoolbarConfig)
②自定义底部sheet页(showsheetbarConfig)
③自定义计数栏(showstatisticBarConfig)
④自定义单元格右键菜单(cellRightClickConfig)
⑤自定义底部sheet页右击菜单(sheetRightClickConfig)
2、表格配置项
表格初始化配置options时,需要配置一个由每个工作表参数组成的一维数组,赋给options.data。
options.data示例如下:
[
{
"name": "Cell", //工作表名称
"color": "", //工作表颜色
"index": 0, //工作表索引
"status": 1, //激活状态
"order": 0, //工作表的下标
"hide": 0,//是否隐藏
"row": 36, //行数
"column": 18, //列数
"defaultRowHeight": 19, //自定义行高
"defaultColWidth": 73, //自定义列宽
"celldata": [], //初始化使用的单元格数据
"config": {
"merge":{}, //合并单元格
"rowlen":{}, //表格行高
"columnlen":{}, //表格列宽
"rowhidden":{}, //隐藏行
"colhidden":{}, //隐藏列
"borderInfo":{}, //边框
"authority":{}, //工作表保护
},
"scrollLeft": 0, //左右滚动条位置
"scrollTop": 315, //上下滚动条位置
"luckysheet_select_save": [], //选中的区域
"calcChain": [],//公式链
"isPivotTable":false,//是否数据透视表
"pivotTable":{},//数据透视表设置
"filter_select": {},//筛选范围
"filter": null,//筛选配置
"luckysheet_alternateformat_save": [], //交替颜色
"luckysheet_alternateformat_save_modelCustom": [], //自定义交替颜色
"luckysheet_conditionformat_save": {},//条件格式
"frozen": {}, //冻结行列配置
"chart": [], //图表配置
"zoomRatio":1, // 缩放比例
"image":[], //图片
"showGridLines": 1, //是否显示网格线
"dataVerification":{} //数据验证配置
},
{
"name": "Sheet2",
"color": "",
"index": 1,
"status": 0,
"order": 1,
"celldata": [],
"config": {}
},
{
"name": "Sheet3",
"color": "",
"index": 2,
"status": 0,
"order": 2,
"celldata": [],
"config": {},
}
]
3、数据的输入和输出
①初始化输入
表格中的数据初始化与表对象中的celldata相关。celldata对象是原始单元格数据集,存储sheet中所有单元格中的值,是一个包含{r:0,c:0,v:{m:"value",v:"value",ct: {fa: "General", t: "g"}}}格式单元格信息的一维数组,只在初始化的时候使用。
r代表行,c代表列,v代表该单元格的值,值可以是字符、数字或者对象。
Luckysheet在建立的时候会根据 options.data[i].row 和 options.data[i].column 的行列数量大小新建一个表格data,然后再使用 data[r][c]=v 的方式填充表格数据,空数据单元格以null表示。
使用celldata初始化完表格后,数据转换为luckysheetfile中的字段data,如luckysheetfile[i].data,后续操作表格的数据更新,会更新到这个data字段中,celldata不再使用。
[{
"r": 0,
"c": 0,
"v": {
ct: {fa: "General", t: "g"},
m:"value1", // m为表格显示的值
v:"value1" // 不显示但可以获取的实际值
},
value: 100
}, {
"r": 0,
"c": 1,
"v": {
ct: {fa: "General", t: "g"},
m:"value2",
v:"value2"
},
value: 100
}]
②输出
可使用插件自带的API获取表格最新的数据。这里需要注意的问题是,导出的数据中,通常m和v的值是一致的,疑是插件的bug。所以当我我们定义了单元格中不同的m和v值,同时想要调用以下方法获得单元格的实际v值时,可自定义一个value值的方式得到我们想要的单元格实际值。
window.luckysheet.getAllSheets()[0].data
③导出
需安装 exceljs 插件,luckysheet提供数据处理,文件的写入由exceljs负责。
exportExcel(window.luckysheet.getluckysheetfile()).then((data) => {
const blob = new Blob([data], {
type: "application/vnd.ms-excel;charset=utf-8",
});
this.$download.saveAs(blob, "xxx");
});
const Excel = require('exceljs')
export async function exportExcel (luckysheet) { // 参数为luckysheet.getluckysheetfile()获取的对象
// 1.创建工作簿,可以为工作簿添加属性
const workbook = new Excel.Workbook()
// 2.创建表格,第二个参数可以配置创建什么样的工作表
luckysheet.every(function (table) {
if (table.data.length === 0) return true
const worksheet = workbook.addWorksheet(table.name)
// 3.设置单元格合并,设置单元格边框,设置单元格样式,设置值
setStyleAndValue(table.data, worksheet)
// setMerge(table.config.merge, worksheet)
// setBorder(table.config.borderInfo, worksheet)
return true
})
// 4.写入 buffer
const buffer = await workbook.xlsx.writeBuffer()
return buffer
}
var setMerge = function (luckyMerge = {}, worksheet) {
const mergearr = Object.values(luckyMerge)
mergearr.forEach(function (elem) { // elem格式:{r: 0, c: 0, rs: 1, cs: 2}
// 按开始行,开始列,结束行,结束列合并(相当于 K10:M12)
worksheet.mergeCells(elem.r + 1, elem.c + 1, elem.r + elem.rs, elem.c + elem.cs)
})
}
var setBorder = function (luckyBorderInfo, worksheet) {
if (!Array.isArray(luckyBorderInfo)) return
luckyBorderInfo.forEach(function (elem) {
let border = borderConvert(elem.borderType, elem.style, elem.color)
let rang = elem.range[0]
// console.log(rang.column_focus + 1, rang.row_focus + 1)
worksheet.getCell(rang.row_focus + 1, rang.column_focus + 1).border = border
})
}
var setStyleAndValue = function (cellArr, worksheet) {
if (!Array.isArray(cellArr)) return
cellArr.forEach(function (row, rowid) {
row.every(function (cell, columnid) {
if (!cell) return true
let fill = fillConvert(cell.bg)
let font = fontConvert(cell.ff, cell.fc, cell.bl, cell.it, cell.fs, cell.cl, cell.ul)
let alignment = alignmentConvert(cell.vt, cell.ht, cell.tb, cell.tr)
let value
if (cell.f) {
value = { formula: cell.f, result: cell.v }
} else {
value = cell.v
}
let target = worksheet.getCell(rowid + 1, columnid + 1)
target.fill = fill
target.font = font
target.alignment = alignment
target.value = value
return true
})
})
}
var fillConvert = function (bg) {
if (!bg) {
return {}
}
let fill = {
type: 'pattern',
pattern: 'solid',
fgColor: {argb: bg.replace('#', '')}
}
return fill
}
var fontConvert = function (ff = 0, fc = '#000000', bl = 0, it = 0, fs = 10, cl = 0, ul = 0) { // luckysheet:ff(样式), fc(颜色), bl(粗体), it(斜体), fs(大小), cl(删除线), ul(下划线)
const luckyToExcel = {
0: '微软雅黑',
1: '宋体(Song)',
2: '黑体(ST Heiti)',
3: '楷体(ST Kaiti)',
4: '仿宋(ST FangSong)',
5: '新宋体(ST Song)',
6: '华文新魏',
7: '华文行楷',
8: '华文隶书',
9: 'Arial',
10: 'Times New Roman ',
11: 'Tahoma ',
12: 'Verdana',
num2bl: function (num) {
return num === 0 ? false : true
}
}
let font = {
name: luckyToExcel[ff],
family: 1,
size: fs,
color: {argb: fc.replace('#', '')},
bold: luckyToExcel.num2bl(bl),
italic: luckyToExcel.num2bl(it),
underline: luckyToExcel.num2bl(ul),
strike: luckyToExcel.num2bl(cl)
}
return font
}
var alignmentConvert = function (vt = 'default', ht = 'default', tb = 'default', tr = 'default') { // luckysheet:vt(垂直), ht(水平), tb(换行), tr(旋转)
const luckyToExcel = {
vertical: {
0: 'middle',
1: 'top',
2: 'bottom',
default: 'top'
},
horizontal: {
0: 'center',
1: 'left',
2: 'right',
default: 'left'
},
wrapText: {
0: false,
1: false,
2: true,
default: false
},
textRotation: {
0: 0,
1: 45,
2: -45,
3: 'vertical',
4: 90,
5: -90,
default: 0
}
}
let alignment = {
vertical: luckyToExcel.vertical[vt],
horizontal: luckyToExcel.horizontal[ht],
wrapText: luckyToExcel.wrapText[tb],
textRotation: luckyToExcel.textRotation[tr]
}
return alignment
}
var borderConvert = function (borderType, style = 1, color = '#000') { // 对应luckysheet的config中borderinfo的的参数
if (!borderType) {
return {}
}
const luckyToExcel = {
type: {
'border-all': 'all',
'border-top': 'top',
'border-right': 'right',
'border-bottom': 'bottom',
'border-left': 'left'
},
style: {
0: 'none',
1: 'thin',
2: 'hair',
3: 'dotted',
4: 'dashDot', // 'Dashed',
5: 'dashDot',
6: 'dashDotDot',
7: 'double',
8: 'medium',
9: 'mediumDashed',
10: 'mediumDashDot',
11: 'mediumDashDotDot',
12: 'slantDashDot',
13: 'thick'
}
}
let template = {style: luckyToExcel.style[style], color: {argb: color.replace('#', '')}}
let border = {}
if (luckyToExcel.type[borderType] === 'all') {
border['top'] = template
border['right'] = template
border['bottom'] = template
border['left'] = template
} else {
border[luckyToExcel.type[borderType]] = template
}
return border
}