You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

解析JSON到Google Sheets时Google Apps Script报TypeError求助

问题分析与解决方案

错误含义解释

TypeError: Cannot read properties of undefined (reading 'forEach') 表示你尝试调用forEach方法的变量是undefined。在你的脚本中,这个变量就是arrayData——你错误地尝试从API返回的JSON中读取opportunities属性,但实际上API返回的是直接的数组,而非包含opportunities键的对象。

核心问题排查

  • API数据结构不匹配:你从API拿到的是直接的机会数据数组([ {...}, {...} ]),但脚本里写了var arrayData = json['opportunities'];,导致arrayData变成undefined,自然无法调用forEach。
  • 字段名不匹配:脚本里的多个字段(如opportunityName、contact、probabilityofClose等)和API实际返回的字段名(如name、contactNames、probability)完全不一致,即使解决了forEach的问题,后续也会出现大量undefined值。
  • 嵌套对象/数组未处理:API返回的stage是对象、companies是数组,直接写入Sheet会显示[object Object],需要提取具体属性。

修正后的完整脚本

function myFunction() {
  var url = "https://example.com";
  var params = {
    "headers": {
      "Authorization": 'Basic ' + Utilities.base64Encode(Username + ':' + Password),
      "Act-Database-Name": "Sample"
    }
  };

  var response = UrlFetchApp.fetch(url, params);
  var code = response.getResponseCode();
  var token = response.getContentText();

  Logger.log(code);
  Logger.log(token);

  var params2 = {
    "headers": { "Authorization": 'Bearer ' + token }
  };
  
  try {
    // 调用API
    var url2 = "https://example.com/api/opportunities";
    var jsondata = UrlFetchApp.fetch(url2, params2);

    var code2 = jsondata.getResponseCode();
    Logger.log(code2);

    var data = jsondata.getContentText();
    var json = JSON.parse(data);

    // 直接使用API返回的数组(无需取opportunities属性)
    var arrayData = json;
    // 容错:如果返回不是数组,初始化空数组
    if (!Array.isArray(arrayData)) {
      arrayData = [];
      Logger.log("API返回数据格式不符合预期,已初始化空数组");
    }

    // 用于存储Sheet数据的数组
    var arrayProperties = [];

    // 遍历机会数据,映射正确字段
    arrayData.forEach(function (el) {
      // 处理嵌套字段:提取stage名称
      var stageName = el.stage ? el.stage.name : "";
      // 处理公司数组:取第一个公司名称
      var companyName = el.companies && el.companies.length > 0 ? el.companies[0].name : "";
      // 处理联系人数组:拼接所有联系人名称
      var contactList = el.contacts && el.contacts.length > 0 ? el.contacts.map(c => c.displayName).join(", ") : "";

      arrayProperties.push([
        el.status || "",
        el.name || "", // 对应原脚本的opportunityName
        contactList || el.contactNames || "", // 对应原脚本的contact
        el.probability || "", // 对应原脚本的probabilityofClose
        el.weightedTotal || "",
        el.productTotal || "", // 对应原脚本的total
        el.edited || "", // 对应原脚本的editDate
        el.estimatedCloseDate || "",
        el.actualCloseDate || "",
        el.recordManager || "",
        "", // leadTime:API无此字段,留空
        "", // accessLevel:API无此字段,留空
        "", // associatedWith:API无此字段,留空
        companyName || "", // 对应原脚本的company
        el.competitor || "",
        el.created || "", // 对应原脚本的createDate
        el.daysInStage || "", // 修正大小写:原脚本为daysinStage
        el.daysOpen || "",
        el.grossMargin || "",
        el.importDate || "",
        el.editedBy || "", // 对应原脚本的lastEditedBy
        el.openDate || "",
        "", // opportunityField2:API无此字段,留空
        "", // opportunityField3:API无此字段,留空
        "", // opportunityField4:API无此字段,留空
        "", // opportunityField5:API无此字段,留空
        "", // opportunityField6:API无此字段,留空
        "", // opportunityField7:API无此字段,留空
        "", // opportunityField8:API无此字段,留空
        el.isPrivate || "", // 对应原脚本的private
        el.stage?.process?.name || "", // 提取process名称
        "", // product:API无此字段,留空
        el.reason || "",
        el.creator || "", // 对应原脚本的recordCreator
        "", // referredBy:API无此字段,留空
        el.sourceId || "", // 修正大小写:原脚本为sourceid
        stageName,
        el.stageStartDate || ""
      ]);
    });

    // 选择输出工作表
    var ss = SpreadsheetApp.getActiveSpreadsheet();
    var sheet = ss.getSheetByName('Current');
    if (!sheet) {
      Logger.log("未找到名为'Current'的工作表");
      return;
    }

    // 清空旧数据(可选)
    sheet.getRange(2, 1, sheet.getLastRow()-1, sheet.getLastColumn()).clearContent();
    
    // 写入数据到Sheet
    if (arrayProperties.length > 0) {
      var numRows = arrayProperties.length;
      var numCols = arrayProperties[0].length;
      sheet.getRange(2, 1, numRows, numCols).setValues(arrayProperties.reverse());
    } else {
      Logger.log("无数据可写入");
    }

  } catch (error) {
    Logger.log("错误信息:" + error.toString());
  }
}

关键修正点说明

  • 数组获取:将var arrayData = json['opportunities'];改为var arrayData = json;,匹配API返回的直接数组结构。
  • 字段映射:所有字段名替换为API文档中定义的名称,修正大小写错误(如daysinStage→daysInStage)。
  • 嵌套数据处理:对stage、companies、contacts等嵌套对象/数组,提取具体显示值,避免Sheet中出现[object Object]。
  • 容错处理:增加数组判断、字段空值默认处理、工作表存在性检查,避免因数据异常导致脚本崩溃。

内容的提问来源于stack exchange,提问作者Ryan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 06:50:50