performance all'ultima - Modo più veloce per trovare la prima riga vuota




7 Answers

Il blog di Google Apps Script conteneva un post sull'ottimizzazione delle operazioni del foglio di calcolo che parlava di letture e scritture in batch che potevano davvero accelerare le cose. Ho provato il tuo codice su un foglio di calcolo con 100 righe, e ci sono voluti circa sette secondi. Usando Range.getValues() , la versione batch impiega un secondo.

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);
}

Se il foglio di calcolo diventa abbastanza grande, potrebbe essere necessario prendere i dati in blocchi di 100 o 1000 righe invece di afferrare l'intera colonna.

come andare

Ho creato uno script che ogni poche ore aggiunge una nuova riga a un foglio di calcolo di Google Apps.

Questa è la funzione che ho fatto per trovare la prima riga vuota:

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

Funziona bene, ma quando si raggiungono circa 100 file, diventa molto lento, anche dieci secondi. Sono preoccupato che quando raggiungo migliaia di file, sarà troppo lento, forse andando in timeout o peggio. C'è un modo migliore?







E perché non usare appendRow ?

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



In effetti i getValues ​​sono una buona opzione, ma puoi usare la funzione .length per ottenere l'ultima riga.

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



Ho un problema simile. In questo momento è una tabella con molte centinaia di righe e mi aspetto che aumenti di molte migliaia. (Non ho visto se un foglio di lavoro di Google gestirà decine di migliaia di righe, ma ci arriverò alla fine.)

Ecco cosa sto facendo.

  1. Avanzare attraverso la colonna per centinaia, fermarsi quando sono su una fila vuota.
  2. Torna indietro attraverso la colonna di decine, cercando la prima riga non vuota.
  3. Avanzare attraverso la colonna di uno, cercando la prima riga vuota.
  4. Restituisce il risultato.

Ciò dipende ovviamente dall'avere contenuti contigui. Non è possibile avere righe vuote casuali. O almeno, se lo fai, i risultati saranno sub-ottimali. E puoi regolare gli incrementi se pensi che sia importante. Questi funzionano per me, e trovo che la differenza di durata tra i passi di 50 e passi di 100 sia trascurabile.

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;
}

Questo è molto più veloce di ispezionare ogni cella dall'alto. E se ti capita di avere altre colonne che estendono il tuo foglio di lavoro, potrebbe essere più veloce di ispezionare ogni cella anche dal basso.




Finalmente ho ottenuto una soluzione a linea singola per questo.

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

Funziona bene per me.




L'utilizzo di indexOf è uno dei modi per ottenere ciò:

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