找回密码
 立即注册

QQ登录

只需一步,快速开始

Quber
金牌服务用户   /  发表于:2024-4-18 14:19  /   查看:1851  /  回复:7
本帖最后由 Quber 于 2024-4-18 14:22 编辑

1、版本号
版本为17.0.7,Vue3。


2、问题描述
实现需求:某个单元格使用了自定义公式,在导出Excel文件后,想保留住这个单元格使用的自定义公式计算的值。
问题描述:现在导出Excel后,这个单元格使用的自定义公式计算的值没有保留住。

如下图所示:

导出前的效果:
image.png136046141.png

导出后的效果:
image.png55318602.png

反正最终想达到的效果是,导出后自定义公式的值要保留下来即可!!!

image.png771110839.png
image.png321217955.png

7 个回复

倒序浏览
Lynn.Dou讲师达人认证 悬赏达人认证 SpreadJS 开发认证
超级版主   /  发表于:2024-4-18 15:05:07
沙发
本帖最后由 Lynn.Dou 于 2024-4-18 15:06 编辑

您好,
在SpreadJS中自定义的函数,MSExcel并不支持,所以导出的xlsx文件在MSExcel中本地打开时会显示#Name
建议您导出时设置 忽略公式仅保留值,在designer中的表现如下:
image.png95954283.png
相关接口请参考学习指南介绍:
https://demo.grapecity.com.cn/sp ... mat/overview/purejs

image.png619263305.png
回复 使用道具 举报
Quber
金牌服务用户   /  发表于:2024-4-18 15:10:06
板凳
Lynn.Dou 发表于 2024-4-18 15:05
您好,
在SpreadJS中自定义的函数,MSExcel并不支持,所以导出的xlsx文件在MSExcel中本地打开时会显示#Nam ...

你好,根据你刚才提供的办法,值可以保留住
但是有一个问题,忽略公式就意味着所有的公式都没有了(包括内置的公式和自定义的公式)

我们想达到的效果是:内置的公式保留,自定义的公式可以不保留(但是值要保留)。
回复 使用道具 举报
Lynn.Dou讲师达人认证 悬赏达人认证 SpreadJS 开发认证
超级版主   /  发表于:2024-4-18 17:08:24
地板
导出忽略公式的配置是全局的,无法对部分公式进行单独设置。
还有一种思路可以考虑下,导出xlsx文件的时候,通过fromJSON/toJSON 复制一个新spread,在新spread中遍历公式判断如果是自定义公式,则setValue计算结果,并将公式删除。之后对新spread导出xlsx(保留公式),以实现需求。
回复 使用道具 举报
Quber
金牌服务用户   /  发表于:2024-4-18 17:14:38
5#
Lynn.Dou 发表于 2024-4-18 17:08
导出忽略公式的配置是全局的,无法对部分公式进行单独设置。
还有一种思路可以考虑下,导出xlsx文件的时候 ...

是的,我刚才就是按照你说的思路对需求进行实现了。

虽然这样可以实现该需求,但是我担心会不会在效率上有所损失,毕竟是每个表单每个单元格去查找公式,一旦表单很多,不知效率如何。

