SpreadJS是葡萄城结合 40 余年专业控件技术和在电子表格应用领域的经验而推出的纯前端表格控件。作为一个类Excel控件,SpreadJS如何实现当前比较流行的表格协同呢?本篇文章将简单介绍一下。

首先,从框架搭建上,本篇示例采用当下流行的前后端分离的开发方式,前端使用npm作为脚手架搭建Svelte框架。 后端使用Java的SpringBoot作为后端框架。前端使用SpreadJS V15.2.5以及SpreadJS在线表格编辑器Designer为前端操作的平台后端使用GCExcel作为文档的终端处理,随时提供备份与恢复。

首先,介绍下在前端Svelte框架下搭建SpreadJS在线表格编辑器。

1、在pageage.json文件中引入相关SpreadJS资源

 "@grapecity/spread-excelio": "15.2.5",
"@grapecity/spread-sheets": "15.2.5",
"@grapecity/spread-sheets-barcode": "15.2.5",
"@grapecity/spread-sheets-charts": "15.2.5",
"@grapecity/spread-sheets-designer": "15.2.5",
"@grapecity/spread-sheets-designer-resources-cn": "15.2.5",
"@grapecity/spread-sheets-languagepackages": "15.2.5",
"@grapecity/spread-sheets-pdf": "15.2.5",
"@grapecity/spread-sheets-pivot-addon": "15.2.5",
"@grapecity/spread-sheets-pivots": "^14.0.0",
"@grapecity/spread-sheets-print": "15.2.5",
"@grapecity/spread-sheets-resources-zh": "15.2.5",
"@grapecity/spread-sheets-shapes": "15.2.5",
"@grapecity/spread-sheets-tablesheet": "15.2.5",

2、然后,集成在线表格编辑器Svelte组件版。在上一篇文章中,我们介绍了如何在Svelte框架中实现在线表格编辑器。

我们按照此思路新建一个SpreadSheet.svelte文件,写入基础在线表格编辑器。

<script>
import {onMount} from 'svelte';
import '@grapecity/spread-sheets-print';
import "@grapecity/spread-sheets-charts";
import '@grapecity/spread-sheets-shapes';
import '@grapecity/spread-sheets-pivot-addon';
import '@grapecity/spread-sheets-tablesheet';
import '@grapecity/spread-sheets-designer-resources-cn';
import '@grapecity/spread-sheets-designer';
import * as GC from '@grapecity/spread-sheets';
import * as GCDesigner from '@grapecity/spread-sheets-designer'; let designer = null;
onMount(async () => {
designer = new GCDesigner.Spread.Sheets.Designer.Designer(document.getElementById("designerHost"));
let spread = designer.getWorkbook();
}); </script>
<div id="designerHost" class="designer-host"></div> <style scoped>
@import "@grapecity/spread-sheets-designer/styles/gc.spread.sheets.designer.min.css";
@import '@grapecity/spread-sheets/styles/gc.spread.sheets.excel2013white.css'; .designer-host {
width: 100%;
height: 100vh;
} </style>

3、协同文档可能不止一个,我们需要在页面上创建一个文档列表,来允许用户选择编辑哪个文档,所以我们需要创建一个文档列表页面OnlineSheets.svelte。在此页面中,我们要实现路由跳转,和加载文档数据。

这里我们用了svelte-spa-router进行路由跳转 与isomorphic-fetch进行前后端数据传输。

