【问题标题】:Need guidance with Google Sheets array processing需要 Google 表格数组处理方面的指导
【发布时间】:2021-10-07 03:52:46
【问题描述】:

这是场景: 我有一个多标签(工作表)工作表。工作表 A(回合)收集数据,工作表 B-D 以不同方式对数据进行格式化。我正在尝试创建一个脚本,将当前工作表设置为工作表 D(Transfer-Stats),然后在那里创建一个二维数据数组。然后我想扫描该数组并选择非空白行并将它们放在另一个二维数组中,然后将其添加(附加)到不同的工作表中。我是 Apps 脚本的初学者,超出了我的技术能力。我想要一些基本的指导。我已经得到了一些初步的代码(如下所示),但到目前为止我唯一完成的是找到 Transfer-Stats 表的最后一行和最后一列。当涉及到尝试创建第一个 2D 数组的语句时,它会出现“找不到方法 getRange(number,number).”的错误。任何有关如何编码此问题的帮助将不胜感激。

function saveStats() {
  ui = SpreadsheetApp.getUi();
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var ssName = SpreadsheetApp.getActiveSpreadsheet().getName();
  var ssRounds = ss.getSheetByName('Rounds').getName();
  var ssStats = ss.getSheetByName('Transfer-Stats').getName();
  ui.alert("ssRounds " + ssRounds + " ssStats " + ssStats + " " + ssName) /** names are correct */
  SpreadsheetApp.setActiveSheet(ss.getSheetByName(ssStats), true); /** set to Transfer-Stats */
  var lastStatsRow = ss.getLastRow() /** find last row of stats sheet */
  var lastStatsCol = ss.getLastColumn() /** find last column of stats sheet */
  var statsArray = [ss.getRange(1, lastStatsCol).getValues()]
  ui.alert("Stop at Stats Last row is " + lastStatsRow + " Last Row is " + lastStatsCol + " " + ssStats + " " + ss)
  /** data shown above is: Stop at Stats Last row is 25 Last Col is 19 Transfer-Stats Spreadsheet which is correct for last row and column but not sure about "Spreadsheet" */
  var statsArray = [ss.getRange(1, lastStatsCol).getValues()] /** this statement fails */
  // SpreadsheetApp.setActiveSheet(ss.getSheetByName(ssRounds),true);
  // ssStats.activate()
}

更多细节:我的主工作表(Rounds)包含用户提供的数据。 Transfer-Stats 表使用 Rounds 表中的等价单元格收集其中一些数据(没有数据输入到 Transfer-Stats)。正在开发的脚本将从 Rounds 表启动,但我想从 Transfer-Stats 收集行并创建一个过滤数组以附加到不在此电子表格中的第三张表中。如果我知道怎么做,我会在这个论坛上分享这些表格 - 上面没有敏感数据。我尝试了建议代码的修改版本,如下所示:

function saveStats() {
// ui = SpreadsheetApp.getUi();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var ssName = SpreadsheetApp.getActiveSpreadsheet().getName();
var ssRounds = ss.getSheetByName('Rounds').getName();
var ssStats = ss.getSheetByName('Transfer_Stats').getName(); /** my code */
ssStats = SpreadsheetApp.setActiveSheet(ss.getSheetByName(ssStats),true); /** set to Transfer_Stats */
var lastStatsRow = ss.getLastRow() /** find last row of Transfer_Stats sheet */
var lastStatsCol = ss.getLastColumn() /** find last column of Transfer_Stats sheet */
var nameCol = 2 /** this column contains player name (checked for blank) */
var rowNum = 2 /** starting row */
var filterArray = [] /** temporary array for filtered rows */
var timeStamp = Utilities.formatDate(new Date(), "MST", "yyyy-MM-dd'/'HH:mm:ss") ; /** stamp each new row */
var filterSheet = ss.getSheetByName("Filtered_Stats") /** see if filtered sheet exists in the spreadsheet */
if (filterSheet != null) ss.deleteSheet(filterSheet) ; /** if it does, delete it so next statement will work */
    filterSheet = ss.insertSheet("Filtered_Stats") /** create a new Filtered_Stats sheet */
var filterSheet = ss.getSheetByName('Filtered_Stats').getName(); /** get the name */

/** Ignore these statements - they will become a question for later ? */
// statsDB = SpreadsheetApp.openById("SVE_Stats_Fall_2021"); /** get the stats database */
// statsDB = DriveApp.getFile /** ById("SVE_Stats_Fall_2021") ; /** get the stats database */
// while (statsDB.hasNext()) {
//  var file = statsDB.next();
//  Logger.log(file.getName());
// }
// Logger.log(statsDB)
// var myID = sheet.getRange(lastRow, myIDCol).getValue(); /** sample from web */
// ui.alert("Stop at Stats Last row is " + lastStatsRow + " Last Col is " + lastStatsCol + " ssStats " + ssStats + " ss " + ss)
// var statsArray = ssStats.getRange(2, 1 ,lastStatsRow, lastStatsCol).getValues() /** .filter(r >= r.join("")) */

/** Resume here with executable code */
for (var rowNum=2; rowNum < lastStatsRow+1; rowNum++ ) /** start selecting rows from the 2D array */
{
var statsName1 = ssStats.getRange(rowNum, nameCol).getValues() ; /** get player 1 name for this row to check if empty */
var statsName2 = ssStats.getRange(rowNum, nameCol+1).getValues() ; /** get player 2 name for this row to check if empty */
var statsArray = ssStats.getRange(rowNum, 1, 1, lastStatsCol).getValues() ; /** get the complete row of data in new array */
statsArray.unshift(timeStamp) ; /** add a time stamp as the first cell of the array */
Logger.log(statsArray) 
/** here's a sample from the above Logger.log (the first row of the 2D array with timestamp added):
    (the second date & time in the sample is actually a date in the original row) 
  7:30:34 AM  Info [2021-10-10/04:30:33, [R1M1-A, Ann Anderson, Kathy Biccum, 1.5, None, , Mon Jan 01 01:00:00 GMT-07:00 2001, 6.0, 4.0, 0.0, 6.0, 1.0, 5.0, 10.0, 0.0, 0.0, 17.0, 6.0, 35.294117647058826]] */ 
/** do I see a 2D array here because of the 2 sets of brackets [] ? */

if (statsName1 != "" && statsName2 != "") {
  filterArray.push(statsArray) /** attempt to create a row in the 1D array from the 2D array */

  Logger.log(filterArray) /** show what the new array looks like */
  /** here's a sample of what the new array looks like:
  7:39:50 AM  Info [[2021-10-10/04:39:49, [R1M1-A, Ann Anderson, Kathy Biccum, 1.5, None, , Mon Jan 01 01:00:00 GMT-07:00 2001, 6.0, 4.0, 0.0, 6.0, 1.0, 5.0, 10.0, 0.0, 0.0, 17.0, 6.0, 35.294117647058826]]]  */
  /** the new array now has another set of brackets around it */

  Logger.log(filterArray.length) /** show how long it is */
  /** here's the length at this point which is correct for the first iteration of the for loop:
  7:44:02 AM  Info  1.0  */

  /** the for loop executes correctly, selecting all the rows with non-blank names and placing them in the new array  */
  /** problem is the end result appended to the new sheet (see below) contains only 2 data elements not 20 as expected */

  /** this code attempts to switch to the Filter_Stats sheet and populate a row from the filterArray */
  /** it somewhat works, the first cell of each row in the sheet is filled with the timestamp */
  /** but the second cell of each row in the sheet contains [Ljava.lang.Object;@39e47f39 */
  ssFiltr = SpreadsheetApp.setActiveSheet(ss.getSheetByName(filterSheet),true); /** set to Filter_Stats */
  ssFiltr.appendRow(statsArray) ;
  ssStats = ss.getSheetByName('Transfer_Stats').getName();
  ssStats = SpreadsheetApp.setActiveSheet(ss.getSheetByName(ssStats),true); /** reset to Transfer_Stats */
}
}

// SpreadsheetApp.setActiveSheet(ss.getSheetByName(ssRounds),true); /** return to primary sheet Rounds */

}

我知道这篇文章会变得令人困惑,但这是我迄今为止所处的位置。我有一些代码在一定程度上可以工作,虽然相当粗糙,但它并不能完全满足我的要求。我已经包含了嵌入了许多 cmets 的代码,在我运行代码时显示了详细的数据样本。我认为主要问题是我没有正确处理数组,因此在新工作表中创建的行不包含我所期望的。任何帮助将不胜感激。

【问题讨论】:

  • 您能否提供一份电子表格副本(不含敏感信息),以便直观地阐明预期结果?
  • 我明白了!经过数小时的反复试验和研究其他示例,我终于想出了一些有效的代码。它看起来更像 COBOL 代码而不是 Apps 脚本,但它确实有效。如果有人有兴趣,我可以发布它。现在讨论 DriveApp 问题。
  • 您好,Tanaike 编辑的答案没有解决您的问题?在这种情况下,您能否发布一个答案来解释问题是什么以及您是如何解决的?

标签: arrays google-apps-script google-sheets


【解决方案1】:

我相信你的目标如下。

  • 您希望从“Rounds”表中检索值,并希望从值中删除空行。而且,您希望将这些值附加到“Transfer-Stats”。

在这种情况下,下面的示例脚本怎么样?

示例脚本:

我为每一行添加了 cmets。请检查一下。并且,在您使用此脚本之前,请设置目标工作表名称。

function saveStats() {
  // Retrieve Spreadsheet.
  var ss = SpreadsheetApp.getActiveSpreadsheet();

  // Retrieve sheet "Transfer-Stats".
  var ssStats = ss.getSheetByName('Rounds');

  // Retrieve values from "Transfer-Stats" and remove the empty rows.
  var values = ssStats.getRange(1, 1, ssStats.getLastRow(), ssStats.getLastColumn()).getValues().filter(r => r.join(""));

  // Retrieve sheet "Transfer-Stats".
  var dstSheet = ss.getSheetByName('Transfer-Stats'); // Please set the destination sheet name.

  // Append the values to the sheet "Transfer-Stats"
  dstSheet.getRange(dstSheet.getLastRow() + 1, 1, values.length, values[0].length).setValues(values);
}

注意:

  • 我了解到您想将“回合”表中的值复制到“转移统计”表中。如果我误解了工作表名称,请修改上述脚本。

参考资料:

编辑:

根据您的以下回复,

更多细节:我的主工作表(Rounds)包含用户提供的数据。 Transfer-Stats 表使用 Rounds 表中的等价单元格收集其中一些数据(没有数据输入到 Transfer-Stats)。正在开发的脚本将从 Rounds 表启动,但我想从 Transfer-Stats 收集行并创建一个过滤数组以附加到不在此电子表格中的第三张表中。如果我知道怎么做,我会在这个论坛上分享这些表格 - 上面没有敏感数据。

我没有注意到这一点。在这种情况下,我知道您想从Transfer-Stats 工作表中检索数据,并希望将过滤后的值放入工作表(我不知道工作表名称),Transfer-StatsRounds 除外。如果我的理解是正确的,下面的示例脚本怎么样?

示例脚本:

function saveStats() {
  // Retrieve Spreadsheet.
  var ss = SpreadsheetApp.getActiveSpreadsheet();

  // Retrieve sheet "Transfer-Stats".
  var ssStats = ss.getSheetByName('Transfer-Stats');

  // Retrieve values from "Transfer-Stats" and remove the empty rows.
  var values = ssStats.getRange(1, 1, ssStats.getLastRow(), ssStats.getLastColumn()).getValues().filter(r => r.join(""));

  // Retrieve sheet a sheet I cannot known the sheet name.
  var dstSheet = ss.getSheetByName('###'); // Please set the destination sheet name.

  // Append the values to the sheet I cannot known the sheet name.
  dstSheet.getRange(dstSheet.getLastRow() + 1, 1, values.length, values[0].length).setValues(values);
}

【讨论】:

  • 更详细一点:我的主工作表(Rounds)包含用户提供的数据。 Transfer-Stats 表使用 Rounds 表中的等价单元格收集其中一些数据(没有数据输入到 Transfer-Stats)。正在开发的脚本将从 Rounds 表启动,但我想从 Transfer-Stats 收集行并创建一个过滤数组以附加到不在此电子表格中的第三张表中。如果我知道怎么做,我会在这个论坛上分享这些表格 - 上面没有敏感数据。
  • @Bob 谢谢你的回复。我为我糟糕的英语水平道歉。不幸的是,从您最初的问题来看,我没有注意到您想要从 Transfer-Stats 工作表中检索数据并希望将过滤后的值放入工作表(我不知道工作表名称),Transfer-Stats 和 @987654332 除外@。如果我的理解是正确的,那么上面的示例脚本呢?如果我误解了你的问题,我再次道歉。
【解决方案2】:

这是适合我的代码。

