在线电子表格编辑器 Luckysheet
下载地址
不知道地址正不正经,我先用着,网上找的地址,不知道是不是可信任的,疑似官网的两个地址都打不开,
https://github.com/dream-num/Luckysheet
zip包 https://codeload.github.com/dream-num/Luckysheet/zip/refs/heads/master
或者克隆
别人是这里下载的,好像是官网之一,打不开
这里有学习文档 :https://mengshukeji.gitee.io/LuckysheetDocs/zh/guide/#%E5%9F%BA%E6%9C%AC%E4%BB%8B%E7%BB%8D
引用方法
在提交PR之前,请确保仔细阅读 贡献指南。
用法
第一步
通过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>
第二步
指定一个表格容器
<div id="luckysheet" style="margin:0px;padding:0px;position:absolute;width:100%;height:100%;left: 0px;top: 0px;"></div>
第三步
创建一个表格
<script>
$(function () {
//配置项
var options = {
container: 'luckysheet' //luckysheet为容器id
}
luckysheet.create(options)
})
</script>
引用效果
如果不添加其它的,它是整个浏览器全屏显示
我找了是把它放在其它div下,非全屏,必须得加高度,不然显示不出来单元格
body下没设置其它div,是这样的全屏效果
离线部署获得dist文件
yum install npm
# 拉取代码,我是下载的zip包安装的,这个地址不知道是不是官网的,好像不是
git clone https://github.com/mengshukeji/Luckysheet.git
# 安装
cd Luckysheet-master
npm install
npm install gulp -g
# 运行
npm run build
[root@mcw01 Luckysheet-master]# ls CHANGELOG.md commitlint.config.js deploy.bat dist docs gulpfile.js LICENSE node_modules package.json package-lock.json README.md README-zh.md src yarn.lock [root@mcw01 Luckysheet-master]# ls dist/ assets css demoData expendPlugins fonts index.html luckysheet.umd.js luckysheet.umd.js.map plugins [root@mcw01 Luckysheet-master]# tar zcf mytable.tar.gz dist [root@mcw01 Luckysheet-master]# ls CHANGELOG.md commitlint.config.js deploy.bat dist docs gulpfile.js LICENSE mytable.tar.gz node_modules package.json package-lock.json README.md README-zh.md src yarn.lock [root@mcw01 Luckysheet-master]#
把生成的dist放到代码下面,我这里只是单纯的随便放的,然后把你网页的静态文件地址改成当前文件dist下的静态文件
没问题,正常使用,是用的本地文件。不是请求的网上的文件了
引用方法同上
我修改的引用
<!doctype html> <html> <head> <meta charset="utf-8"> <title>无标题文档</title> <link rel='stylesheet' href='./dist/plugins/css/pluginsCss.css' /> <link rel='stylesheet' href='./dist/plugins/plugins.css' /> <link rel='stylesheet' href='./dist/css/luckysheet.css' /> <link rel='stylesheet' href='./dist/assets/iconfont/iconfont.css' /> <script src="./dist/plugins/js/plugin.js"></script> <script src="./dist/luckysheet.umd.js"></script> </head> <body> <div> <div style="height: 40px;background-color: green;"></div> <div> <div style="float:left;width: 29.5%;height: 1000px;background-color: blue;"></div> <div style="float:right;width: 70%;height: 1000px;background-color: yellowgreen;"> <div id="luckysheet" style="margin:0px;padding:0px;width:100%;height:100%;left: 20px;top: 48px;"></div> </div> </div> </div> </body> <script> $(function () { //Configuration item var options = { container: 'luckysheet' //luckysheet is the container id } luckysheet.create(options) }) </script> </html>
表格和后端数据库做交互
总的代码
test.html
<!doctype html> <html> <head> <meta charset="utf-8"> <title>无标题文档</title> <link rel='stylesheet' href='/static/dist/plugins/css/pluginsCss.css' /> <link rel='stylesheet' href='/static/dist/plugins/plugins.css' /> <link rel='stylesheet' href='/static/dist/css/luckysheet.css' /> <link rel='stylesheet' href='/static/dist/assets/iconfont/iconfont.css' /> <script src="/static/dist/plugins/js/plugin.js"></script> <script src="/static/dist/luckysheet.umd.js"></script> </head> <body> {#<div id="luckysheet" style="margin:0px;padding:0px;position:absolute;width:100%;height:100%;left: 0px;top: 0px;"></div>#} <a class="btn btn-primary btn-rounded btn-sm" onclick="saveData()"><i class="fa fa-save"></i> <@ctx.i18n text = "保存数据"/></a> <div id="luckysheet" style="margin-top:48px;padding:0px;position:absolute;width:100%;height:90%;left: 0px;top: 0px;"> </div> </body> <script> $(function () { var options = { container: 'luckysheet', title: '工作汇报', lang: 'zh', showsheetbar:false, data: [ { "name": "进度填报表", "status": 1, "celldata": [{"r":0,"c":0,"v":{"m":"dd","ct":{"fa":"General","t":"g"},"v":"dd"}},{"r":0,"c":1,"v":{"m":"dd","ct":{"fa":"General","t":"g"},"v":"dd"}},{"r":0,"c":2,"v":{"m":"b","ct":{"fa":"General","t":"g"},"v":"b"}}] } ] } luckysheet.create(options); }) function saveData() { var celldata = (JSON.stringify(luckysheet.transToCellData(luckysheet.getLuckysheetfile()[0].data))); $.ajax({ url:"http://127.0.0.1:5000/article/mcw", data:{"sheetData":celldata,"scheId":0}, Type:"post", dataType:"json", success:function(res) { console.log(res); } }); } </script> </html>
视图函数
@article_bp1.route('/testmytb', methods=['POST', 'GET']) def testmytb(): return render_template('test.html') @article_bp1.route('/mcw', methods=['POST', 'GET']) def testmytb1(): print(request.args) return ''
从数据库中获取数据并渲染在表格中
<div id="luckysheet" style="margin-top:48px;padding:0px;position:absolute;width:100%;height:90%;left: 0px;top: 0px;"> </div> $(function () { var options = { container: 'luckysheet', title: '工作汇报', lang: 'zh', showsheetbar:false, data: [ { "name": "进度填报表", "status": 1, "celldata": [{"r":0,"c":0,"v":{"m":"dd","ct":{"fa":"General","t":"g"},"v":"dd"}},{"r":0,"c":1,"v":{"m":"dd","ct":{"fa":"General","t":"g"},"v":"dd"}},{"r":0,"c":2,"v":{"m":"b","ct":{"fa":"General","t":"g"},"v":"b"}}] } ] } luckysheet.create(options); }) }
单元格数据结构如下:
分析:
- title: '工作汇报',可以指的工作簿名称;
- 我们指定了表名但是没有出来 "name": "进度填报表";
- 在数据里存放的应该是工作表列表,这里只放了一个进度填报表,虽然表名字没有出来。单元格数据用如下格式存放到单元格数据里面。也就是我们可以在后端将数据查出来然后存放到这里,然后前端页面就能看到后端传递渲染的数据
- 单元格数据里放的是单元格列表,单元格的值是v下面的v里面
[{ "r": 0, "c": 0, "v": {"m": "dd", "ct": {"fa": "General", "t": "g"}, "v": "dd"} }, {"r": 0, "c": 1, "v": {"m": "dd", "ct": {"fa": "General", "t": "g"}, "v": "dd"}}, {"r": 0, "c": 2, "v": {"m": "b", "ct": {"fa": "General", "t": "g"}, "v": "b"}}]
效果如下图
将表格数据传递给后端保存到数据库中
现象:
在前端输入数据,点击保存按钮
后段能在拼接的工作表数据里面获取到单元格数据
再看看下代码
- 在某个地方定义一个保存按钮,并给保存按钮绑定保存点击事件的函数
- 当点击保存数据按钮时,触发执行函数,会获取到单元格数据,然后发送ajax请求,这里是post请求,但是我们将单元格数据和表id放到data参数下,它们会以?和&符号拼接到url后面,作为args参数,
- 后端需要从args中获取到这两个值,其中一个就是单元格数据,这样我们就可以保存到数据库中了。这个url也可以不用写ip端口的
<a class="btn btn-primary btn-rounded btn-sm" onclick="saveData()"><i class="fa fa-save"></i> <@ctx.i18n text = "保存数据"/></a> $(function () { function saveData() { var celldata = (JSON.stringify(luckysheet.transToCellData(luckysheet.getLuckysheetfile()[0].data))); $.ajax({ url:"http://127.0.0.1:5000/article/mcw", data:{"sheetData":celldata,"scheId":0}, Type:"post", dataType:"json", success:function(res) { console.log(res); } }); }
- 我们再研究一下,当点击保存后,会将单元格中的数据按如下格式发送到请求的url。然后它对应的视图函数可以从args中获取sheetData参数的值,也就是保存的单元格数据。数据里面有两个都显示了单元格内容。
- 由行数,列数和图片中数据填写位置得知,r就是行索引,c就是列索引,v就是就是value,value下面还有其它信息,v下面的m和v是单元格的具体内容,可能用v更好点吧。
- 也就是我们从args中获取到这个数据,就可以保存到数据库了,
- 由保存数据和渲染数据可以看出,二者数据结构基本差不多,那么是不是就可以直接将表格数据json存入到数据库,然后读取的时候直接从数据库读取渲染呢。回头验证
[{"r": 0, "c": 0, "v": {"m": "dd", "ct": {"fa": "General", "t": "g"}, "v": "dd"}}, {"r": 0, "c": 1, "v": {"m": "dd", "ct": {"fa": "General", "t": "g"}, "v": "dd"}}, {"r": 0, "c": 2, "v": {"m": "b", "ct": {"fa": "General", "t": "g"}, "v": "b"}}, {"r": 1,"c": 1, "v": {"m": "小马","ct": {"fa": "General", "t": "g"}, "v": "小马"}}]
在线表格中元素增删改,样式修改
这些修改我是放在跟options一起的函数里面,创建表后面才生效的,放在这这个function之外一直没生效。放在里面添加标签和修改样式都是生效的
对在线表格保存数据和渲染数据的实操案例
<!doctype html> <html> <head> <meta charset="utf-8"> <title>无标题文档</title> <link rel='stylesheet' href='/static/dist/plugins/css/pluginsCss.css' /> <link rel='stylesheet' href='/static/dist/plugins/plugins.css' /> <link rel='stylesheet' href='/static/dist/css/luckysheet.css' /> <link rel='stylesheet' href='/static/dist/assets/iconfont/iconfont.css' /> <script src="/static/dist/plugins/js/plugin.js"></script> <script src="/static/dist/luckysheet.umd.js"></script> </head> <body> <div id="luckysheet" style="margin:0px;padding:0px;position:absolute;width:100%;height:100%;left: 0px;top: 0px;"></div> </body> <script> $(function () { var options = { container: 'luckysheet', title: '工作汇报', lang: 'zh', showsheetbar:false, data: [ { "name": "进度填报表", "status": 1, "celldata": {{ cellData.content |safe}},//[{"r":0,"c":0,"v":{"m":"dd","ct":{"fa":"General","t":"g"},"v":"dd"}},{"r":0,"c":1,"v":{"m":"dd","ct":{"fa":"General","t":"g"},"v":"dd"}},{"r":0,"c":2,"v":{"m":"b","ct":{"fa":"General","t":"g"},"v":"b"}}] } ] } luckysheet.create(options); $('.sheet-name').append('<a class="btn btn-primary btn-rounded btn-sm" onclick="saveData()"><i class="fa fa-save"></i> 保存数据</a>'); var mytitle=$('.luckysheet-share-logo').attr('title') console.log(mytitle); }) function saveData() { var celldata = (JSON.stringify(luckysheet.transToCellData(luckysheet.getLuckysheetfile()[0].data))); var mytitle=$('.luckysheet-share-logo').attr('title') console.log(mytitle); $.ajax({ url:"/machangwei", data:{"sheetData":celldata,"scheId":0,"title":mytitle}, Type:"post", dataType:"json", success:function(res) { console.log(res); } }); } </script> </html>
from flask import Blueprint,request, render_template, redirect from apps.onlinetable.models import Mysheet from ext import db table_bp=Blueprint('table',__name__) @table_bp.route('/', methods=['POST', 'GET']) def testmytb(): cellData=Mysheet.query.first() print(cellData.content) return render_template('test.html',cellData=cellData) @table_bp.route('/machangwei', methods=['POST', 'GET']) def testmytb1(): print(request.args) sheetData = request.args.get('sheetData') title = request.args.get('title') sd=Mysheet.query.filter(Mysheet.title==title).first() if not sd: sd=Mysheet() # print(sd) sd.title=title sd.content=sheetData db.session.add(sd) db.session.commit() return ''
# ORM 类 ----》 表 # 类对象 ---〉表中的一条记录 from datetime import datetime from ext import db # create table user(id int primarykey auto_increment,username varchar(20) not null,..) class Mysheet(db.Model): # db.Column(类型,约束) 映射表中的列 # ''' 类型: db.Integer int db.String(15) varchar(15) db.Datetime datetime ''' id = db.Column(db.Integer, primary_key=True, autoincrement=True) title=db.Column(db.String(100), nullable=False,default='马昌伟') content = db.Column(db.Text(5000), nullable=False) rdatetime = db.Column(db.DateTime, default=datetime.now) def __str__(self): return self.title
不加safe
渲染会有问题
加上safe。正常渲染
添加数据,点击保存
数据库中有相同标题的,就是修改数据,如果没就是创建数据
其它页面访问,可以访问到。会从数据库中将数据渲染到前端,但是我刚刚调整的单元格宽度并没有保存上