背景:SpreadJS区域快照不支持渲染单元格溢出,对于引用区域存在文本溢出单元格的情况,区域快照仅能显示单元格宽度范围内的字符宽度。
问题原帖:https://gcdn.grapecity.com.cn/forum.php?mod=viewthread&tid=235832
如图1所示,Sheet1中A2单元格中的长文本“君不见,黄河之水天上来,奔流到海不复回。”,A4单元格数据为长文本“君不见,高堂明镜悲白发,朝如青丝暮成雪。”。引用单元格区域A1:O5的区域快照中,相对于单元格A2和A4的位置,仅能显示首个完整字符”君“。
图1. 单元格长文本溢出显示
因为A2和A4单元格所在列宽为20,如图2所示,而长文本“君不见,黄河之水天上来,奔流到海不复回。”据测量结果显示,在默认字体、字号和默认样式下,这段长文本的每个字的宽度总和约为293,如图3所示。很显然,20比293更小,不足以容纳。
图2. A1单元格列宽
图3. 长文本总字宽
面对此情此景,可以在设计sheet时,对需要作为区域快照引用的单元格区域中的长文本所在单元格设置自适应列宽或者合并右侧相邻的空单元格,以扩大单元格宽度,确保单元格宽度大于等于长文本总字宽。
然而,如果使用的是历史文件,且文件数量较多,手动操作的工作量更大,效率较低。为此,可通过代码自动化实现批量处理,核心思路是计算长文本的总宽度,并在文本总宽度大于单元格宽度时调整单元格结构。
Designer事件FileLoaded在文件成功导入后被触发,在此时完成对文件的初始化操作。那么,便可在此对长文本溢出单元格合并右侧相邻的空单元格,或者自适应列宽。
在这个处理过程中,关键点在于如何判断当前单元格中是否出现了长文本溢出的现象。我们知道对比长文本总字宽和单元格列宽即可,且Worksheet:getColumnWidth()即可获取单元格列宽。
在SpreadJS中,普通单元格类型为Text,单元格类型基类声明了两个接口Base:getAutoFitHeight()和Base:getAutoFitWidth()用以根据单元格的实际样式、实际数据计算其中字符的总字宽。
那么,对比发现单元格宽度小于其中文本总字宽时,向右侧寻找足够数量单元格进行合并,确保合并后所得的单元格宽度大于等于文本总字宽,这样便可以在单元格中显示完整的长文本字符串。
以合并单元格的策略为例,完整思路如下:
1. 事件监听:对Designer实例绑定FileLoaded事件,或者自定义导入功能,在Workbook:import()的成功回调函数中,在成功导入文件后立即触发自动化处理逻辑。
2. 文本溢出检测:
2.1. 跳过合并单元格:对当前单元格,如果Worksheet:getSpans()所得结果为合并单元格,则跳过当前单元格所在的整个合并单元格。参考如下代码:
- // 跳过已存在的合并单元格
- if (checkSpan(sheet, i, j) != j) {
- j = checkSpan(sheet, i, j);
- continue;
- }
- /**
- * 判断单元格是否在合并单元格中
- */
- function checkSpan(sheet, row, col) {
- var span = sheet.getSpans(new GC.Spread.Sheets.Range(row, col, 1, 1));
- if (span && span.length >= 1) {
- col = span[0].col + span[0].colCount - 1;
- }
-
- return col;
- }
复制代码 2.2. 计算文本实际宽度:通过Text:getAutoFitColumn()获取长文本的实际总字宽,记为TextWidth。参考如下代码:
- /**
- * 获取长文本的字宽
- */
- function getTextWidth(textCell, sheet, row, col) {
- var width = textCell.getAutoFitWidth(sheet.getValue(row, col),
- sheet.getText(row, col),
- sheet.getActualStyle(row, col),
- sheet.zoom(),
- {
- 'sheet': sheet,
- 'row': row,
- 'col': col,
- 'sheetArea': GC.Spread.Sheets.SheetArea.viewpoprt
- });
- return width;
- }
复制代码 2.3. 获取单元格宽度:通过Worksheet:getColumnWidth()获取单元格当前的实际宽度,记为CellWidth。
2.4. 合并单元格:轮询单元格右侧的单元格,每次获取当前单元格的宽度,并将其累加至CellWidth,对比CellWidth是否大于等于TextWidth,这意味着通过Worksheet:addSpan()合并这些单元格即可令长文本完整显示在合并单元格中。参考如下代码:
- /**
- * 处理单元格合并
- */
- function processSpan(sheet, row, col, width) {
- var startCol = col;
- // 当前单元格宽度,在此基础上累加相邻单元格宽度,直至宽度累加和大于等于文本长度
- var colWidthSum = sheet.getColumnWidth(col);
- while (colWidthSum < width) {
- startCol += 1;
- colWidthSum += sheet.getColumnWidth(startCol);
- }
- // 合并单元格
- sheet.addSpan(row, col, 1, startCol - col + 1);
- return startCol;
- }
复制代码 3. 批量处理:重复步骤2处理区域快照中待引用区域中的每一个单元格,完成单元格合并。
如图4所示,导入包含长文本溢出单元格的ssjson文件,上述流程处理后,可见区域快照能够完全一比一同步引用区域。
图4. 合并单元格以完整显示长文本
同理,对于自适应列宽的策略,只需要在处理过程中用自适应列宽替代单元格合并过程即可。附上合并单元格策略demo,以供参考。
|
|