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 通知 执行完成
问题分析
从日志可见两个核心问题:
monthly数组包含空元素:日志里monthly最后一项是[, ],这是因为veriler数组读取到了空行,空行进入循环后生成了无效数据。- 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
相关产品推荐
相关产品推荐

