google apps script - script - ¿Cómo puedo saber si las celdas de la hoja de cálculo se fusionan con la secuencia de comandos de Google Apps?
google script spreadsheet (8)
En una hoja de cálculo de Google Docs. Si las celdas A1 y A2 se fusionan, ¿hay alguna forma de confirmar que están fusionadas, utilizando el script de Google Apps?
Hay una función de fusión en GAS https://developers.google.com/apps-script/class_range#merge
Pero no hay ninguna función o ejemplo que muestre cómo verificar si las celdas están fusionadas.
getValues etc simplemente devuelve una cadena vacía para la celda. por ejemplo, esto no funciona.
function testMerge() {
var spreadsheet = SpreadsheetApp.openById(''Z3ppTjxNUE........'');
var sheet = spreadsheet.getSheets()[0];
var range = sheet.getRange("A3:A4");
var values = range.getValues();
var formulas = range.getFormulasR1C1();
var formulasA1 = range.getFormulas();
range = sheet.getRange("A4");
range.setValue("a");
range = sheet.getRange("A3:A4");
var values2 = range.getValues();
var formulas2 = range.getFormulasR1C1();
var formulasA12 = range.getFormulas();
var count = range.getHeight();
}
Encontré esta solución, publicada aquí:
https://code.google.com/p/google-apps-script-issues/issues/detail?id=618
Pero solo funciona para rango activo
// This is my function to test the active range is merged or not and return
// true or false by passing active range to it
function ismerge() {
var spread = SpreadsheetApp.getActiveSpreadsheet();
var sheet = spread.getActiveSheet();
var last_row = sheet.getActiveRange().getLastRow();
var last_col = sheet.getActiveRange().getLastColumn();
Logger.log("Last row: %s", last_row);
var active_row = sheet.getActiveRange().getRow();
var active_col = sheet.getActiveRange().getColumn();
Logger.log("Row: %s", active_row);
if ( (last_row == active_row) && (last_col == active_col) ) {
Logger.log("Cell not merged");
return false;
}
else {
Logger.log("Cell merged");
return true;
}
}
No es posible saber eso. Ya se ha abierto un problema con respecto a esto, pero es bastante antiguo y no tiene actividad. Deberías protagonizarlo (para realizar un seguimiento de las actualizaciones y votar al respecto) y dejar un comentario para ver si puedes llamar la atención.
Pero lo que hago cuando necesito asegurar que las celdas fusionadas sean como las quiero es dividir todo y fusionar nuevamente, solo para estar seguro. Por supuesto, esta no es una solución, solo una idea que también le conviene.
Para aquellos como yo que no conocían el método .breakapart()
para unmerge cells: https://developers.google.com/apps-script/class_range#breakApart
¡Gracias a Henrique por la propina!
Descargar como HTML: puede descargar una hoja como HTML, esto incluirá la información de la celda fusionada. No es una buena solución, pero funciona.
URL de descarga de ejemplo:
docs.google.com/feeds/download/spreadsheets/Export?key=* spreadsheetkey * & exportFor mat = html & gid = 3
donde gid es el número de hoja gid. - Se requiere iniciar sesión a través de la API de Google api (ver google Drive DrEdit Tutorial para más detalles)
Si alguien necesita una solución alternativa para este problema, escribí una pequeña herramienta que quita la mayor parte del trabajo de burro de crear un archivo de valor clave de todas las celdas combinadas del HTML exportado.
Puede encontrarlo aquí: https://github.com/martinhbramwell/CellMergeWorkAround
Lo escribí porque tengo un pequeño proyecto que depende de poder clonar por completo los rangos de una hoja de cálculo a otra. Obviamente, he agregado mi voto para querer solucionar el problema.
(Nota: habría agregado esto como un comentario a la respuesta correcta, pero carezco de los puntos necesarios).
Parece haber una solución que explota el hecho de que las celdas combinadas siempre devuelven un fondo blanco. El código siguiente parece funcionar para mí; Lo agradeceré si alguien puede confirmarlo.
function testMerged() {
var WHITE = ''#ffffff'';
var NON_WHITE = ''#fffffe'';
var range = SpreadsheetApp.getActiveSheet().getDataRange();
range.setBackground(NON_WHITE);
range.getBackgrounds().forEach(function (row, rowNum) {
row.forEach(function (col, colNum) {
if (col === WHITE) { Logger.log(''Cell merged at row '' + rowNum + '' col '' + colNum); }
});
});
range.setBackground(WHITE);
}
Tal vez es una respuesta un poco tarde porque no vi este problema para la nueva versión de las hojas de cálculo de Google. Pero todavía utilizo la versión anterior de las hojas de cálculo para mi proyecto. Así que se me necesitaba de alguna manera resolverlo.
Necesito copiar el formato de la columna anterior para nuevas columnas. Esto es parte del código a continuación:
// trying to find first column with week day (white background)
var background = '''';
for(var columnIndex = 3; columnIndex<=columnLetters.length; columnIndex++){
background = sheet.getRange(1, columnIndex).getBackground();
if(background == ''white'' || background == ''''){
tmpRange = columnLetters[columnIndex]+'':''+columnLetters[columnIndex];
Logger.log(''tmpRange: ''+tmpRange);
// workaround to be able to copy format if there is some merged cells
try{
Logger.log(''try'');
// copy format of previous column
sheet.getRange(tmpRange).copyTo(
sheet.getRange(''B1''), {formatOnly:true}
);
}catch(e) {
Logger.log(''continue'');
continue;
}
Logger.log(''break'');
break;
}
}
Entonces, la parte más importante aquí es:
try{
Logger.log(''try'');
// copy format of previous column
sheet.getRange(tmpRange).copyTo(
sheet.getRange(''B1''), {formatOnly:true}
);
}catch(e) {
Logger.log(''continue'');
continue;
}
Si es imposible copiar esas células, simplemente continúe buscando otras.
range.isPartOfMerge ()
Parece que se implementó el método .isPartOfMerge()
(11 de septiembre de 2016).
Para que pueda verificar si un rango se fusionó como tal:
function testMerge() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Sheet1");
var range = sheet.getRange(1,1,2); // example for cells A1 and A2
Logger.log(range.isPartOfMerge());
}
Documentos https://developers.google.com/apps-script/reference/spreadsheet/range#ispartofmerge
ANTIGUO ENFOQUE
Publicando aquí otro enfoque que me gusta más que la respuesta aceptada.
Si intenta usar GAS para almacenar un valor en una celda de un rango combinado, excepto la primera celda, no la almacenará.
Como tal, podemos explotar esto e intentar almacenar el valor y verificar si fue almacenado, usando una función similar a esta:
function isMerged(range){
try {
range.getDataSourceUrl()
} catch (err) {
throw "isMerged function only works with valid GAS Range objects"
}
var sheet = range.getSheet();
var rangeData = range.getValues();
var testValue = "testing merge";
if (rangeData.length == 1 && rangeData[0].length == 1) return false; // we have a single cell. Can''t possible be merged :)
if (rangeData.length == 1) {
// We have a single row. Which means we''re testing a row with multiple columns
var mainCell=range.getA1Notation().split(":")[0];
var rowNumber= sheet.getRange(mainCell).getRow();
var nextColNumber = sheet.getRange(mainCell).getColumn()+1;
var row = rangeData[0];
var oldValue = row[1]; // for testing purposes, we''re chosing the next possible column
sheet.getRange(rowNumber,nextColNumber).setValue(testValue);
if (sheet.getRange(rowNumber,nextColNumber).getValue() !== testValue) {
return true;
} else {
sheet.getRange(rowNumber,nextColNumber).setValue(oldValue);
return false;
};
} else if (rangeData[0].length == 1) {
// We have multiple rows and a single column.
var mainCell=range.getA1Notation().split(":")[0];
var nextRowNumber= sheet.getRange(mainCell).getRow()+1;
var colNumber = sheet.getRange(mainCell).getColumn();
var oldValue = rangeData[1][0]; // for testing purposes, we''re chosing the next possible row
sheet.getRange(nextRowNumber,colNumber).setValue(testValue);
if (sheet.getRange(nextRowNumber,colNumber).getValue() !== testValue) {
return true;
} else {
sheet.getRange(nextRowNumber,colNumber).setValue(oldValue);
return false;
};
} else {
// We have multiple rows and multiple columns
var mainCell=range.getA1Notation().split(":")[0];
var nextRowNumber= sheet.getRange(mainCell).getRow()+1;
var nextColNumber = sheet.getRange(mainCell).getColumn()+1;
var oldValue = rangeData[1][1]; // for testing purposes, we''re chosing the next possible row and next possible column
sheet.getRange(nextRowNumber,nextColNumber).setValue(testValue);
if (sheet.getRange(nextRowNumber,nextColNumber).getValue() !== testValue) {
return true;
} else {
sheet.getRange(nextRowNumber,nextColNumber).setValue(oldValue);
return false;
};
}
// if none of these checks worked, something''s fishy. Either way, return false
return false
}
Realicé una serie de pruebas rápidas y devolvió true
/ false
consecuencia, pero hay una limitación que no tuve tiempo de cubrir: si tuvieras un rango combinado como "A1:F1"
y verificaste el rango "A1:G1"
(por lo tanto, una columna más), devolverá true
, incluso si G1 no es parte del rango fusionado, porque solo verifica la siguiente columna usando como referencia la primera fila / columna enlazada.