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

Google Apps Script TypeError:无法读取undefined的'0'属性解决

Google Apps Script TypeError 排查:月度盈亏表写入失败

用Google Sheets每日跟踪股票价格,通过Google Apps Script抓取股价写入表格。现在要生成股票月度盈亏表,编写代码提取带日期的股价数组,将每月首尾数据存入monthly数组后写入'Aylık P/L'工作表。但添加写入数据的for循环后,抛出错误:TypeError: Cannot read properties of undefined (reading '0')。怀疑monthly数组存在空值,但无法定位问题。

相关代码

function aylikRapor() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet1 = ss.getSheetByName('Fiyat Çek');
  var sheet2 = ss.getSheetByName('Günlük Fon Takip');
  var sheet3 = ss.getSheetByName('Haftalık Fon Takip');
  var sheet4 = ss.getSheetByName('Aylık Fon Takip');
  var sheet5 = ss.getSheetByName('Funds Main');
  var sheet6 = ss.getSheetByName('Aylık');
  var sheet7 = ss.getSheetByName('Aylık P/L');

  var pfs = sheet5.getRange(1,1).getValue(); // pfs = PortföydekiFonSayısı
  var i = 1;
  var f = 1;
  var a;
  var b;

  try {
    
    for(i=1; i<=pfs; i++) {
        var colH = sheet2.getRange(1,3*i,1,1);
        var harf = colH.getA1Notation().match(/([A-Z]+)/)[0];
        var column = sheet2.getRange(harf+":"+harf);
      
        // get lastFilledRow
        var value = ''
        const max = sheet2.getMaxRows()
        var values = column.getValues()
        values = [].concat.apply([], values)
        for (row = max - 1; row > 0; row--) {
          value = values[row]
          if (value != '') { break }
      }

      lastRowD = row + 1;
      Logger.log(lastRowD);

   let veriler = sheet2.getRange(14,3*i-1,lastRowD-12,2).getValues();
    

    let month = veriler[0][0].getMonth();

    
    let monthly = [[veriler[0][0],veriler[0][1]]];
    
    veriler.forEach( (row,index) => {
        
        let test = new Date(row[0]).getMonth();
        if( test !== month ) {
          monthly.push([veriler[index-1][0],veriler[index-1][1]]);
          
          monthly.push([row[0],row[1]]);
          month = test;

        }
      }
    )
    Logger.log(monthly);

      for (f=1, a=0, b=1; f <=monthly.length-1; f++, a+=2, b+=2){
        sheet7.getRange(3+f,5*i-2).setValue(monthly[a][0]); 
        sheet7.getRange(3+f,5*i-1).setValue(monthly[a][1]);
        sheet7.getRange(3+f,5*i).setValue(monthly[b][0]);
        sheet7.getRange(3+f,5*i+1).setValue(monthly[b][1]);
      }
    
  }
  }
  catch(err) {
    Logger.log("Error in Monthly: "+err);
  }
}

执行日志(翻译后)

执行日志
09:49:37    通知    执行开始
09:49:49    信息   119.0
09:49:50    信息   [[Wed Aug 17 00:00:00 GMT+03:00 2022, 0.080777], [Wed Aug 31 00:00:00 GMT+03:00 2022, 0.082585], [Thu Sep 01 00:00:00 GMT+03:00 2022, 0.0831], [Fri Sep 30 00:00:00 GMT+03:00 2022, 0.08431], [Mon Oct 03 00:00:00 GMT+03:00 2022, 0.085019], [Mon Oct 31 00:00:00 GMT+03:00 2022, 0.096867], [Tue Nov 01 00:00:00 GMT+03:00 2022, 0.098144], [Wed Nov 30 00:00:00 GMT+03:00 2022, 0.115665], [Thu Dec 01 00:00:00 GMT+03:00 2022, 0.117343], [Fri Dec 30 00:00:00 GMT+03:00 2022, 0.126554], [Mon Jan 02 00:00:00 GMT+03:00 2023, 0.127234], [Thu Jan 12 00:00:00 GMT+03:00 2023, 0.111894], [, ]]
09:49:50    信息   月度报表错误: TypeError: Cannot read properties of undefined (reading '0')
09:49:38    通知    执行完成

问题分析