<script>
import {onMount} from 'svelte';
import { link } from "svelte-spa-router";
import {Utility} from "../utility.js"; let docList = [];
onMount(async () => {
Utility.getDocList().then(result => {
docList = result.map((item,index)=>{
return {
path:'/Spreadsheet/' + item.substring(0, item.lastIndexOf('.')),
index,
fileName:item
}
})
});
});
</script>
<main class="main">
<table className='table' aria-labelledby="tabelLabel">
<thead>
<tr>
<th>Document</th>
<th></th>
</tr>
</thead>
<tbody>
{#each docList as docItem}
<tr>
<td>{docItem.index}</td>
<td>{docItem.fileName}</td>
<td className='row'>
<a use:link={docItem.path}> Open</a>
</td>
</tr>
{/each}
</tbody>
</table>
</main>

以上代码实现了文档列表查看与文档跳转,使用Open将跳转至前面设计好的在线表格编辑器中。

至此,前端的相关内容就准备好了,接下来搭建下后端工作。

后端的准备工作,首先安装gradle作为包管理器。当然,这里也可以用其他工具来代替,例如maven,或者源生引入jar包的方式将需要用到的jar包引入进来。之后创建springboot工程配合搭建gradle引用GCExcel以及后面协同需要用到的websocket。

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<version>2.4.3</version>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
<version>2.4.3</version>
</dependency> <dependency>
<groupId>com.grapecity.documents</groupId>
<artifactId>gcexcel</artifactId>
<version>4.0.3</version>
</dependency> <dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.6</version>
</dependency> <dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency> <dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<version>10.0.2</version>
</dependency> <dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<version>2.5.0</version>
</dependency>
</dependencies>

这样子,我们做了框架的基本环境搭建,接下来我们介绍下如何搭建webSocket。

在SpreadSheet.svelte文件中写入如下代码建立webSocket链接:

   function connectDocument(docName) {
if (webSocket != null) {
return;
}
var ws = new WebSocket(Utility.webSocketUrl); //'ws://localhost:8090/spreadjs'
ws.onopen = function () {
var data = {
cmd: "connect",
docID: docName
}
ws.send(JSON.stringify(data));
}
ws.onmessage = onmessage;
webSocket = ws;
}

接下来我们访问下文档列表页,从文档列表页跳转进入文档,进行编辑。

接下来我们需要监听前端发出的操作。这里因为在线表格编辑器本身将所有用户可能做的操作全部做了封装,所以省下了很多的功夫。

 onMount(async () => {
//初始化Designer
designer = new GCDesigner.Spread.Sheets.Designer.Designer(document.getElementById("designerHost"));
let spread = designer.getWorkbook();
//fromJSON
openDocument(docName);
//建立webSocket
connectDocument(docName);
var cm = spread.commandManager();
cm.addListener('myListener', onCommandExecute)
});

根据cmd去判断并且对命令再做一些简单封装,之后将封装过的命令发到服务端,之后通过websocket发同步指令:

function onCommandExecute(args) {
console.log(args.command);
var command = args.command;
var ServerCommand = null; switch (command.cmd) {
case Utility.ServerCommands.EditCell:
ServerCommand = {
sheetName: command.sheetName,
row: command.row,
column: command.col,
newValue: command.newValue
}
break;
case Utility.ServerCommands.ResizeRow:
ServerCommand = {
sheetName: command.sheetName,
rows: command.rows,
size: command.size
};
break;
case Utility.ServerCommands.ResizeColumn:
ServerCommand = {
sheetName: command.sheetName,
columns: command.columns,
size: command.size
};
break;
case 'Designer.' + Utility.ServerCommands.SetFontFamily:
case 'Designer.' + Utility.ServerCommands.SetFontSize:
case 'Designer.' + Utility.ServerCommands.SetBackColor:
case 'Designer.' + Utility.ServerCommands.SetForeColor:
case 'Designer.' + Utility.ServerCommands.SetFontWeight:
case 'Designer.' + Utility.ServerCommands.SetFontStyle:
case 'Designer.' + Utility.ServerCommands.SetUnderline:
case 'Designer.' + Utility.ServerCommands.SetDoubleUnderline:
if (command.value && command.value.indexOf('undefined') === -1) {
ServerCommand = {
sheetName: command.sheetName,
selections: command.selections,
value: command.value
}
}
break;
case Utility.ServerCommands.MoveFloatingObjects:
ServerCommand = {
sheetName: command.sheetName,
floatingObjects: command.floatingObjects,
offsetX: command.offsetX,
offsetY: command.offsetY
};
break;
case Utility.ServerCommands.ResizeFloatingObjects:
ServerCommand = {
sheetName: command.sheetName,
floatingObjects: command.floatingObjects,
offsetX: command.offsetX,
offsetY: command.offsetY,
offsetWidth: command.offsetWidth,
offsetHeight: command.offsetHeight
};
break;
case Utility.ServerCommands.InsertColumns:
case Utility.ServerCommands.InsertRows:
ServerCommand = {
sheetName: command.sheetName,
selections: command.selections
};
break;
default:
} if (ServerCommand != null) { var cmd = command.cmd;
var dotIndex = cmd.lastIndexOf('.');
if (dotIndex !== -1) {
cmd = cmd.substring(dotIndex + 1);
}
ServerCommand.cmd = cmd;
ServerCommand.docID = params.fileName; Utility.ExecuteCommandAtServer(ServerCommand); command.docID = ServerCommand.docID;
webSocket.send(JSON.stringify(command))
}
}

当协同端通过websocket接收到请求的时候,使用onmessage方法做同步命令。这里在协同端执行command之前需要先撤销之前的监听,避免再发送websocket导致死循环。在执行之后,再次添加监听。

 function onmessage(message) {
var command = JSON.parse(message.data);
command._styles = null;
let spread = designer.getWorkbook()
var cm = spread.commandManager();
cm.removeListener('myListener'); spread.commandManager().execute(command); cm.addListener('myListener', onCommandExecute);
}

至此,协同基础内容搭建结束,我们来看看编辑单元格内容后,发生了什么吧。

如下图所示,修改E4单元格内容,同时打开控制台网络tab。

将E4单元格数值2500改为2000,此时触发了EditCell事件,同时发出了交互指令:

![](https://img2023.cnblogs.com/blog/139239/202302/139239-20230214171707564-1725613752.png)

此时新建一个窗口,复制链接,查看文档内容已经变为了2000。
如下动图所示:
![](https://img2023.cnblogs.com/blog/139239/202302/139239-20230214171722569-698427034.gif) 以上就是Svelte框架结合SpreadJS实现表格协同文档的方法,如果您想体验更多功能或免费下载试用SpreadJS,欢迎访问葡萄城官网。

Svelte框架结合SpreadJS实现表格协同文档的更多相关文章

  1. Svelte框架实现表格协同文档

    首先,从框架搭建上,本篇示例采用当下流行的前后端分离的开发方式,前端使用npm作为脚手架搭建Svelte框架. 后端使用Java的SpringBoot作为后端框架. 首先,介绍下在前端Svelte框架 ...

  2. atitit。获取表格的字段注释metadata的原理以及AND 字段表格描述文档方案

    atitit.获取表格的字段注释metadata的原理以及AND 字段表格描述文档方案 1. 通过sql ide navicate获取(推荐)通过meatadata数据库获取 1 2. 通过代码获取 ...

  3. Spring Boot从入门到精通(十一)集成Swagger框架,实现自动生成接口文档

    Swagger是一个规范和完整的框架,用于生成.描述.调用和可视化 RESTful 风格的 Web 服务.Swagger 是一组开源项目,其中主要要项目如下: Swagger-tools:提供各种与S ...

  4. Jquery框架1.选择器|效果图|属性、文档操作

    1.JavaScript和jquery的对比 书写繁琐,代码量大 代码复杂 动画效果,很难实现.使用定时器 各种操作和处理 <!DOCTYPE html> <html lang=&q ...

  5. 基于WPF系统框架设计(5)-Ribbon整合Avalondock 2.0实现多文档界面设计(二)

    AvalonDock 是一个.NET库,用于在停靠模式布局(docking)中排列一系列WPF/WinForm控件.最新发布的版本原生支持MVVM框架.Aero Snap特效并具有更好的性能. Ava ...

  6. 从零开始编写自己的C#框架(4)——文档编写说明

    在写本系列的过程中,了解得越多越不知道从哪里做为切入点来写,几乎每个知识点展开来说都可以写成一本书.而自己在写作与文档编写方面来说,还是一个初鸟级别,所以只能从大方面说说,在本框架开发所需的范围内来讲 ...

  7. 理解MFC 文档、视图、框架[转]

    理解文档/视图框架                                      出处.雷神 了解文档和视图的相互作用关系是编写MFC程序的基本功.但是MFC的应用程序框架把文档和视图之间 ...

  8. MFC文档、视图和框架

    文档.视图.框架 文档/视图结构是MFC提供的一种不错的设计,它将数据的处理和显示分开来,这样更便于我们对程序的维护和扩展. 文档        文档对象用于管理和维护数据,包括保存数据.取出数据以及 ...

  9. 将表格添加到Word文档中 ,包括表格样式设置

    创建 Table 对象并设置其属性 在您将表格插入文档之前,必须创建 Table 对象并设置其属性. 要设置表格的属性,请创建TableProperties对象并为其提供值. TablePropert ...

  10. 2018-10-04 [日常]用Python读取word文档中的表格并比较

    最近想对某些word文档(docx)的表格内容作比较, 于是找了一下相关工具. 参考Automate the Boring Stuff with Python中的word部分, 试用了python-d ...

随机推荐

  1. 渗透测试中遇到的Adminer任意文件读取漏洞

    渗透测试中遇到的Adminer任意文件读取漏洞 免责声明: 软件简介 漏洞原理 漏洞复现 字典脚本 直接输入文件读取脚本 直接输入文件绝对路径读取脚本使用方法 字典脚本使用方法 免责声明: 免责声明: ...

  2. Window使用PowerShell改文件时间戳

    We cross infinity with every step; we meet eternity in every second. 我们每一步都跨过无穷,每一秒都遇见永恒. Window使用Po ...

  3. 说一下 ArrayDeque 和 LinkedList 的区别?

    大家好,我是小彭. 在上一篇文章里,我们聊到了基于链表的 Queue 和 Stack 实现 -- LinkedList.那么 Java 中有没有基于数组的 Queue 和 Stack 实现呢?今天我们 ...

  4. ValueError: Detected newline in header value. This is a potential security problem

    原因 flask框架进行重定向的url中包含 换行符\n或\r 解决方法 使用 strip() 函数去除行首或行尾的换行符(如果你url中间包含这些符号replace函数替换, 但是如果中间包含只能说 ...

  5. 关于linux fcitx输入法候选词中含有省略号的问题解决

    前言 这几天舍弃了 sogou 输入法,换上了google拼音输入法,因为我在纯文本终端调用中文输入法,搜狗显示出来的是加密的,候选词都是加密的,很烦这种 问题原因 这个问题主要是因为 云拼音 模块凉 ...

  6. 初次邂逅 EasyExcel

    前言 由于工作原因,有这种需求,就是把数据库中的数据导出成 Excel 表格,同时,也得支持人家用 Excel 表格导入数据到数据库.当前项目也是在用 EasyExcel,所以我不得不学啦! 以前学习 ...

  7. 各类数据库写入Webhsell总结

    1.MySQL写入WebShell 1.1写入条件 数据库的当前用户为ROOT或拥有FILE权限: 知道网站目录的绝对路径: PHP的GPC参数为off状态: MySQL中的secure_file_p ...

  8. 【离线数仓】Day03-系统业务数据仓库:数仓表概念、搭建、数据导入、数据可视化、Azkaban全调度、拉链表的使用

    一.电商业务与数据结构简介 1.业务流程 2.常识:SKU/SPU SKU=Stock Keeping Unit(库存量基本单位).现在已经被引申为产品统一编号的简称,每种产品均对应有唯一的SKU号. ...

  9. Android-helloword

    环境早已配置完毕,就是后来选择API的时候出现了一点问题,唉,追求时尚,选择最新版本的API,结果就悲剧了,跑不起来,也找不到原因.后来换成Android 4.22 17API Level就行了... ...

  10. 视图 触发器 事务 MVCC 存储过程 MySQL函数 MySQL流程控制 索引的数据结构 索引失效 慢查询优化explain 数据库设计三范式

    目录 视图 create view ... as 触发器 简介 创建触发器的语法 create trigger 触发器命名有一定的规律 临时修改SQL语句的结束符 delimiter 触发器的实际运用 ...