请选择 进入手机版 | 继续访问电脑版
 找回密码
 立即注册

QQ登录

只需一步,快速开始

Ellia.Duan SpreadJS 开发认证
超级版主   /  发表于:2025-1-26 10:54  /   查看:40  /  回复:0
本帖最后由 Ellia.Duan 于 2025-1-26 11:04 编辑

在SpreadJS中,有一个方法是autoFitRow()可以对当前行自适应行高,但是一些用户发现,如果我这一行存在合并单元格,autoFitRow()不生效。

那么,我们该怎么处理呢?
SpreadJS有一个getAutoFitHeight()方法可以获取当前单元格的内容需要的高度 。
image.png96981505.png
通过上图,发现单元格的值、文本、样式、当前工作表的缩放系数都会影响单元格的实际高度。
比如存在这么一个单元格,如下图所示。合并单元格的区域从B5开始,3行5列。
image.png653584594.png

思路:
1、b5的列宽调整为B:F列的列宽,
2、取消合并单元格,
3、计算此时B5的实际高度,
4、合并单元格
5、计算后的高度减去剩余两行的高度
6、重置b5的列宽

此时计算出来的高度就是当前合并单元格自适应行高的高度。
但是呢,这个还不够。要对当前行自适应高度,要对所有列的单元格按照上面思路计算最大值后,进行比较。
所以我们要对所有列的单元格按照上述步骤计算出来一个行高最大值,最大值即为我们想要的结果。

讲完对合并单元格的思路 ,再重新思考一下这个问题。
sheet中一行的数据,并不都是合并单元格,如果存在非合并单元格,我们可以调用SpreadJS本身自带的autofitRow方法。那么我们怎么兼容上述两种情况呢。
为此,我们创建一个对整行进行自适应行高的方法autoFitMergeCell。在此方法中,对所有可能的情况进行判断。



  1.    spread.suspendPaint()
  2. spread.sheets.forEach(sheet => {
  3.             let oldZoom = sheet.zoom()
  4.             sheet.zoom(1)
  5.             let {row, rowCount} = sheet.getUsedRange(GC.Spread.Sheets.UsedRangeType['data'])
  6.             for (let i = row; i < row + rowCount; i++) {
  7.                 autoFitMergeCell(sheet, i, oldZoom)
  8.             }
  9.             sheet.zoom(oldZoom)
  10.         })
  11.         spread.resumePaint()</div>
  12.    function autoFitMergeCell(sheet, r, oldZoom) {
  13. }
复制代码

如下上代码所示:
1、添加suspendPaint/resumePaint 暂停/恢复绘画来提升性能。
2、遍历sheet  
3、获取当前sheet的缩放系数
4、重置zoom为1
5、遍历每一行
6、调用autoFitMergeCell,传参sheet,row,zoom(影响行高的因素)来对整个工作表进行自适应行高。

这里对zoom进行设置,是为了排除zoom对getAutoFitHeight()方法的影响。
接下来,我们将在autoFitMergeCell方法中,分三种情况进行讨论:
一、不存在合并单元格
如果不存在合并单元格,则直接调用autoFitRow
  1. function autoFitMergeCell(sheet, r, oldZoom) {
  2.   let allSpans = sheet.getSpans()
  3. //判断当前行是否存在合并单元格
  4. let currentRowSpan = allSpans.filter(item => {
  5.                 if (item.row == r) return item
  6.             })
  7.             //1. 不存在合并单元格,直接autoFitRow
  8.             if (!currentRowSpan.length) {
  9.                 sheet.autoFitRow(r);
  10.                 return
  11.             }
  12. }
复制代码

