Luckysheet ,一款纯前端类似excel的在线表格,功能强大、配置简单、完全开源。
##,###0.00 , $1,234.56$##,###0.00_);[Red]($##,###0.00), _($* ##,###0.00_);_(...($* "-"_);_(@_), 08-05 PM 01:30MM-dd AM/PM hh:mm )撤销/恢复
复制/粘贴/剪切操作 (支持Luckysheet到excel和excel到Luckysheet带格式的互相拷贝)
快捷键支持 (快捷键操作保持与excel一致)
| 快捷键 | 功能 |
|---|---|
| CTRL + C | 复制单元格 |
| CTRL + V | 粘贴单元格 |
| CTRL + X | 剪切单元格 |
| CTRL + Z | 撤销 |
| CTRL + Y | 重做 |
| CTRL + A | 全选 |
| CTRL + B | 加粗 |
| CTRL + F | 查找 |
| CTRL + H | 替换 |
| CTRL + I | 斜体 |
| CTRL + UP/DOWN/LEFT/RIGHT | 快捷调整单元格选框 |
| SHIFT + UP/DOWN/LEFT/RIGHT | 调整选区 |
| CTRL + 鼠标左击 | 多选单元格 |
| SHIFT + 鼠标左击 | 调整选区 |
| UP/DOWN/LEFT/RIGHT | 移动单元格选框 |
| ENTER | 编辑单元格 |
| TAB | 向右移动单元格选框 |
| DELETE | 清除单元格数据 |
格式刷 (与google sheet类似)
任意选区拖拽 (选择单元格,输入公式,插入图表,会与选区相关,可以通过任意拖动和放大缩小选区来改变与之关联的参数)
功能界面如下:

