前端excel的实现方案Luckysheet

news2024/12/27 11:05:43

一、介绍

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
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2216343.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

第二十七篇:传输层讲解,TCP系列一

一、传输层的功能 ① 分割与重组数据 传输层也要做数据分割&#xff0c;所以必然也需要做数据重组。 ② 按端口号寻址 IP只能定位数据哪台主机&#xff0c;无法判断数据报文应该交给哪个应用&#xff0c;传输层给每个应用都设置了一个编号&#xff0c;这个编号就是端口&…

大数据毕业设计选题推荐-电影数据分析系统-电影推荐系统-Python数据可视化-Hive-Hadoop-Spark

✨作者主页&#xff1a;IT研究室✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Python…

大模型应用开发:如何在网页中嵌入3D人物

要实现的效果如图所示&#xff1a; 左侧是插入的3D人物&#xff0c;类似AI智能助手的角色。 我们这里是通过React做的。需要用到以下工具或者网站&#xff1a; readyplayer.me/ 自定义3D人物Blender 3维设计软件&#xff0c;3D文件格式转化&#xff0c;主要是fbx和glb的互转w…

【Docker】安装部署项目流程(Pycharm版)

安装部署步骤 1.准备项目 第一步要准备好你所需要部署的项目&#xff0c;确保在工作目录下所以程序.py文件正常调用并能正确运行 如上&#xff0c;main要在工作目录中能跑通&#xff0c;这里有一点需要注意 在IDE src不要标记为源代码根目录&#xff0c;观察一下是否能跑通代…

React国际化中英文切换实现

目录 概况 安装 文件结构 引入 使用 正常使用 传参使用 概况 react-intl-universal 是一个国际化库&#xff0c;专门为 React 应用提供多语言支持。与 React 原生的 react-intl 相比&#xff0c;react-intl-universal 支持从远程服务器加载语言包&#xff0c;动态切换语…

【途牛旅游网-注册/登录安全分析报告】

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 暴力破解密码&#xff0c;造成用户信息泄露短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造成亏损无底洞…

RabbitMQ service is already present - only updating service parameters

Windows下卸载RabbitMQ之后,然后重新注册RabbitMQ服务的时候,报错以下信息: D:\software\rabbitmq-server-4.0.2\rabbitmq_server-4.0.2\sbin>D:\software\rabbitmq-server-4.0.2\rabbitmq_server-4.0.2\sbin\rabbitmq-service.bat install RabbitMQ service is already …

智能时代摩托车一键启动无钥匙进入感受科技前线

向智能化与高性能迈进,技术创新与绿色转型引领摩托车行业智能化出行。 摩托车一键启动无钥匙进入功能是一种先进的车辆控制系统&#xff0c;它允许驾驶员在不使用传统机械钥匙的情况下&#xff0c;通过智能感应技术自动解锁和启动摩托车。这种系统通常包括一个智能钥匙&#x…

第二十八篇:TCP协议概述,TCP系列二

传输控制协议&#xff08;Transmission Control Protocol&#xff0c;TCP&#xff09;是一种面向连接的、可靠的、基于字节流的传输层通信协议。在 TCP 协议中&#xff0c;通过三次握手建立连接。通信结束后&#xff0c;还需要断开连接。如果在发送数据包时&#xff0c;没有正确…

哪款宠物空气净化器性价比高?希喂、米家和范罗士哪款更好?

这次我真的不是很想抱怨&#xff0c;是我男朋友真的很过分&#xff01;真的很过分&#xff0c;差点让我们两个分道扬镳。先听我说&#xff0c;这不是我和他都嫌家里太安静了吗&#xff0c;每天下班后两个人吃完饭就各玩各的手机&#xff0c;生活太无趣了&#xff0c;加上这几年…

前端开发设计模式——状态模式