具体实现参见如下代码:


  1. /**
  2. * 导出为Excel文件(保留自定义公式的值)
  3. * 如支持导出自定义公式的值等功能
  4. * @param spread 原始Spread对象
  5. * @param GC Spread的GC对象
  6. * @param fileName 导出的文件名称,不传则为第一个表单的名称
  7. */
  8. const exportToExcelPlus = (spread: any, GC: any, fileName: string = "") => {
  9.     const json = spread.toJSON();

  10.     //需要移除的自定义公式名称集合(该变量的作用是,在导出Excel前,将工作簿中所有的自定义公式移除掉,其他内置的公式保留)
  11.     const removeCustomFormulas = [
  12.         "YJMAX",
  13.         "YJMIN",
  14.         "YJMID",
  15.         "YJGETNUM",
  16.         "YJGETS",
  17.         "YJGETCV",
  18.         "YJINTERPOLATIONMETHOD",
  19.         "YJINTERPOLATIONMETHOD_Y",
  20.     ];

  21.     //临时工作簿
  22.     const tempSpread = new GC.Spread.Sheets.Workbook();
  23.     tempSpread.fromJSON(json);

  24.     //暂停绘制
  25.     tempSpread.suspendPaint();

  26.     //获取Sheet数量
  27.     const sheetCount = tempSpread.getSheetCount();

  28.     for (let iSheet = 0; iSheet < sheetCount; iSheet++) {
  29.         //当前表单
  30.         const sheet = tempSpread.getSheet(iSheet);

  31.         //暂停公式的计算,提高新能
  32.         sheet.suspendCalcService();

  33.         for (var i = 0; i < sheet.getRowCount(); i++) {
  34.             for (var j = 0; j < sheet.getColumnCount(); j++) {
  35.                 //获取单元格的公式
  36.                 const cellFormula = sheet.getFormula(i, j);

  37.                 //如果cellFormula不为null或undefined,则说明该单元格引用了公式
  38.                 if (
  39.                     cellFormula != null &&
  40.                     cellFormula != undefined &&
  41.                     removeCustomFormulas.some(
  42.                         (item) => cellFormula.indexOf(item) > -1
  43.                     )
  44.                 ) {
  45.                     //获取单元格的值
  46.                     const cellVal = sheet.getValue(i, j);

  47.                     //移除单元格引用的公式
  48.                     sheet.getCell(i, j).formula(undefined);

  49.                     //设置单元格的值
  50.                     sheet.setValue(i, j, cellVal);
  51.                 }
  52.             }
  53.         }

  54.         //恢复计算
  55.         sheet.resumeCalcService(false);
  56.     }

  57.     //恢复绘制
  58.     tempSpread.resumePaint();

  59.     if (fileName == "") {
  60.         fileName = tempSpread.getSheet(0).name();
  61.     }

  62.     let options = {
  63.         fileType: GC.Spread.Sheets.FileType.excel,
  64.         includeBindingSource: true,
  65.         includeStyles: true,
  66.         includeFormulas: true,
  67.         saveAsView: false,
  68.         rowHeadersAsFrozenColumns: false,
  69.         columnHeadersAsFrozenRows: false,
  70.         includeAutoMergedCells: false,
  71.         includeCalcModelCache: false,
  72.         includeUnusedNames: true,
  73.         includeEmptyRegionCells: true,
  74.     };

  75.     tempSpread.export(
  76.         (blob) => {
  77.             saveAs(blob, `${fileName}.xlsx`);
  78.         },
  79.         () => {},
  80.         options
  81.     );

  82.     //销毁临时工作簿
  83.     tempSpread.destroy();
  84. };
复制代码





回复 使用道具 举报
Lynn.Dou讲师达人认证 悬赏达人认证 SpreadJS 开发认证
超级版主   /  发表于:2024-4-18 17:40:40
6#
代码逻辑看没啥问题(需要补充的一点是:可以维护一个自定义公式数组,获取公式后判断是否为自定义公式,之后再替换为value)。
关于性能咱们可以结合当前业务数据等实际测试下,除此外目前也没有更好的方案了。
回复 使用道具 举报
Quber
金牌服务用户   /  发表于:2024-4-18 17:56:04
7#
Lynn.Dou 发表于 2024-4-18 17:40
代码逻辑看没啥问题(需要补充的一点是:可以维护一个自定义公式数组,获取公式后判断是否为自定义公式,之 ...

是的,我们有专门维护的自定义公式数组,这里只是Demo演示,就写了个静态的数组名称。

感谢提供的解决方案,目前就只有先按照这种方式处理了。
回复 使用道具 举报
Lynn.Dou讲师达人认证 悬赏达人认证 SpreadJS 开发认证
超级版主   /  发表于:2024-4-19 09:27:46
8#
您客气了,那本贴就先结贴了,有问题欢迎另开新帖交流。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 立即注册
返回顶部