performance nächste - Schnellere Möglichkeit, die erste leere Zeile zu finden




7 Answers

Im Google Apps Script-Blog gab es einen Beitrag zur Optimierung von Tabellenkalkulationsoperationen , in dem es um das Batching von Lese- und Schreibvorgängen ging, die die Dinge wirklich beschleunigen konnten. Ich habe Ihren Code in einer Tabelle mit 100 Zeilen probiert und es hat ungefähr sieben Sekunden gedauert. Wenn Sie Range.getValues() , dauert die Stapelversion eine Sekunde.

function getFirstEmptyRow() {
  var spr = SpreadsheetApp.getActiveSpreadsheet();
  var column = spr.getRange('A:A');
  var values = column.getValues(); // get all data in one call
  var ct = 0;
  while ( values[ct][0] != "" ) {
    ct++;
  }
  return (ct);
}

Wenn die Tabelle groß genug wird, müssen Sie die Daten möglicherweise in Blöcken von 100 oder 1000 Zeilen erfassen, anstatt die gesamte Spalte zu erfassen.

excel userform

Ich habe ein Skript erstellt, das alle paar Stunden eine neue Zeile zu einer Google Apps-Tabelle hinzufügt.

Dies ist die Funktion, die ich gemacht habe, um die erste leere Zeile zu finden:

function getFirstEmptyRow() {
  var spr = SpreadsheetApp.getActiveSpreadsheet();
  var cell = spr.getRange('a1');
  var ct = 0;
  while ( cell.offset(ct, 0).getValue() != "" ) {
    ct++;
  }
  return (ct);
}

Es funktioniert gut, aber wenn es ungefähr 100 Zeilen erreicht, wird es wirklich langsam, sogar zehn Sekunden. Ich bin besorgt, dass wenn es Tausende von Zeilen erreicht, es zu langsam sein wird, vielleicht in Timeout oder schlimmer. Gibt es einen besseren Weg?







Und warum nicht appendRow ?

var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
spreadsheet.appendRow(['this is in column A', 'column B']);



In der Tat ist die getValues ​​eine gute Option, aber Sie können die Funktion .Length verwenden, um die letzte Zeile zu erhalten.

 function getFirstEmptyRow() {
  var spr = SpreadsheetApp.getActiveSpreadsheet();
  var array = spr.getDataRange().getValues();
  ct = array.length + 1
  return (ct);
}



Ich habe ein ähnliches Problem. Im Moment ist es ein Tisch mit vielen hundert Reihen, und ich erwarte, dass er auf viele Tausende anwächst. (Ich habe nicht gesehen, ob eine Google-Tabelle zehntausende von Zeilen verarbeitet, aber ich komme irgendwann dazu.)

Hier ist was ich mache.

  1. Gehe zu Hunderten um die Spalte vor, hör auf, wenn ich in einer leeren Reihe bin.
  2. Rückwärts durch die Spalte um Zehner gehen und nach der ersten nicht leeren Zeile suchen.
  3. Geh vorwärts durch die Spalte nach Einsen und suche nach der ersten leeren Reihe.
  4. Gib das Ergebnis zurück.

Dies hängt natürlich von zusammenhängenden Inhalten ab. Darf keine zufälligen Leerzeilen enthalten. Oder zumindest, wenn Sie dies tun, werden die Ergebnisse suboptimal sein. Und Sie können die Inkremente einstellen, wenn Sie es für wichtig halten. Diese funktionieren für mich, und ich finde, dass der Unterschied in der Dauer zwischen Schritten von 50 und Schritten von 100 vernachlässigbar ist.

function lastValueRow() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var r = ss.getRange('A1:A');
  // Step forwards by hundreds
  for (var i = 0; r.getCell(i,1).getValue() > 1; i += 100) { }
  // Step backwards by tens
  for ( ; r.getCell(i,1).getValue() > 1; i -= 10) { }
  // Step forwards by ones
  for ( ; r.getCell(i,1).getValue() == 0; i--) { }
  return i;
}

Das ist viel schneller, als jede Zelle von oben zu untersuchen. Und wenn Sie einige andere Spalten haben, die Ihr Arbeitsblatt erweitern, kann es auch schneller sein, als jede Zelle von unten zu untersuchen.




Endlich habe ich eine Single-Line-Lösung dafür.

var sheet = SpreadsheetApp.getActiveSpreadsheet();
var lastEmptyOnColumnB = sheet.getRange("B1:B"+sheet.getLastRow()).getValues().join(",").replace(/,,/g, '').split(",").length;

Es funktioniert gut für mich.




Die Verwendung von indexOf ist eine der Möglichkeiten, dies zu erreichen:

function firstEmptyRow() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sh = ss.getActiveSheet();
  var rangevalues = sh.getRange(1,1,sh.getLastRow(),1).getValues(); // Column A:A is taken
  var dat = rangevalues.reduce(function (a,b){ return a.concat(b)},[]); // 
 2D array is reduced to 1D//
  // Array.prototype.push.apply might be faster, but unable to get it to work//
  var fner = 1+dat.indexOf('');//Get indexOf First empty row
  return(fner);
  }



Related

performance google-apps-script google-spreadsheet