找回密码
 立即注册

QQ登录

只需一步,快速开始

KevinChen 讲师达人认证 悬赏达人认证 SpreadJS 开发认证
论坛元老   /  发表于:2020-6-30 16:51  /   查看:4502  /  回复:0
有很多小伙伴对SpreadJS没有原生支持格式刷功能而纠结,实际上已经有了非常接近Excel的实现,
本文就来为大家分析一下这个功能是如何实现的,以及提供一个封装好的格式刷功能模块。

一、格式刷的实现:
关于格式刷的实现,需要处理的几个问题点如下:
1、选择边界问题;
当用户选中某个单元格或区域作为源格式区域,再选中一块可能大小不等,甚至重叠的区域,
这时需要怎样处理边界问题,就是我们首先要考虑的。

2、跨sheet问题;
在SpreadJS中,有个copyTo的方法可以实现样式的拷贝,但我们试过就会发现,它不支持跨sheet复制样式,
实际上,SpreadJS提供了一个命令:GC.Spread.Sheets.Commands.clipboardPaste,通过这个命令,
不仅可以实现跨sheet拷贝样式,还支持更加灵活的区域样式拷贝(无需像copyTo一样一对一拷贝range)

3、能否撤销;
在SpreadJS中,所有用户操作都被抽象成一个个的命令(Command),command可以支持撤销、
重做等行为。关于Command的使用方法,参考:
https://www.grapecity.com.cn/blogs/how-to-use-spreadjs-built-in-commands-and-custom-commands

理清楚以上可能遇到的问题,我们就可以着手实现格式刷的功能了.

二、格式刷的实现

1、选择边界处理和跨Sheet实现:

  1. var targetSheet = me.workbook.getActiveSheet();
  2. var source = me.getActualRange(me.sourceSheet, me.sourceRange);
  3. var target = me.getActualRange(targetSheet, targetSheet.getSelections().pop());

  4. // 仅选一个目标单元格时将按源尺寸复制
  5. if (target.rowCount === 1 && target.colCount === 1) {
  6.         target.rowCount = Math.min(source.rowCount, targetSheet.getRowCount() - target.row);
  7.         target.colCount = Math.min(source.colCount, targetSheet.getColumnCount() - target.col);
  8. }

  9. var targetEndRow = target.row + target.rowCount;
  10. var targetEndCol = target.col + target.colCount;
复制代码

  1. getActualRange: function (sheet, range) {
  2.         var isFullRow = range.col === -1;
  3.         var isFullCol = range.row === -1;
  4.         return new GC.Spread.Sheets.Range(isFullCol ? 0 : range.row, isFullRow ? 0 : range.col,
  5.                 isFullCol ? sheet.getRowCount() : range.rowCount, isFullRow ? sheet.getColumnCount() : range.colCount);
  6. }
复制代码


2、clipboardPaste命令调用:


  1. GC.Spread.Sheets.Commands.clipboardPaste.execute(me.workbook, {
  2.         // 目标sheet的名称
  3.         sheetName: targetSheet.name(),
  4.         // 源sheet
  5.         fromSheet: me.sourceSheet,
  6.         // 源区域
  7.         fromRanges: [new GC.Spread.Sheets.Range(source.row, source.col, copyRows, copyCols)],
  8.         // 目标区域
  9.         pastedRanges: [new GC.Spread.Sheets.Range(row, col, copyRows, copyCols)],
  10.         // 是否剪切
  11.         isCutting: false,
  12.         clipboardText: "",
  13.         // 复制内容(样式)
  14.         pasteOption: GC.Spread.Sheets.ClipboardPasteOptions.formatting
  15. }, false);
复制代码


三、模块化封装

感谢@GoodGod 同学的分享,对于这个功能模块他做了大量的优化、封装工作。
希望大家多多分享自己的经验,大家相互学习,共同进步!

现在的前端应用越来越讲究模块化,针对这个相对独立的小功能,最好的办法就是把它封装成一个“类”,
在需要的地方将它“实例化”,然后执行调用,管理状态。

对于这个纯功能的案例,模块化相对简单,重写它的prototype即可(当然利用新特性也可以声明class)
参考代码:

  1. var FormatPainter = function (workbook) {
  2.         this.construct(workbook);
  3. };
  4. FormatPainter.prototype = {
  5.         //功能定义
  6. };
复制代码


完整代码示例参考附件。

FormatPainterDemoLikeExcel.html

10.13 KB, 下载次数: 270

0 个回复

您需要登录后才可以回帖 登录 | 立即注册
返回顶部