发表于 2022-7-14 12:40:56

spreadjs 换行问题(SJS-4589)

本帖最后由 Derrick.Jiao 于 2022-8-1 09:44 编辑

上次的问题 spreadjs 自定义 cellType 问题https://gcdn.grapecity.com.cn/fo ... 99307&fromuid=63067
(出处: 葡萄城产品技术社区)

针对spreadjs 换行做了cellType 更换,但是者只针对图通文本,如果要修改富文本的格式要怎么处理

Derrick.Jiao 发表于 2022-7-14 14:52:43

你好,富文本换行可以参考附件的demo通过/n/r换行。若仍未符合需求,可以提供对应demo以及描述详细需求,这边来做详细调研。

发表于 2022-7-14 17:28:54

Derrick.Jiao 发表于 2022-7-14 14:52
你好,富文本换行可以参考附件的demo通过/n/r换行。若仍未符合需求,可以提供对应demo以及描述详细需求,这 ...

/******************************** 单元格文本换行,重写 Tex 的 paint 方法 ********************************/
function AutoWrapTextCellType() {
}

AutoWrapTextCellType.prototype = new GC.Spread.Sheets.CellTypes.Text();
AutoWrapTextCellType.prototype.paint = function (ctx, value, x, y, w, h, style, context) {
    ctx.font = style.font;
    value = wrapString(ctx, value, w - 2);
    GC.Spread.Sheets.CellTypes.Text.prototype.paint.apply(this, );
};
function wrapString(c, str, maxWidth) {
    if(typeof str == 'object' && str['richText']){
      return wrapRichTextString(c, str, maxWidth);
    }
    return wrapTextString(c, str, maxWidth)
}

/**
* 对普通文本进行换行
* @param c
* @param str
* @param maxWidth
* @returns {string|*}
*/
function wrapTextString(c, str, maxWidth){
    let width = c.measureText(str).width;
    if (width <= maxWidth) return str;
    const len = str.length;
    let newStrList = [];
    let index = 0;
    for (let i = 0; i < len; i++) {
      // 临时拼接字符串
      let _newStr = newStrList + str;
      // 临时拼接字符串的长度
      let newWidth = c.measureText(_newStr).width;
      // 初始化数组
      if (!newStrList) newStrList = '';
      // 长度判断
      if (newWidth >= maxWidth) { // 长度超过,换行
            newStrList = newStrList.substr(newStrList.length - 1) + str;
            newStrList = newStrList.substr(0, newStrList.length - 1);
            index++;
      } else {
            newStrList = newStrList + str;
      }
    }
    return newStrList.join('\r\n');
}

/**
* 对富文本进行换行
* @param c
* @param str
* @param maxWidth
* @returns {*}
*/
function wrapRichTextString(c, str, maxWidth){
    const richText = str['richText'];
    const newRichText = [];
    // 之前部分遗留的字符串
    let prevStr = '';
    // 需要测量长度的字符串
    let tmpStr = '';
    let index = 0;
    for (let i = 0; i < richText.length; i++) {
      const text = richText['text'];
      const style = richText['style'];
      const len = text.length;
      for (let j = 0; j < len; j++) {
            // 临时拼接字符串
            let _tmpStr = tmpStr + text;
            // 临时拼接字符串的长度 上个部分遗留的+当前拼接的
            let newWidth = c.measureText(prevStr+_tmpStr).width;
            // 长度判断
            if (newWidth >= maxWidth) { // 长度超过,换行
                newRichText = {
                  text : tmpStr,
                  style: style,
                }
                index++;
                newRichText = {
                  text : '\r\n',
                  style: style,
                }
                index++;
                // 记录当前字符,并将之前部分的记录清空
                tmpStr = text;
                prevStr = '';
            } else {
                tmpStr = _tmpStr;
            }
      }
      // 每一部分结束后,将剩余的该部分单独组成一个完成的部分,并记录到prevStr
      newRichText = {
            text : tmpStr,
            style: style,
      }
      index++;
      prevStr = prevStr + tmpStr;
      tmpStr = '';
    }
    str['richText'] = newRichText
    return str;
}
这是换行的cellType,spreadjs并不识别

