Guys, how are you? Here’s a nice tip to keep your Google Sheet tables tidy without annoying blank rows. To do this, you need to open the Apps Script tools in Google Sheets and activate the Google Sheets API service in the editor.
In the function area, you place this script (please test it thoroughly with prototypes to see if it has any errors). I haven’t tested it on a large scale yet, but I’m seeing good results.
how does it work?
? Algorithm Summary (Super Condensed):
-
Scan all rows in column A.
-
Detect which ones are empty.
-
If there’s more than one empty row, delete all except the last.
-
Perform deletions from bottom to top to avoid index shifting issues.
Plain English Summary:
This script checks column A of the active sheet and finds all empty rows.
If more than one empty row exists, it deletes all but the last one to keep the sheet tidy without removing the blank row that AppSheet sometimes expects for new entries.
It executes the deletions in a batch, starting from the bottom, using the Google Sheets API to avoid index mismatches during row removal.
The only condition will be that you place the ID (required) in column A. Why? Because the script doesn’t go through the entire table, but only column A. This is because it’s faster, and we know that the ID field is the only one that is always required in our tables.
function eliminarFilasVaciasDeUnaVez() {
var hoja = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var spreadsheetId = SpreadsheetApp.getActiveSpreadsheet().getId();
var sheetId = hoja.getSheetId();
// Obtener todos los valores de la columna A hasta la última fila con contenido
// o hasta el máximo de filas si la columna A está vacía pero otras tienen datos.
// Para ser más exhaustivos, podríamos usar hoja.getMaxRows() si la columna A
// puede estar vacía incluso si hay datos en otras columnas más allá de A.
var maxFilas = hoja.getMaxRows();
if (maxFilas === 0) {
Logger.log("La hoja no tiene filas.");
return;
}
var rango = hoja.getRange("A1:A" + maxFilas);
var valores = rango.getValues();
var indicesFilasVacias = []; // Almacenará los índices 0-based de las filas vacías
// Recorrer las filas para encontrar todas las que están vacías en la columna A
for (var i = 0; i < valores.length; i++) {
if (valores[i][0] === "" || valores[i][0] == null) { // Considerar "" y null como vacío
indicesFilasVacias.push(i); // i es el índice 0-based de la fila
}
}
if (indicesFilasVacias.length <= 1) {
Logger.log("No hay suficientes filas vacías para eliminar (se encontró " + indicesFilasVacias.length + ", se necesita más de una).");
return;
}
// Queremos conservar la última fila vacía encontrada (la que tiene el índice más alto).
// Por lo tanto, eliminaremos todas las filas vacías excepto la última en la lista 'indicesFilasVacias'.
// 'slice' crea una nueva lista con los elementos a borrar.
// El último elemento de 'indicesFilasVacias' es el que se conservará.
var indicesParaBorrar = indicesFilasVacias.slice(0, indicesFilasVacias.length - 1);
if (indicesParaBorrar.length === 0) {
Logger.log("Después de la lógica de 'conservar una', no quedan filas para borrar.");
return;
}
// Crear las solicitudes de eliminación para la API
var requests = indicesParaBorrar.map(function(rowIndex) {
// rowIndex es 0-based y se refiere a la fila real en la hoja.
return {
"deleteDimension": {
"range": {
"sheetId": sheetId,
"dimension": "ROWS",
"startIndex": rowIndex, // 0-indexed, inclusivo
"endIndex": rowIndex + 1 // 0-indexed, exclusivo
}
}
};
});
// ¡Importante! Para evitar problemas con el cambio de índices durante la eliminación,
// las solicitudes de eliminación deben procesarse de abajo hacia arriba (índices más altos primero).
// Por eso, ordenamos las 'requests' en orden descendente según 'startIndex'.
requests.sort(function(a, b) {
return b.deleteDimension.range.startIndex - a.deleteDimension.range.startIndex;
});
// Ejecutar la operación por lotes
try {
Sheets.Spreadsheets.batchUpdate({ "requests": requests }, spreadsheetId);
Logger.log(indicesParaBorrar.length + " filas vacías eliminadas de una vez.");
} catch (e) {
Logger.log("Error al eliminar filas: " + e.toString());
SpreadsheetApp.getUi().alert("Error al eliminar filas: " + e.toString());
}
}
Process
The idea is that it deletes the blank rows (in batch) and not one by one, leaving a single blank row at the end (since if you use Google Sheets tables, they must have at least one blank row).
While the script is to monitor changes when you add a row to the appsheet, it also works outside of the appsheet since it belongs to the Google Sheet.
Well, I hope you can test it with sheets that don’t compromise your data, and then let me know how it goes.