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

QQ登录

只需一步,快速开始

硕㏒

金牌服务用户

69

主题

187

帖子

606

积分

金牌服务用户

积分
606
硕㏒
金牌服务用户   /  发表于:2025-4-14 16:51  /   查看:85  /  回复:5
1金币
  1. // 在SpreadJs中异步请求
  2. function customFunctions15(GC) {
  3.   const asyncGetBoxQuality = function () {
  4.     this.typeName = "GETBOXQUALITY";
  5.     this.name = "GETBOXQUALITY";
  6.     this.maxArgs = 2;
  7.     this.minArgs = 2;
  8.     this.description = function () {
  9.       return {
  10.         description: "Get a box's quality by a box's number.",
  11.       };
  12.     };
  13.   };
  14.   asyncGetBoxQuality.prototype =
  15.     new GC.Spread.CalcEngine.Functions.AsyncFunction();
  16.   asyncGetBoxQuality.prototype.defaultValue = function () {
  17.     return "/";
  18.   };
  19.   // 参数1:盒号
  20.   // 参数2:试验室id
  21.   asyncGetBoxQuality.prototype.evaluateAsync = function (context, arg1, arg2) {
  22.     console.log(arg2);
  23.     try {
  24.       getByBoxNum(String(arg1)).then((res) => {
  25.         if (res.data.success) {
  26.           if (res.data.result) {
  27.             context.setAsyncResult(res.data.result.boxQuality);
  28.           } else {
  29.             context.setAsyncResult("/");
  30.           }
  31.         } else {
  32.           context.setAsyncResult("/");
  33.         }
  34.       });
  35.     } catch (error) {
  36.       // 捕获所有异常并返回 "/"
  37.       context.setAsyncResult("/");
  38.     }
  39.   };
  40.   // 全局注册
  41.   GC.Spread.CalcEngine.Functions.defineGlobalCustomFunction(
  42.     "GETBOXQUALITY",
  43.     new asyncGetBoxQuality()
  44.   );
  45. }
复制代码
这段代码是我注册的自定义函数,自定义函数中调用了后端的接口,在初始化文件夹的时候,一下调用了9000多次接口,但是我只有42个单元格使用了自定义函数

1872955eb239765ee81f7404ef8e6c0.png768965759.png

样品-土.ssjson

2.75 MB, 下载次数: 6

5 个回复

倒序浏览
Matthew.Xue
超级版主   /  发表于:2025-4-14 17:15:03
沙发
您好,我测试了您的自定义函数以及ssjson,由于没有getByBoxNum函数,我对您的函数稍作了修改,用以统计进入evaluateAsync方法的次数:
image.png124505003.png
image.png457717589.png
发现count数只加到了84,正好是42的两倍。
您可以自己测试一下这个数据,并同时统计接口调用的次数,看二者有怎样的关系?
回复 使用道具 举报
硕㏒
金牌服务用户   /  发表于:2025-4-14 17:51:10
板凳
Matthew.Xue 发表于 2025-4-14 17:15
您好,我测试了您的自定义函数以及ssjson,由于没有getByBoxNum函数,我对您的函数稍作了修改,用以统计进 ...