发表于 2022-7-14 17:29:25

Derrick.Jiao 发表于 2022-7-14 14:52
你好,富文本换行可以参考附件的demo通过/n/r换行。若仍未符合需求,可以提供对应demo以及描述详细需求,这 ...

{"richText":[{"text":"该水样所检项目中肉眼可见物、耗氧量(COD","style":{"font":"14.7px 宋体","foreColor":"Text 1 0","textDecoration":0}},{"text":"Mn","style":{"vertAlign":2,"font":"14.7px 宋体","foreColor":"Text 1 0","textDecoration":0}},{"text":"法,以O","style":{"font":"14.7px 宋体","foreColor":"Text 1 0","textDecoration":0}},{"text":"2","style":{"vertAlign":2,"font":"14.7px 宋体","foreColor":"Text 1 0","textDecoration":0}},{"text":"计)、总大肠菌群、菌落总数、浑浊度检测结果超《生活饮用水卫生标准》(GB 5749-2006)标准要求,其它项目检测结果均符合标准要求。","style":{"font":"14.7px 宋体","foreColor":"Text 1 0","textDecoration":0}}],"text":"该水样所检项目中肉眼可见物、耗氧量(CODMn法,以O2计)、总大肠菌群、菌落总数、浑浊度检测结果超《生活饮用水卫生标准》(GB 5749-2006)标准要求,其它项目检测结果均符合标准要求。"}
这是转换之前的richText

发表于 2022-7-14 17:29:51

Derrick.Jiao 发表于 2022-7-14 14:52
你好,富文本换行可以参考附件的demo通过/n/r换行。若仍未符合需求,可以提供对应demo以及描述详细需求,这 ...

{"richText":[{"text":"该水样所检项目中肉眼可见物、耗氧量(COD","style":{"font":"14.7px 宋体","foreColor":"Text 1 0","textDecoration":0}},{"text":"Mn","style":{"vertAlign":2,"font":"14.7px 宋体","foreColor":"Text 1 0","textDecoration":0}},{"text":"法,以O","style":{"font":"14.7px 宋体","foreColor":"Text 1 0","textDecoration":0}},{"text":"2","style":{"vertAlign":2,"font":"14.7px 宋体","foreColor":"Text 1 0","textDecoration":0}},{"text":"计)、总大肠菌群、菌落总数、浑浊度检","style":{"font":"14.7px 宋体","foreColor":"Text 1 0","textDecoration":0}},{"text":"\r\n","style":{"font":"14.7px 宋体","foreColor":"Text 1 0","textDecoration":0}},{"text":"测结果超《生活饮用水卫生标准》(GB 5749-2006)标准要求,其它项目检测结果均符合标准要求","style":{"font":"14.7px 宋体","foreColor":"Text 1 0","textDecoration":0}},{"text":"\r\n","style":{"font":"14.7px 宋体","foreColor":"Text 1 0","textDecoration":0}},{"text":"。","style":{"font":"14.7px 宋体","foreColor":"Text 1 0","textDecoration":0}}],"text":"该水样所检项目中肉眼可见物、耗氧量(CODMn法,以O2计)、总大肠菌群、菌落总数、浑浊度检测结果超《生活饮用水卫生标准》(GB 5749-2006)标准要求,其它项目检测结果均符合标准要求。"}
这是转换之后的richText

发表于 2022-7-14 17:30:42

Derrick.Jiao 发表于 2022-7-14 14:52
你好,富文本换行可以参考附件的demo通过/n/r换行。若仍未符合需求,可以提供对应demo以及描述详细需求,这 ...


最终效果并没有变化

Derrick.Jiao 发表于 2022-7-14 18:14:16

浩 发表于 2022-7-14 17:30
最终效果并没有变化

这是我测试的效果,在添加“/n/r”处实现了换行。

发表于 2022-7-21 11:29:59

Derrick.Jiao 发表于 2022-7-14 18:14
这是我测试的效果,在添加“/n/r”处实现了换行。