function saveStats() {
// ui = SpreadsheetApp.getUi();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var ssName = SpreadsheetApp.getActiveSpreadsheet().getName();
var ssRounds = ss.getSheetByName('Rounds').getName();
var ssStats = ss.getSheetByName('Transfer_Stats').getName(); /** my code */
ssStats = SpreadsheetApp.setActiveSheet(ss.getSheetByName(ssStats),true); /** set to Transfer_Stats */
var lastStatsRow = ss.getLastRow() /** find last row of Transfer_Stats sheet */
var lastStatsCol = ss.getLastColumn() /** find last column of Transfer_Stats sheet */
var nameCol = 2 /** this column contains player name (checked for blank) */
var rowNum = 2 /** starting row */
var filterArray = [] /** temporary array for filtered rows */
var timeStamp = Utilities.formatDate(new Date(), "MST", "yyyy-MM-dd'/'HH:mm:ss") ; /** stamp each new row */
var filterSheet = ss.getSheetByName("Filtered_Stats") /** see if filtered sheet exists in the spreadsheet */
if (filterSheet != null) ss.deleteSheet(filterSheet) ; /** if it does, delete it so next statement will work */
    filterSheet = ss.insertSheet("Filtered_Stats") /** create a new Filtered_Stats sheet */
var filterSheet = ss.getSheetByName('Filtered_Stats').getName(); /** get the name */

/** Ignore these statements - they will become a question for later ? */
// statsDB = SpreadsheetApp.openById("SVE_Stats_Fall_2021"); /** get the stats database */
// statsDB = DriveApp.getFile /** ById("SVE_Stats_Fall_2021") ; /** get the stats database */
// while (statsDB.hasNext()) {
//  var file = statsDB.next();
//  Logger.log(file.getName());
// }
// Logger.log(statsDB)
// var myID = sheet.getRange(lastRow, myIDCol).getValue(); /** sample from web */
// ui.alert("Stop at Stats Last row is " + lastStatsRow + " Last Col is " + lastStatsCol + " ssStats " + ssStats + " ss " + ss)
// var statsArray = ssStats.getRange(2, 1 ,lastStatsRow, lastStatsCol).getValues() /** .filter(r >= r.join("")) */

/** Resume here with executable code */
for (var rowNum=2; rowNum < lastStatsRow+1; rowNum++ ) /** start selecting rows from the 2D array */
{
var statsName1 = ssStats.getRange(rowNum, nameCol).getValues() ; /** get player 1 name for this row to check if empty */
var statsName2 = ssStats.getRange(rowNum, nameCol+1).getValues() ; /** get player 2 name for this row to check if empty */
var statsArray = ssStats.getRange(rowNum, 1, 1, lastStatsCol).getValues() ; /** get the complete row of data in new array */
statsArray.unshift(timeStamp) ; /** add a time stamp as the first cell of the array */
Logger.log(statsArray) 
/** here's a sample from the above Logger.log (the first row of the 2D array with timestamp added):
    (the second date & time in the sample is actually a date in the original row) 
  7:30:34 AM  Info [2021-10-10/04:30:33, [R1M1-A, Ann Anderson, Kathy Biccum, 1.5, None, , Mon Jan 01 01:00:00 GMT-07:00 2001, 6.0, 4.0, 0.0, 6.0, 1.0, 5.0, 10.0, 0.0, 0.0, 17.0, 6.0, 35.294117647058826]] */ 
/** do I see a 2D array here because of the 2 sets of brackets [] ? */

if (statsName1 != "" && statsName2 != "") {
  filterArray.push(statsArray) /** attempt to create a row in the 1D array from the 2D array */

  Logger.log(filterArray) /** show what the new array looks like */
  /** here's a sample of what the new array looks like:
  7:39:50 AM  Info [[2021-10-10/04:39:49, [R1M1-A, Ann Anderson, Kathy Biccum, 1.5, None, , Mon Jan 01 01:00:00 GMT-07:00 2001, 6.0, 4.0, 0.0, 6.0, 1.0, 5.0, 10.0, 0.0, 0.0, 17.0, 6.0, 35.294117647058826]]]  */
  /** the new array now has another set of brackets around it */

  Logger.log(filterArray.length) /** show how long it is */
  /** here's the length at this point which is correct for the first iteration of the for loop:
  7:44:02 AM  Info  1.0  */

  /** the for loop executes correctly, selecting all the rows with non-blank names and placing them in the new array  */
  /** problem is the end result appended to the new sheet (see below) contains only 2 data elements not 20 as expected */

  /** this code attempts to switch to the Filter_Stats sheet and populate a row from the filterArray */
  /** it somewhat works, the first cell of each row in the sheet is filled with the timestamp */
  /** but the second cell of each row in the sheet contains [Ljava.lang.Object;@39e47f39 */
  ssFiltr = SpreadsheetApp.setActiveSheet(ss.getSheetByName(filterSheet),true); /** set to Filter_Stats */
  ssFiltr.appendRow(statsArray) ;
  ssStats = ss.getSheetByName('Transfer_Stats').getName();
  ssStats = SpreadsheetApp.setActiveSheet(ss.getSheetByName(ssStats),true); /** reset to Transfer_Stats */
}
}

// SpreadsheetApp.setActiveSheet(ss.getSheetByName(ssRounds),true); /** return to primary sheet Rounds */

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-09-11
    • 2021-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多