克隆Luckysheet源码到本地
git clone https://github.com/dream-num/Luckysheet.git
npm install
npm install gulp -g
npm run dev
npm run build
npm run build 后 dist 文件夹下的所有文件复制到vue项目的public目录下,然后在index.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>
<div id="luckysheet" class="luckysheet-wrap">div>
<style scoped>
.luckysheet-wrap {
margin: 0px;
padding: 0px;
position: absolute;
width: 100%;
height: 100%;
left: 0px;
top: 0px;
}
style>
data () {
return {
// 配置项
options: {
container: 'luckysheet', // DOM容器的ID
title: '电子表格', // 工作簿名称
lang: 'zh', // 设定表格的语言
showtoolbarConfig: {
print: false, // 工具栏隐藏打印按钮
},
showsheetbarConfig: {
add: false, // 底部sheet页隐藏新增sheet按钮
menu: false, // 底部sheet页隐藏管理按钮
},
sheetRightClickConfig: {
hide: false, // 隐藏,取消隐藏
move: false, // 向左移,向右移
}
}
};
},
mounted () {
this.createSheet()
},
methods:{
// 创建工作表
createSheet () {
// 初始化表格
luckysheet.create(this.options)
// 获取Luckysheet表格文件的数据
this.sheetfile = luckysheet.getluckysheetfile()
// console.log(this.sheetfile)
}
}
初始化表格时,可以设置一个对象 options 来自定义配置Luckysheet表格。
如下是一个简洁的配置案例:
// 配置项
const options = {
container: 'luckysheet', // 设定DOM容器的id
title: 'Luckysheet Demo', // 设定表格名称
lang: 'zh' // 设定表格语言
// 更多其他设置...
}
// 初始化表格
luckysheet.create(options)
这里的 options 配置项会作用于整个表格,单个sheet的配置则需要在 options.data 数组中,分别设置对应更详细的参数,参考工作表配置
loadUrl和loadSheetUrl的时候,需要手动配置传入整个客户端所有sheet数据[shee1, sheet2, sheet3],详细参数设置参见工作表配置类型:Object
默认值:{}
作用:自定义配置工具栏,可以与showtoolbar配合使用,showtoolbarConfig拥有更高的优先级。
示例:
仅显示撤消重做和字体按钮:
// options
{
showtoolbar: false,
showtoolbarConfig:{
undoRedo: true,
font: true,
}
}
仅隐藏图片和打印按钮:
// options
{
showtoolbar: true, // 默认就是true,可以不设置
showtoolbarConfig:{
image: false,
print: false,
}
}
类型:Object
默认值:{}
作用:自定义配置底部sheet页按钮,可以与showsheetbar配合使用,showsheetbarConfig拥有更高的优先级。
格式:
{
add: false, // 新增sheet
menu: false, // sheet管理菜单
sheet: false // sheet页显示
}
示例:
仅显示新增sheet按钮:
// options
{
showsheetbar: false,
showsheetbarConfig:{
add: true,
}
}
仅隐藏新增sheet和管理按钮:
// options
{
showsheetbar: true, // 默认就是true,可以不设置
showsheetbarConfig:{
add: false,
menu: false,
}
}
类型:Object
默认值:{}
作用:自定义配置sheet页右击菜单
格式:
{
delete: false, // 删除
copy: false, // 复制
rename: false, // 重命名
color: false, // 更改颜色
hide: false, // 隐藏,取消隐藏
move: false, // 向左移,向右移
}
钩子函数应用于二次开发时,会在各个常用鼠标或者键盘操作时植入钩子,调用开发者传入的函数,起到扩展Luckysheet功能的作用。
钩子函数统一配置在options.hook下,可以分别针对单元格、sheet页、表格创建配置hook。
使用案例可参考源码 src/index.html
常用钩子函数如下:
鼠标钩子:
工作簿:
参数:
v或者显示值m;默认值为v,表示获取单元格的实际值说明:
获取单元格的值。
特殊情况,单元格格式为yyyy-MM-dd,type为'v'时会强制取'm'显示值
参数:
true;用于多个单元格赋值时候控制节流,前面单元格赋值的时候应设置为 false,最后一个单元格赋值时设置为true。说明:
设置某个单元格的值,也可以设置整个单元格对象,用于同时设置多个单元格属性。
如果需要更新公式,也可以在这里赋值,Luckysheet在内部会主动把这个公式做计算并加入到公式链中,最后重刷界面。
参数:
{Boolean} [title]: 是否首行为标题
title可能的值有:
"true": 首行为标题"false": 首行不为标题{PlainObject} [setting]: 可选参数
"A1:B2"、"sheetName!A1:B2"或者{row:[0,1],column:[0,1]},只能为单个选区;默认为当前选区说明:
复制指定工作表指定单元格区域的数据,返回json格式的数据
说明:
返回所有工作表配置,格式同工作表配置,得到的结果可用于表格初始化时作为options.data使用。
所以此API适用于,手动操作配置完一个表格后,将所有工作表信息取出来自行保存,再用于其他地方的表格创建。如果想得到包括工作簿配置在内的所有工作簿数据,推荐使用 toJson,并且可以直接用于初始化Luckysheet。
示例:
luckysheet.getAllSheets()[0]说明:
返回所有表格数据结构的一维数组luckysheetfile,不同于getAllSheets方法,此方法得到的工作表参数会包含很多内部使用变量,最明显的区别是表格数据操作会维护luckysheetfile[i].data,而初始化数据采用的是options.data[i].celldata,所以luckysheetfile可用于调试使用,但是不适用初始化表格。
除此之外,加载过的工作表参数中会增加一个load = 1,这个参数在初始化数据的时候需要置为0才行。所以,将getLuckysheetfile()得到的数据拿来初始化工作簿,需要做两个工作:
现在已有getAllSheets来完成这个工作,无需再手动转化数据。
示例:
luckysheet.getLuckysheetfile()[0]参数:
说明:
初始化一个Luckysheet,可包含多个工作表
参数:
说明:
获取工作簿名称
// 导入json数据
importJson (data) {
let range = luckysheet.getRange()
// console.log(range)
let row = range[0].row[0]
let column = range[0].column[0]
if (data.length > 0) {
let keys = Object.keys(data[0])
// console.log(keys)
keys.forEach((item, index) => {
luckysheet.setCellValue(row, column + index, item)
})
}
data.forEach((item1, index1) => {
// console.log(item1)
let values = Object.values(item1)
// console.log(values)
values.forEach((item2, index2) => {
luckysheet.setCellValue(row + 1 + index1, column + index2, item2)
})
})
}
sheetData是一个JSON数组,格式如下:
[
{"年级":"初一","姓名":"李四","学号":7142,"年龄":18,"籍贯":"河北","成绩":79},
{"年级":"初二","姓名":"王五","学号":7143,"年龄":19,"籍贯":"河北","成绩":80},
{"年级":"初三","姓名":"李华","学号":7144,"年龄":20,"籍贯":"山东","成绩":81},
{"年级":"初一","姓名":"赵国","学号":7145,"年龄":21,"籍贯":"河北","成绩":82},
{"年级":"初一","姓名":"李青","学号":7146,"年龄":22,"籍贯":"河北","成绩":83},
{"年级":"初三","姓名":"王国","学号":7147,"年龄":23,"籍贯":"山西","成绩":84},
{"年级":"初一","姓名":"正东","学号":7148,"年龄":24,"籍贯":"四川","成绩":85},
{"年级":"初二","姓名":"钱多","学号":7149,"年龄":25,"籍贯":"河北","成绩":86},
{"年级":"初一","姓名":"付丽","学号":7150,"年龄":26,"籍贯":"贵州","成绩":87}
]
选中工作区,才能导出JSON数据
// 导出json数据
exportJson () {
let jsonData = luckysheet.getRangeJson(true)
console.log(jsonData)
}
选中工作区,才能导出csv格式的数据
// 导出工作表csv格式
exportCsv () {
let name = luckysheet.getWorkbookName()
// console.log(name)
let exceldata = luckysheet.getRangeJson(true)
// console.log(exceldata)
let data = ""
let keys = Object.keys(exceldata[0])
// console.log(keys)
data = keys.join(",")
exceldata.forEach(item => {
let values = Object.values(item)
// console.log(values)
data += "\n" + values.join(",")
})
// console.log(data)
// Download element
var blob = new Blob(["\uFEFF" + data], { type: 'text/csv;charset=utf-8;' });
// IE Compatibility
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveOrOpenBlob(blob, name + '.csv');
} else {
// Download element
var pom = document.createElement('a');
var url = URL.createObjectURL(blob);
pom.href = url;
pom.setAttribute('download', name + '.csv');
document.body.appendChild(pom);
pom.click();
pom.parentNode.removeChild(pom);
}
},
// 保存工作表数据
saveData () {
let data = luckysheet.getLuckysheetfile()
data.forEach((item, index) => {
if (item.chart) {
item.chart.forEach((chart, i) => {
data[index].chart[i] = {
...data[index].chart[i],
chartOptions: { ...chartmix.default.getChartJson(chart.chart_id) }
}
let div = document.getElementById(chart.chart_id + '_c');
if (div.style) {
data[index].chart[i].left = parseInt(div.style.left)
data[index].chart[i].top = parseInt(div.style.top)
data[index].chart[i].width = parseInt(div.style.width)
data[index].chart[i].height = parseInt(div.style.height)
}
})
}
})
console.log(data)
}
创建表格前,手动配置传入整个客户端所有sheet数据的options的data选项
mounted () {
this.setData()
// this.createSheet()
// this.addButton()
},
methods: {
setData () {
this.$axios.post("/api/sheetData").then(res => {
console.log(res)
this.$set(this.options, "data", res.data)
// this.options.data = res.data
console.log(this.options.data)
this.createSheet()
})
}
}
单条数据量不大的情况下,支持5000+的数据量不卡

src/controllers/ sheet 主要操作
src/expendPlugins/ 扩展
src/locale/ 语言包
src/config.js 默认导出sheet创建配置信息
src/css/luckysheet-core.css 页面结构样式类