二、rowCount为1
当前行如果存在合并单元格,且所有的合并单元格rowCount为1,也可以调用autoFitRow。

  1. function autoFitMergeCell(sheet, r,oldzoom) {
  2. ...

  3.     //2. 存在合并单元格,但是都是rowCount都是1,此时也可以直接autoFitRow
  4.             let count = currentRowSpan.filter(item => {
  5.                 if (item.rowCount == 1) {
  6.                     return item
  7.                 }
  8.             })
  9.             if (count.length == currentRowSpan.length) {
  10.                 sheet.zoom(oldZoom);
  11.                 sheet.autoFitRow(r);
  12.                 sheet.zoom(1);
  13.                 return
  14.             }
  15. }
复制代码

三、rowCount为n
此种情况,如上文提到的合并单元格自适应行高的思路,
  1. function autoFitMergeCell(sheet, r, oldZoom) {
  2.           ...
  3.             //3.1 存在合并单元格,且rowCount >1 , 计算行高最大值
  4.             let maxHeight = sheet.defaults.rowHeight
  5.             var instance = new GC.Spread.Sheets.CellTypes.Text();
  6.             let map = {}

  7.             for (let i = 0; i < currentRowSpan.length; i++) {
  8.                 let item = currentRowSpan<i>
  9.                 const {row, col, rowCount, colCount} = item
  10.                 //考虑多列的情况,将合并列的列宽放在第一列,计算后再重置
  11.                 let firstColWidth = 0, oldWidth = sheet.getColumnWidth(col);
  12.                 for (let i = col; i < col + colCount; i++) {
  13.                     firstColWidth += sheet.getColumnWidth(i);
  14.                     map<i> = true
  15.                 }
  16.                 sheet.setColumnWidth(col, firstColWidth)
  17.                 sheet.removeSpan(item.row, item.col);
  18.                 var returnValue = instance.getAutoFitHeight(
  19.                     sheet.getValue(row, col),
  20.                     sheet.getText(row, col),
  21.                     sheet.getActualStyle(row, col),
  22.                     sheet.zoom(),
  23.                     {
  24.                         "sheet": sheet,
  25.                         "row": row,
  26.                         "col": col,
  27.                         "sheetArea": GC.Spread.Sheets.SheetArea.viewport
  28.                     });
  29.                 sheet.addSpan(item.row, item.col, item.rowCount, item.colCount);
  30.                 for (let i = row + 1; i < row + rowCount; i++) {
  31.                     returnValue -= sheet.getRowHeight(i)
  32.                 }
  33.                 sheet.setColumnWidth(col, oldWidth)

  34.                 if (returnValue > maxHeight) {
  35.                     maxHeight = returnValue
  36.                 }
  37.             }
  38.             //3.2 此行存在合并单元格,也存在不合并单元格,计算不合并单元格的行高最大值
  39.             for (let i = 0; i < sheet.getColumnCount(); i++) {
  40.                 if (!map<i> && sheet.getValue(r, i)) {
  41.                     let row = r, col = i;
  42.                     var oldSpan = sheet.getSpan(row,col);
  43.                     if(oldSpan){
  44.                         sheet.removeSpan(row,col);
  45.                     }
  46.                     var returnValue = instance.getAutoFitHeight(
  47.                         sheet.getValue(row, col),
  48.                         sheet.getText(row, col),
  49.                         sheet.getActualStyle(row, col),
  50.                         sheet.zoom(),
  51.                         {
  52.                             "sheet": sheet,
  53.                             "row": row,
  54.                             "col": col,
  55.                             "sheetArea": GC.Spread.Sheets.SheetArea.viewport
  56.                         });
  57.                     if(oldSpan){
  58.                         sheet.addSpan(oldSpan.row,oldSpan.col,oldSpan.rowCount,oldSpan.colCount)
  59.                     }
  60.                     if (returnValue > maxHeight) {
  61.                         maxHeight = returnValue
  62.                     }
  63.                 }
  64.             }
  65.             sheet.setRowHeight(r, maxHeight)
  66.         }
复制代码




完整代码请参考附件:
合并单元格自适应_designer.html (7.57 KB, 下载次数: 0)

0 个回复

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