我这边试了下,2940次
image.png264630126.png
这段代码是我初始化的操作


  1. async workbookInitialized(value) {
  2.       if (this.isDesigner) {
  3.         initializeFunctions(GC, value, 1);
  4.         //designer设计器的方法
  5.         this.designer = value;
  6.         this.spread = this.designer.getWorkbook();
  7.         this.getTemplateParamList();
  8.         // this.changeOpenMenu();
  9.       } else {
  10.         initializeFunctions(GC, value, 2);
  11.         // 将传入的 value(电子表格实例)分配给 this.spread
  12.         this.spread = value;
  13.         // this.changeOpenMenu();
  14.       }

  15.       // 设置 tabStripPosition 为 1
  16.       this.spread.options.tabStripPosition = 1;
  17.       // 刷新电子表格视图
  18.       this.spread.invalidateLayout();
  19.       this.spread.repaint();
  20.       // 暂停电子表格的绘制
  21.       this.spread.suspendPaint();
  22.       //禁用delete
  23.       // let commandManager = this.spread.commandManager();
  24.       // commandManager.register("clearcontent", {
  25.       //   canUndo: true,
  26.       //   execute: function () {
  27.       //     // Do nothing to prevent delete
  28.       //     return true;
  29.       //   },
  30.       // });
  31.       // commandManager.setShortcutKey(
  32.       //   "clearcontent",
  33.       //   GC.Spread.Commands.Key.del,
  34.       //   false,
  35.       //   false,
  36.       //   false,
  37.       //   false
  38.       // );
  39.       //监听sheet页的切换
  40.       let now = this;
  41.       this.addSheetChangedListener(this.spread, function (newSheetName) {
  42.         console.log("切换到新的工作表:" + newSheetName);
  43.         now.activeSheetName = newSheetName;
  44.       });

  45.       try {
  46.         // 获取与 sampleTaskCode 相关的数据
  47.         // const result = await getSampleTaskOriginalRecordsByTaskId(
  48.         //   this.$route.query.sampleTaskCode || this.sampleTaskCode
  49.         // );
  50.         // const result = await this.getSampleTaskOriginalRecords();
  51.         // 如果成功获取数据
  52.         // console.log("🚀 ~ workbookInitialized ~ this.form:", this.form);
  53.         if (JSON.stringify(this.form) != "{}") {
  54.           // if (this.templateMode == 3) {
  55.           //   this.markFile(result.data.result);
  56.           // }
  57.           // 如果 fileUrl 存在
  58.           if (this.form.fileUrl) {
  59.             // 更新组件数据
  60.             // this.form = result.data.result;
  61.             // this.flowStatus = this.form.flowStatus;
  62.             this.showPrint = this.form.pdfFileUrl ? true : false;
  63.             this.pdfFileUrl = this.form.pdfFileUrl;
  64.             this.pdfFileTitle = this.form.pdfFileTitle;
  65.             this.experienceItemId = this.form.experienceItemId;
  66.             this.printId = this.form.id;
  67.             this.experienceItemParamNames = this.form.experienceItemParamNames;
  68.             if (this.form.immutableDataJson) {
  69.               this.dirtyDataObject = JSON.parse(this.form.immutableDataJson);
  70.             }
  71.             this.reportConcentrate = JSON.parse(this.form.variableDataJson);

  72.             // 下载文件并处理数据
  73.             const source = await downLoadApi(this.form.fileUrl);

  74.             // 读取文件内容
  75.             const reader = new FileReader();
  76.             reader.readAsText(source.data, "utf-8");
  77.             reader.onload = (e) => {
  78.               // 解析文件内容为 JSON
  79.               let json = JSON.parse(e.currentTarget.result);
  80.               // 将 JSON 数据导入到电子表格中
  81.               this.spread.fromJSON(json);
  82.               // 获取电子表格中的工作表数量
  83.               let index = this.spread.getSheetCount();
  84.               // 遍历所有工作表
  85.               for (let i = 0; i <= index - 1; i++) {
  86.                 // 解析 extendDataJson
  87.                 let obj = JSON.parse(this.form.extendDataJson);
  88.                 let data = {};

  89.                 // 获取当前工作表的数据
  90.                 if (obj) {
  91.                   data = obj[this.spread.getSheet(i).name()]
  92.                     ? obj[this.spread.getSheet(i).name()]
  93.                     : {};
  94.                 }
  95.                 // 深拷贝数据
  96.                 data = JSON.parse(JSON.stringify(data));
  97.                 //对JSON中的数据尽量转换类型,防止excel无法计算
  98.                 // 从Object.prototype获取hasOwnProperty方法的引用,以安全地检查对象自有属性
  99.                 const hasOwn = Object.prototype.hasOwnProperty;

  100.                 // 遍历data对象的所有属性
  101.                 for (let key in data) {
  102.                   if (hasOwn.call(data, key)) {
  103.                     const value = data[key];

  104.                     // 如果值是数组
  105.                     if (Array.isArray(value)) {
  106.                       // 遍历数组中的每一项
  107.                       for (let i = 0; i < value.length; i++) {
  108.                         const item = value[i];

  109.                         // 如果数组中的项是对象
  110.                         if (typeof item === "object" && item !== null) {
  111.                           // 遍历对象的所有属性
  112.                           for (let prop in item) {
  113.                             if (hasOwn.call(item, prop)) {
  114.                               item[prop] = this.convertToNumberOrDate(
  115.                                 item[prop]
  116.                               );
  117.                             }
  118.                           }
  119.                         }
  120.                       }
  121.                     } else {
  122.                       // 如果值不是数组,则直接转换
  123.                       data[key] = this.convertToNumberOrDate(value);
  124.                     }
  125.                   }
  126.                 }

  127.                 // 创建数据源

  128.                 let dataSource =
  129.                   new GC.Spread.Sheets.Bindings.CellBindingSource(data);
  130.                 // 如果数据是数组类型
  131.                 if (Array.isArray(data)) {
  132.                   // 设置工作表的数据源
  133.                   this.deviceData = data;
  134.                   this.spread.getSheet(i).setDataSource(data);
  135.                   // 设置列宽
  136.                   for (let J = 0; J <= 16; J++) {
  137.                     this.spread.getSheet(i).setColumnWidth(J, 200);
  138.                   }
  139.                 } else {
  140.                   // 设置工作表的数据源
  141.                   this.initDataSource(
  142.                     this.spread.getSheet(i),
  143.                     dataSource,
  144.                     data
  145.                   );
  146.                 }
  147.                 // this.autoFitRowOnSetDataSource(this.spread.getSheet(i));
  148.                 // this.spread.getSheet(i).recalcAll();
  149.               }
  150.               // 重置设置 tabStripPosition 为 1
  151.               this.spread.options.tabStripPosition = 1;
  152.               //禁止复制本地excel时粘贴的时候连带格式粘贴,保证只粘贴值
  153.               this.spread.options.allowCopyPasteExcelStyle = false;
  154.               // 刷新电子表格视图
  155.               this.spread.invalidateLayout();
  156.               this.processReports(this.spread);

  157.               // 检查testStatus是否为'已分配'
  158.               if (
  159.                 this.$route.query.testStatus &&
  160.                 this.$route.query.testStatus === "已分配"
  161.               ) {
  162.                 this.processingMaterialInfo(this.spread);
  163.               }

  164.               // this.autoFitRowOnValueChanged(value);
  165.               this.SelectionChanged(this.spread);

  166.               this.CellChanged(this.spread);
  167.               //获取设备缓存列表
  168.               this.getDeviceCache();
  169.               this.DragFill(this.spread);
  170.               this.spread.options.highlightInvalidData = false;
  171.               // 恢复电子表格的绘制
  172.               this.spread.resumePaint();
  173.             };
  174.           } else {
  175.             this.$message.error("获取模板失败");
  176.           }
  177.         }
  178.         // else {
  179.         //   this.$message.error("获取详情失败");
  180.         // }
  181.       } catch (error) {
  182.         // 输出错误信息并显示错误提示
  183.         console.error(error);
  184.         this.$message.error("发生错误");
  185.       }
  186.     },
复制代码



回复 使用道具 举报
Matthew.Xue
超级版主   /  发表于:2025-4-14 18:13:54
地板
注意到您代码中有遍历sheet做setDataSource的操作,结合模板中的GETBOXQUALITY函数引用了其他sheet的单元格,一旦这些被引用的单元格的值因为setDataSource而改变,就会触发一次重算,这才导致了上千次的接口请求。
建议您在fromJSON之后,先暂停计算服务,等待setDataSource结束之后,再继续计算。
image.png145744322.png
回复 使用道具 举报
硕㏒
金牌服务用户   /  发表于:7 天前
5#
Matthew.Xue 发表于 2025-4-14 18:13
注意到您代码中有遍历sheet做setDataSource的操作,结合模板中的GETBOXQUALITY函数引用了其他sheet的单元格 ...

好的
回复 使用道具 举报
Matthew.Xue
超级版主   /  发表于:7 天前
6#

好的,有进展还请您在帖子同步一下
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 立即注册
返回顶部