本帖最后由 Winny 于 2022-7-28 17:26 编辑
需求背景:在本地使用Excel时,经常会有需要在Excel中添加一些附件文件的需求,例如在Excel中附带一些Word,CAD图等等。Excel能支持这些文件的添加,本质上并不是Excel可以直接打开这些文件。而是由于我们本机已经安装了能打开这些文件的软件。关于Excel中上传附件文件可以参考:在Excel电子表格中插入对象。
类比到Web端,也会有不少客户,希望能够在Spread中添加一个附件。但是Web端不必本地环境,无法直接打开Word等其它附件。但是在Excel中,也有一种通过链接的形式来显示附件的方式。而SpreadJS中也是提供超链接的形式,利用这一点,或许可以对SpreadJS添加附件展开探索。
解决方案:
SpreadJS中提供了三种超链接的形式,分别是:
(1)超链接单元格;
(2)超链接类型;
(3)HYPERLINK函数
超链接类型与HYPERLINK函数与Excel兼容,而超链接单元格从SpreadJS导出Excel时,由于实现机制有差异,Excel无法识别,所以实现附件需求尽量使用超链接类型或HYPERLINK函数,我在这里使用的是超链接类型。
在需要在某个单元格中上传附件时,我们可以弹出一个模态框,在模态框中上传文件,点击提交之后,可以对文件做一个暂存,将文件信息存储在单元格的Tag中。Tag在SpreadJS当中可以理解为是对单元格的一种属性标记,可以支持复杂类型。在这里我存储的是一个json,json结构如下:
- {
- type: 'attachfile',
- fileInfo: object file
- }
复制代码 其中type表示当前是否为附件,fileInfo代表的是文件对象。由于我演示的是纯前端的demo,所以fileInfo中传递的是File对象,File对象在实际使用时需要从os中在我读取文件,这种形式在传前端的demo演示下可行。但在实际项目中,fileInfo应该使用的是文件上传完成后的路径地址,这一点在实际项目中一定要注意!同时需要将单元格设置为超链接,超链接的url为一个相对路径。至于为何是相对路径,这一点是为了后续导出文件后能正常访问到附件文件,与Excel中的机制相同。对同一个单元格重复上传附件时会做文件的替换,此时我们只需要对应的去修改Tag及超链接的信息即可。与此对应,清除附件文件,只需要清除对应的Tag和值信息即可。接下来会将一些核心的代码逻辑。
1. 创建页面的HTML结构
- <button id="uploadAttach">上传附件</button>
- <div id="fileOperate" style="visibility: hidden;position: absolute;top: 100px;left: 300px;z-index: 10; background-color: #eee;padding: 16px">
- <label for="choseFile">选择文件</label>
- <input type="file" id="choseFile" name="choseFile"/>
- <button id="submit">提交</button>
- <button id="cancel">取消</button>
- </div>
- <div id="ss" style="width:100%;height:98vh;border:1px solid darkgray"></div>
复制代码 点击上传附件文件,id为fileOperate的div会显示出来,在这里可以完成文件的上传及暂存。
2. 暂存附件信息
- function hasAttachFile(sheet,row,col,file){
- /**
- * 附件文件暂存
- * 这里由于没有服务端,所以我直接存了File对象,但File对象只有在实际使用时才会去获取实际的文件内容。在demo中可行
- * 在实际项目中,需要将file对象上传到文件服务器中
- * 上传完成后tag中的fileInfo应该代表的是文件的访问地址,而不能再是File对象。
- */
- sheet.setValue(row,col,file.name)
- sheet.setTag(row,col,{
- type: hyerlinkType,
- fileInfo: file // 实际项目中fileInfo应该为上传完成文件的访问路径
- })
- sheet.setHyperlink(row, col, {
- url: file.name,
- linkColor: '#0066cc',
- visitedLinkColor: '#3399ff',
- drawUnderline: true,
- command:'downloadAttachFile',
- }, GC.Spread.Sheets.SheetArea.viewport);
- }
复制代码 这一步起始主要用来设置文件上传之后单元格超链接及tag信息。细心的同学会注意到,这里我注册了一个命令,超链接本身会有一个跳转的行为,写command之后,会阻止这个默认跳转,转去执行对应的命令。注册的命令主要就是用来做附件文件的下载。关于SpreadJS中如何注册命令可以在学习指南或API中检索。
- // 下载文件
- spread.commandManager().register("downloadAttachFile",{
- canUndo: false,
- execute: function(context,options,isUndo){
- let sheet = context.getActiveSheet()
- let row = sheet.getActiveRowIndex()
- let col = sheet.getActiveColumnIndex()
- let cellTag = sheet.getTag(row,col)
- console.log(sheet,row,col,cellTag)
- if(cellTag && cellTag.type==hyerlinkType){
- /***
- * 纯前端demo,文件存在于本地,fileInfo中存储的是File对象,可以直接获取到文件
- * 实际项目中,fileInfo应该是上传到文件服务器上的文件访问地址。
- * 因此这里需要发送请求,先获取文件blob,将获取的blob传递到saveAs的第二个参数中。
- */
- saveAs(cellTag.fileInfo,cellTag.fileInfo.name)
- }
- }
- })
复制代码 在这里,我引入了三方组件库FileSaver,在点击超链接单元格时,可以支持当前附件文件的下载。
3. 附件文件清除
- document.getElementById("removeAttach").onclick = function(){
- /***
- * 清除附件
- * 清除附件需要先删除远程文件服务器的文件,之后清除单元格的Tag信息。
- * 这里前端演示demo,只删除了tag。
- * 实际项目中tag中的fileInfo应该是文件上传后的路径
- */
- let sheet = spread.getActiveSheet()
- let row = sheet.getActiveRowIndex()
- let col = sheet.getActiveColumnIndex()
- spread.commandManager().execute({
- cmd:"removeAttachFile",
- sheet,row,col
- })
- }
复制代码
4. 文件保存
SpreadJS提供了一种结构叫做SSJSON,用来描述一个Excel文件的全部信息。也提供了文件blob的形式,但由于导出文件流之后Tag信息会清除,因为Excel中并没有Tag的概念。所以对于当前的形式,需要将文件保存成json结构。如果有必须保存excel文件的需求,我们可以将文件信息保存在Excel与SpreadJS都能兼容的属性中。
- document.getElementById("fileSaver").onclick = function(){
- // 保存文件
- submitFile = spread.toJSON()
- spread.clearSheets()
- spread.addSheet(0)
- }
复制代码 因为是一个纯前端的demo,这里我用一个全局变量来表示当前保存的文件。
5. 文件加载
- document.getElementById("loadSubmitFile").onclick = function(){
- // 加载已保存文件
- spread.fromJSON(submitFile)
- }
复制代码
详细的Demo可以参考:SpreadJS上传附件。
|
|