【问题标题】:Google Script (Sheets) Getlastrow not working as expectedGoogle 脚本(表格)Getlastrow 未按预期工作
【发布时间】:2021-08-24 03:07:42
【问题描述】:

提前致谢!我是脚本新手(熟悉 VBA),我不知道如何获得正确的最后一行。变量完全错误。我在代码中添加了有关不起作用的特定部分的 cmets。我尝试了两种不同的方法来获得最后一行。我基本上有一个需要复制的范围,以便每天输入到主文件。当脚本复制范围时,某些行可能有数据,也可能没有数据。当我再次运行脚本时,它会将整个范围视为每一行都有数据。已经为此工作了两天,我很困惑。我也试过录制一个宏,选择最后一个单元格,按下 control + 向上,这也不起作用。

工作表链接:https://docs.google.com/spreadsheets/d/1gIiChSoz1EMh8UjZxB3kAnsHw0eytPXg9HSnCsN42-c/edit#gid=328424380

function morningInputTest () {

var ss           = SpreadsheetApp.getActiveSpreadsheet();
var daySheet     = ss.getSheetByName("Day");
var reportSheet  = ss.getSheetByName("Monthly");
var todayDate    = daySheet.getRange("A1").getDisplayValue();
var expenseSheet = ss.getSheetByName("Expense");
var inventorySheet  =ss.getSheetByName("Inventory");
var choreSheet   = ss.getSheetByName("Chores ");

var lookupRangeValues = reportSheet.getRange(2,1,31,1).getDisplayValues();

for(var row in lookupRangeValues){
  if(lookupRangeValues[row][0]==todayDate)
    break;

}
row = +row + 2;

//Copies data from Day shift and pastes in Monthly report
//cash on hand
daySheet.getRange("I2").copyTo(reportSheet.getRange("C" + row),SpreadsheetApp.CopyPasteType.PASTE_VALUES,false);
//POS Readout
daySheet.getRange("B3").copyTo(reportSheet.getRange("B" + row),SpreadsheetApp.CopyPasteType.PASTE_VALUES,false);
//Waste or free pizza
daySheet.getRange("B5").copyTo(reportSheet.getRange("P" + row),SpreadsheetApp.CopyPasteType.PASTE_VALUES,false);
//Dough made
daySheet.getRange("B6").copyTo(reportSheet.getRange("N" + row),SpreadsheetApp.CopyPasteType.PASTE_VALUES,false);
//Total expenses NOT itemized
daySheet.getRange("E16").copyTo(reportSheet.getRange("K" + row),SpreadsheetApp.CopyPasteType.PASTE_VALUES,false);



// Porblem is here. Need to figrue out how to get the actual last row with data. For now it is copying 6 rows down for each row copied, including blank rows
//also need to be able to clear the expenses etc, but I know how to do this. Do it for day and for night. 
//I''ve tried these 3 different methods and none of them are working. 

//This one gives me completely random rows anywhere from 4-30ish
var expLR = expenseSheet.getRange("A999").getNextDataCell(SpreadsheetApp.Direction.UP).getRowIndex();
Logger.log(expLR + "Exp");

//This one also gives me seemingly random rows including pasting over existing data
inventorySheet.getRange("B1").activate;
inventorySheet.getCurrentCell().getNextDataCell(SpreadsheetApp.Direction.DOWN).activate;
var invLR = expenseSheet.getCurrentCell().getRowIndex() + 1;

//This one works the best, but still leaves gaps (range copied may not always have all rows filled with data, basically it posts the data from A28-D31. If there is one line of data, it still skips 4 rows before pasting the data)
Logger.log(invLR + "INV");
var chrLR = choreSheet.getLastRow()+1;
Logger.log(chrLR + "chr");


//This part also does not work (Exp I added one to get to next blank row, the others I add 1 to the variable, not sure what the best way to do it is as none of then are working at the moment)
//Total expenses itemized
daySheet.getRange("A10:G15").copyTo(expenseSheet.getRange("A" + (+expLR + 1)),SpreadsheetApp.CopyPasteType.PASTE_VALUES,false);
//Total inventory keyed
daySheet.getRange("A19:G24").copyTo(inventorySheet.getRange("A" + (+invLR)),SpreadsheetApp.CopyPasteType.PASTE_VALUES,false);
//Total chores not finished
daySheet.getRange("A28:D31").copyTo(choreSheet.getRange("A" + (+chrLR)),SpreadsheetApp.CopyPasteType.PASTE_VALUES,false);


//This all works fine. 
//clears cash on hand
daySheet.getRange("B2:H2").clear({contentsOnly: true});
//clears POS Readout
daySheet.getRange("B3").clear({contentsOnly: true});
//clears Waste or free pizza
daySheet.getRange("B5").clear({contentsOnly: true});
//clears Dough made
daySheet.getRange("B6").clear({contentsOnly: true});
//clears Total expenses itemized
daySheet.getRange("E16").clear({contentsOnly: true});

/*
This is the log reported from the last time I ran the script
10:16:51 PM Notice  Execution started
10:16:52 PM Info    89Exp
10:16:52 PM Info    4INV
10:16:52 PM Info    35chr
10:16:54 PM Notice  Execution completed
*/

}

【问题讨论】:

标签: google-sheets


【解决方案1】:

通常的方法是使用Sheet.getLastRow()。如果电子表格中的“空白”行包含公式、下拉列表或复选框,则该方法将返回最后一行,无论该行中是否有可见内容。

下面的函数获取具有可见内容的最后一行。

/**
* Gets the position of the last row that has visible content in a column of the sheet.
* When column is undefined, returns the last row that has visible content in any column.
*
* @param {Sheet} sheet A sheet in a spreadsheet.
* @param {Number} columnNumber Optional. The 1-indexed position of a column in the sheet.
* @return {Number} The 1-indexed row number of the last row that has visible content.
*/
function getLastRow_(sheet, columnNumber) {
  // version 1.5, written by --Hyde, 4 April 2021
  const values = (
    columnNumber
      ? sheet.getRange(1, columnNumber, sheet.getLastRow() || 1, 1)
      : sheet.getDataRange()
  ).getDisplayValues();
  let row = values.length - 1;
  while (row && !values[row].join('')) row--;
  return row + 1;
}

【讨论】:

  • 这很棒!谢谢!我不敢相信它在 Java 中如此复杂而在 VBA 中如此简单。非常感谢任何有关最佳实践的提示!再次感谢。
【解决方案2】:

你可以使用这个功能

function getLastDataRow(sheet,col) {
// col in letter
  var lastRow = sheet.getLastRow();
  var range = sheet.getRange(col + lastRow);
  if (range.getValue() !== "") {
    return lastRow;
  } else {
    return range.getNextDataCell(SpreadsheetApp.Direction.UP).getRow();
  }              
}

这样调用

var lastRow = getLastDataRow(expenseSheet,'A')

希望有效(拒绝访问您的电子表格)

【讨论】:

  • 我不知道为什么,但这个功能也很不稳定。它给出了不同的结果(我很可能是用户错误......)无论如何感谢您的帮助!学习更多代码总是好的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-09-07
  • 1970-01-01
  • 2020-05-03
  • 2015-10-24
  • 1970-01-01
  • 2018-05-18
  • 1970-01-01
相关资源
最近更新 更多