从日志可见两个核心问题:

  1. monthly数组包含空元素:日志里monthly最后一项是[, ],这是因为veriler数组读取到了空行,空行进入循环后生成了无效数据。
  2. for循环索引越界:原循环条件f <=monthly.length-1会导致当monthly长度为奇数时(比如日志里的13),最后一次循环中b的值会超出数组最大索引,访问monthly[b][0]时触发undefined错误。

修复方案

1. 过滤空行,清理veriler数组

获取数据后直接过滤掉空行,避免无效数据进入后续逻辑:

let veriler = sheet2.getRange(14,3*i-1,lastRowD-12,2).getValues()
  .filter(row => row[0] !== '' && row[0] !== undefined);

2. 补全年度最后一个月的末尾数据

原代码只在月份切换时添加上月末尾数据,最后一个月的末尾数据未写入,需要在forEach循环结束后补充:

// 在forEach循环结束后添加最后一个月的收盘价
if(veriler.length > 0) {
  monthly.push([veriler[veriler.length-1][0], veriler[veriler.length-1][1]]);
}

3. 修正for循环逻辑,避免索引越界

改用按成对元素遍历的方式,确保不会访问超出数组范围的索引:

// 替换原有的for循环
for (let f = 0; f < monthly.length; f += 2) {
  if(f + 1 >= monthly.length) break; // 防止最后一组不完整
  const targetRow = 3 + (f / 2 + 1); // 对应工作表的目标行号
  sheet7.getRange(targetRow, 5*i-2).setValue(monthly[f][0]); 
  sheet7.getRange(targetRow, 5*i-1).setValue(monthly[f][1]);
  sheet7.getRange(targetRow, 5*i).setValue(monthly[f+1][0]);
  sheet7.getRange(targetRow, 5*i+1).setValue(monthly[f+1][1]);
}

4. 增加空数据判断

在处理veriler前判断是否为空,避免因无数据导致veriler[0][0]报错:

if(veriler.length === 0) continue; // 无数据时跳过当前股票
let month = veriler[0][0].getMonth();

修复后的完整代码

function aylikRapor() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet2 = ss.getSheetByName('Günlük Fon Takip');
  var sheet5 = ss.getSheetByName('Funds Main');
  var sheet7 = ss.getSheetByName('Aylık P/L');

  var pfs = sheet5.getRange(1,1).getValue(); // pfs = PortföydekiFonSayısı

  try {
    for(let i=1; i<=pfs; i++) {
        var colH = sheet2.getRange(1,3*i,1,1);
        var harf = colH.getA1Notation().match(/([A-Z]+)/)[0];
        var column = sheet2.getRange(harf+":"+harf);
      
        // 获取最后有数据的行
        var value = ''
        const max = sheet2.getMaxRows()
        var values = column.getValues()
        values = [].concat.apply([], values)
        for (let row = max - 1; row > 0; row--) {
          value = values[row]
          if (value != '') { break }
        }

        const lastRowD = row + 1;
        Logger.log(lastRowD);

        // 获取数据并过滤空行
        let veriler = sheet2.getRange(14,3*i-1,lastRowD-12,2).getValues()
          .filter(row => row[0] !== '' && row[0] !== undefined);
        
        // 无数据则跳过
        if(veriler.length === 0) continue;

        let month = veriler[0][0].getMonth();
        let monthly = [[veriler[0][0],veriler[0][1]]];
        
        veriler.forEach( (row,index) => {
            let test = new Date(row[0]).getMonth();
            if( test !== month ) {
              monthly.push([veriler[index-1][0],veriler[index-1][1]]);
              monthly.push([row[0],row[1]]);
              month = test;
            }
          }
        );

        // 补充最后一个月的末尾数据
        monthly.push([veriler[veriler.length-1][0], veriler[veriler.length-1][1]]);
        Logger.log(monthly);

        // 写入工作表
        for (let f = 0; f < monthly.length; f += 2) {
          if(f + 1 >= monthly.length) break;
          const targetRow = 3 + (f / 2 + 1);
          sheet7.getRange(targetRow, 5*i-2).setValue(monthly[f][0]); 
          sheet7.getRange(targetRow, 5*i-1).setValue(monthly[f][1]);
          sheet7.getRange(targetRow, 5*i).setValue(monthly[f+1][0]);
          sheet7.getRange(targetRow, 5*i+1).setValue(monthly[f+1][1]);
        }
    }
  }
  catch(err) {
    Logger.log("Error in Monthly: "+err);
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 19:05:18