目录 一、状态模式的定义和特点 二、状态模式的结构与原理 1.结构&#xff1a; 2.原理&#xff1a; 三、状态模式的实现方式 四、状态模式的使用场景 1.按钮的不同状态&#xff1a; 2.页面加载状态&#xff1a; 3.用户登录状态&#xff1a; 五、状态模式的优点 1.提…

vue+element的confirm提示消息文字变色和换行

效果: 思路: 可以考虑采用模板字符串的思路实现 代码: this.confirm(您确定要<b style"Color: red">${text}</b>的数据项&#xff1f;<br/>单位名称: ${row.companyName} <br/>属性: ${row.attributeName}).then(() > {console.log(确定…

一、定时器的时钟来源

计数器的时钟选择8个时钟源&#xff0c;可以分成4类: 一、来自RCC的内部时钟TIMx CLK 二、芯片内部其他定时器的触发输入ITR 使用某一个定时器作为另外一个定时器的分频 ITR1、ITR2、ITR3和ITR4 三、外部时钟源模式1&#xff1a; 外部捕获引脚上的边沿信号 TI1FP…

趋势(一)利用python绘制折线图

趋势&#xff08;一&#xff09;利用python绘制折线图 折线图&#xff08; Line Chart&#xff09;简介 折线图用于在连续间隔或时间跨度上显示定量数值&#xff0c;最常用来显示趋势和关系&#xff08;与其他折线组合起来&#xff09;。折线图既能直观地显示数量随时间的变化…

从零开始在Windows系统上搭建一个node.js后端服务项目

目录 一、下载node.js及配置环境 二、搭建node.js项目及安装express框架 三、集成nodemon&#xff0c;实现代码热部署 四、Express 应用程序生成器 一、下载node.js及配置环境 网上很多安装教程&#xff0c;此处就不再赘述了 版本信息 C:\Users\XXX>node -v v20.15.0…

Go语言基础学习(Go安装配置、基础语法)

一、简介及安装教程 1、为什么学习Go&#xff1f; 简单好记的关键词和语法&#xff1b;更高的效率&#xff1b;生态强大&#xff1b;语法检查严格&#xff0c;安全性高&#xff1b;严格的依赖管理&#xff0c; go mod 命令&#xff1b;强大的编译检查、严格的编码规范和完整的…

微信小程序应用echarts和二维表的结合

1.刚进入页面时&#xff0c;小馋猫图片的位置是由echarts图表的&#xff0c;这个你别管&#xff0c;我有我的难处&#xff0c;是由二维表组成的 当滑动鼠标时&#xff0c;会出现这种情况&#xff0c;echarts图表随着鼠标滑动&#xff0c;位置不固定 3.解决问题&#xff0c;因为…

用manim实现内燃机引擎的活塞,连杆和曲柄的模拟运动【上】

一&#xff0c;介绍 内燃机引擎是现代机械设备中一种非常重要的动力装置&#xff0c;其核心部件包括活塞、连杆和曲柄。活塞在气缸内做往复运动&#xff0c;通过连杆与曲柄相连&#xff0c;将往复运动转化为旋转运动&#xff0c;驱动机械设备正常工作。 活塞是内燃机引擎的关键…

VSCode中的TypeScript教程

TypeScript 是JavaScript的类型化超集&#xff0c;可编译为纯JavaScript。它提供了类、模块和接口来帮助您构建健壮的组件。 安装 TypeScript 编译器 Visual Studio Code 包括 TypeScript 语言支持&#xff0c;但不包括 TypeScript 编译器tsc。您需要在全局或工作区中安装Typ…

【C语言】预编译+编译+汇编+链接

文章目录 翻译环境和运行环境翻译环境预处理&#xff08;预编译&#xff09;编译汇编链接 运行环境 接下来是预处理阶段的一系列知识&#xff0c;认真阅读哦预定义符号#define定义常量#define定义宏带有副作用的宏参数宏替换的规则宏函数的对比#和##命名约定#undef命令行定义条…