直接写入是可以的,但是我这里还使用了自定义单元格类型,重写了paint方法,兼容自动换行
function AutoWrapTextCellType() {
}

AutoWrapTextCellType.prototype = new GC.Spread.Sheets.CellTypes.Text();
AutoWrapTextCellType.prototype.paint = function (ctx, value, x, y, w, h, style, context) {
    ctx.font = style.font;
    value = wrapString(ctx, value, w - 2);
    GC.Spread.Sheets.CellTypes.Text.prototype.paint.apply(this, );
};
function wrapString(c, str, maxWidth) {
    if($.common.isNotEmpty(str) && typeof str == 'object' && str['richText']){
      // return wrapRichTextString(c, str, maxWidth);
      return str;
    }
    return wrapTextString(c, str, maxWidth)
}

/**
* 对普通文本进行换行
* @param c
* @param str
* @param maxWidth
* @returns {string|*}
*/
function wrapTextString(c, str, maxWidth){
    let width = c.measureText(str).width;
    if (width <= maxWidth) return str;
    const len = str.length;
    let newStrList = [];
    let index = 0;
    for (let i = 0; i < len; i++) {
      // 临时拼接字符串
      let _newStr = newStrList + str;
      // 临时拼接字符串的长度
      let newWidth = c.measureText(_newStr).width;
      // 初始化数组
      if (!newStrList) newStrList = '';
      // 长度判断
      if (newWidth >= maxWidth) { // 长度超过,换行
            newStrList = newStrList.substr(newStrList.length - 1) + str;
            newStrList = newStrList.substr(0, newStrList.length - 1);
            index++;
      } else {
            newStrList = newStrList + str;
      }
    }
    return newStrList.join('\r\n');
}

/**
* 对富文本进行换行
* @param c
* @param str
* @param maxWidth
* @returns {*}
*/
function wrapRichTextString(c, str, maxWidth){
    const richText = str['richText'];
    const newRichText = [];
    // 之前部分遗留的字符串
    let prevStr = '';
    // 需要测量长度的字符串
    let tmpStr = '';
    let index = 0;
    for (let i = 0; i < richText.length; i++) {
      const text = richText['text'];
      const style = richText['style'];
      const len = text.length;
      for (let j = 0; j < len; j++) {
            // 临时拼接字符串
            let _tmpStr = tmpStr + text;
            // 临时拼接字符串的长度 上个部分遗留的+当前拼接的
            let newWidth = c.measureText(prevStr+_tmpStr).width;
            // 长度判断
            if (newWidth >= maxWidth) { // 长度超过,换行
                newRichText = {
                  text : tmpStr,
                  style: style,
                }
                index++;
                newRichText = {
                  text : '\r\n',
                  style: style,
                }
                index++;
                // 记录当前字符,并将之前部分的记录清空
                tmpStr = text;
                prevStr = '';
            } else {
                tmpStr = _tmpStr;
            }
      }
      // 每一部分结束后,将剩余的该部分单独组成一个完成的部分,并记录到prevStr
      newRichText = {
            text : tmpStr,
            style: style,
      }
      index++;
      prevStr = prevStr + tmpStr;
      tmpStr = '';
    }
    str['richText'] = newRichText
    console.log(JSON.stringify(str))
    return str;
}

Derrick.Jiao 发表于 2022-7-21 17:46:02

浩 发表于 2022-7-21 11:29
直接写入是可以的,但是我这里还使用了自定义单元格类型,重写了paint方法,兼容自动换行

由于上面提供的代码这边无法直接复现,请在附件的demo中复现此问题。并且,详细描述想要实现的效果,也就是具体需要在哪个位置进行换行。这样我们这边就可以直接根据需求来调整提供过来的demo。

发表于 2022-7-21 19:36:00

Derrick.Jiao 发表于 2022-7-21 17:46
由于上面提供的代码这边无法直接复现,请在附件的demo中复现此问题。并且,详细描述想要实现的效果,也就 ...

这是demo,可以发现换行位置和console输出的换行位置完全不一致
页: [1] 2
查看完整版本: spreadjs 换行问题(SJS-4589)