Script wont work on new sheets/spreadsheets - google-apps-script

I have been using this script for months, but now i wanted to add it to another sheets or spreadsheet and its not working, on old sheets where it was added moths ago it works fine.
Script is for hiding empty rows and showing rows that has values.
Maybe someone have any idea what to change in script so that it works again?
function hiderows() {
var ss = SpreadsheetApp.openById('1YoInjxlCeBPZP0HlEW0HSYBkdMCGtRaeJFylCQNXnMM');
sheets = ["Lapa1"]
for (var s = 0; s < sheets.length; s++) {
var sh = ss.getSheetByName(sheets[s]);
var firstRow = 1;
var firstCol = 1;
var data = sh.getDataRange().getValues();
var show = null, map = [], index, flag;
for (var i = firstRow - 1, length = data.length; i < length; i++) {
flag = false;
for (var j = firstCol - 1, width = data[0].length; j < width; j++) {
if (data[i][j] ) {
flag = true;
break;
}
}
if (show === flag) {
map[index].rows++;
} else {
index = i + 1;
show = flag;
map[index] = {rows: 1, show: show};
}
}
for (
var i in map) {
if (map[i].show) {
sh.showRows(i, map[i].rows);
} else {
sh.hideRows(i, map[i].rows);
}
}
}
}

Related

Google Sheet : The result could not be auto-expanded. Please insert new columns (1)

This script import opportunities that we get. It populates rows which then calculates some numbers such as interest and stuff. However, I now have errors when populating my cells (#REF error, see pictures below). Nothing has changed so my first guess is it has do with the processing of the sheet which has become too heavy.
`
function onInstall(e) {
onOpen(e);
}
function onOpen(e) {
var menu = SpreadsheetApp.getUi().createAddonMenu();
menu.addItem('Créer étude', 'init');
menu.addToUi();
}
function init() {
ss = SpreadsheetApp.getActiveSpreadsheet();
identifyJe();
sheetMaker = ss.getActiveSheet();
currentRow = ss.getActiveCell().getRowIndex();
ssEtudes = SpreadsheetApp.openById(getSheetEtudesId());
var ui = SpreadsheetApp.getUi();
var respon se = ui.alert(
'Ligne sélectionnée : ' + currentRow + '. Exécuter ?',
ui.ButtonSet.OK_CANCEL
);
if (response !== ui.Button.OK) return;
doEtude();
doContrat();
doPhases();
}
function doEtude(nomEtude) {
var etudeData = [];
for (var i = 0; i < etudeNamedRanges.length; i++) {
var column = ss.getRangeByName(etudeNamedRanges[i]).getColumn();
etudeData.push(sheetMaker.getRange(currentRow, column).getValue());
}
var destSheet = ssEtudes.getSheetByName('etudes');
var rowToAppend = getFirstEmptyRow(destSheet, 0);
for (var i = 0; i < etudeData.length; i++) {
var column = ssEtudes.getRangeByName(etudeNamedRanges[i]).getColumn();
destSheet.getRange(rowToAppend, column).setValue(etudeData[i]);
}
}
function doContrat() {
var contratData = [];
for (var i = 0; i < contratNamedRanges.length; i++) {
var column = ss.getRangeByName(contratNamedRanges[i]).getColumn();
contratData.push(sheetMaker.getRange(currentRow, column).getValue());
}
var destSheet = ssEtudes.getSheetByName('contrats');
var rowToAppend = getFirstEmptyRow(destSheet, 11);
for (var i = 0; i < contratData.length; i++) {
destSheet.getRange(rowToAppend, i + 4).setValue(contratData[i]);
}
}
function doPhases() {
var phasesCoords = getPhasesCoords();
var phasesData = [];
for (var i = 0; i < phasesCoords.length; i++) {
var phaseData = getPhaseData(phasesCoords[i]);
phaseData.unshift(i + 1);
phasesData.push(phaseData);
}
var destSheet = ssEtudes.getSheetByName('phases');
var rowToAppend = getFirstEmptyRow(destSheet, 9);
var columns = [];
for (var nPhase = 0; nPhase < phasesData.length; nPhase++) {
var phaseData = phasesData[nPhase];
for (var i = 0; i < phaseData.length; i++) {
if (columns[i] === undefined)
columns[i] = ssEtudes.getRangeByName(phasesNamedRanges[i]).getColumn();
destSheet
.getRange(rowToAppend + nPhase, columns[i])
.setValue(phaseData[i]);
}
}
}
`
Type of formula
The results
The error, which translates into The result could not be auto-expanded. Please insert new columns (1).
The results actually appear for some time and disappear after a few seconds, constantly. Does it have something to do with the size of the spreadsheet ?

GOOGLE SCRIPT Why a function is running when it's not called in the script?

I have a problem that I can't seem to be able to resolve. Basically, I have a Project where I have all my scripts. For some reason, all of a sudden and with no apparent reason, when I try to execute a script, it executes all the script at once... why does it happen? Specifically, I need to execute my script "copiaInEffettivo", but when I do it triggers the other 2 as well. Before this afternoon, everything was fine.
I copy here all my scripts together, but I highlight the fact that in the editor all these functions have their own separate file:
function colorazioneCaselle()
{
var ss = SpreadsheetApp.getActiveSpreadsheet();
var PRAG = ss.getSheetByName("PRAG");
var colors = ss.getSheetByName("colors");
var row = 3;
var col = 2;
var cella = colors.getRange(row, col);
var valcel = cella.getValue();
var i = 0;
while (col != 47) {
while (i != 24) {
if (valcel != "") {
var x = 0;
var y = 29;
while (x != 17) {
var cella2 = colors.getRange(y, 3).getValue();
if (valcel == cella2) {
var colore = colors.getRange(y, 1).getBackgroundColor();
PRAG.getRange(row + 1, col + 1).setBackgroundColor(colore);
x = 17;
}
else if (valcel != cella2) {
y++;
x++;
}
}
}
row++;
valcel = colors.getRange(row, col).getValue();
i++;
Logger.log("cella giù");
}
col++;
row = 3;
valcel = colors.getRange(row, col).getValue();
i = 0;
Logger.log("cambio colonna")
}
}
function controlloCasellaEffettivo() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var effettivo = ss.getSheetByName('effettivo');
var info = ss.getSheetByName('info');
var row = 3;
var row2 = 3;
var col = 7;
var col2 = 5;
var cellauno = effettivo.getRange(row, col);
var luogo = info.getRange(row2, col2);
for(var y = 0; y < 27; y++)
{
var i = 0;
while(i < 155)
{
if (cellauno.isChecked() === true)
{var contenuto = effettivo.getRange(row, 3).getValues();
luogo.setValues(contenuto);
row2++;
luogo = info.getRange(row2, col2);
}
row++;
cellauno = effettivo.getRange(row, col);
i++;
}
col++;
col2++;
row2 = 3;
row = 3;
luogo = info.getRange(row2, col2);
cellauno = effettivo.getRange(row, col);
}
}
colorazioneCaselle()
function copiaInEffettivo() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var pianificazione = ss.getSheetByName('pianificazione');
var effettivo = ss.getSheetByName('effettivo');
var contenuto = pianificazione.getRange(3, 3, 154, 30);
contenuto.copyTo(effettivo.getRange(3, 3));
pianificazione.hideSheet()
}
The first script basically applies color to cells based on their content, the second one extracts and transfers some informations into a sheet and the third one simply copies data from one sheet to another and then hides the first one. "ControlloCasellaEffettivo", as you can see, calls "ColorazioneCaselle" at the end. Any guesses on why this happens?

How to Change .getMergedRanges() From String to a Range?

The following code will run very slow in my Google Sheets because my getRange is too large. Is there a way to only loop through the columns that are merged? I only want the for loop to get the number of columns in "yourRange" that are merged.
function getUpfrontCosts() {
var sheet = SpreadsheetApp.getActive().getSheetByName('LPB_COST');
var cl , count=0;
var yourRange = sheet.getRange("H13:UV13");
for (var i = 1; i < yourRange.getNumColumns()+1; i++)
{
cl=yourRange.getCell(1, i);
if (cl.isPartOfMerge()){
if (cl.offset(15, 0).getBackground() == "#ff8300" && cl.getMergedRanges()[0].getCell(1, 1).getValue()=='Upfront Costs') {
count = count + cl.offset(15, 0).getValue();
}
else {
}
} else {
}
}
return count;
};
The second code is how I am trying to turn a string to a range. I am getting "Cell reference out of range" error
How can I change cl to not be a string and be a range?
function getUpfrontCosts()
{
var sheet = SpreadsheetApp.getActive().getSheetByName('LPB_COST');
var destSheet = SpreadsheetApp.getActive().getSheetByName('Top Level PN');
var cl , count=0;
var yourRange = sheet.getRange("I13:UZ13");
var mergedRanges = yourRange.getMergedRanges();
for (var i = 0; i < mergedRanges; i++){
}
var newRange = sheet.getRange(mergedRanges[i].getA1Notation());
Logger.log(newRange.getA1Notation());
for (var i = 0; i < newRange.getNumColumns()+1; i++){
cl=newRange.getCell(1, i);
Logger.log(newRange.getA1Notation());
if (cl.offset(15, 0).getBackground() == "#ff8300" && cl.getValue()=='Upfront Costs') {
count = count + cl.offset(15, 0).getValue();
}
else {
}
}
return count;
};
This is the line with the error
cl=newRange.getCell(1, i);
if you want to use merge cell range, you can do this:
function UntitledMacro1()
{
var sheet = SpreadsheetApp.getActive().getSheetByName('Sheet1');
var cl , count=0 ;
var yourRange = sheet.getRange("I13:UZ13");
var bb = yourRange.getMergedRanges();
for (a=bb[0].getColumn();a<bb[0].getLastColumn()+1;a++)
{
//Your actual columns from I13, for first merge range, here your cl,
//but if your range is ("13:13"), you don't need
//-sheet.getRange("I13").getColumn()+1
cl=yourRange.getCell(1, a-sheet.getRange("I13").getColumn()+1);
//For your offset 15
Logger.log(cl.offset(15, 0).getValue());
//on so on
}
};

Google Spreadsheet setBackgroundColors() "Deprecated"

A gs I have been using in the past to check for duplicates, is no longer working. The script would check all cells in the spread sheet if any were identical it would highlight all their occurrences green. I also had another function that would revert all the cells back to white.
setBackgroundColors() has been deprecated; people have been recommended to now use setBackground(). The script still doesn't work...
Here is my gs, make a copy and fiddle with it. Many Thanks...
https://docs.google.com/spreadsheets/d/1UELTxZRZPKQKU9NsQwNefvdxJDM0xDt8904sZy3etoY/edit#gid=0
Here is the script.
/**
* Retrieves all the rows in the active spreadsheet that contain data and logs the
* values for each row.
* For more information on using the Spreadsheet API, see
* https://developers.google.com/apps-script/service_spreadsheet
*/
function readRows() {
var sheet = SpreadsheetApp.getActiveSheet();
var rows = sheet.getDataRange();
var numRows = rows.getNumRows();
var values = rows.getValues();
for (var i = 0; i <= numRows - 1; i++) {
var row = values[i];
Logger.log(row);
}
};
/**
* Adds a custom menu to the active spreadsheet, containing a single menu item
* for invoking the readRows() function specified above.
* The onOpen() function, when defined, is automatically invoked whenever the
* spreadsheet is opened.
* For more information on using the Spreadsheet API, see
* https://developers.google.com/apps-script/service_spreadsheet
*/
function onOpen() {
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var entries = [{
name : "Check Directory",
functionName : "CheckDirectory"
}];
spreadsheet.addMenu("Script Center Menu", entries);
};
function CheckDirectory() {
var sheet = SpreadsheetApp.getActiveSheet();
var dataRange = sheet.getDataRange();
var data = dataRange.getValues();
var numRows = data.length;
var numColumns = data[0].length;
var formats = [];
var values = [];
for (var i = 0; i < numRows; i++) {
formats[i] = [];
for (var j = 0; j < numColumns; j++) {
formats[i][j] = 'white';
if (data[i][j] != '') {
values.push([data[i][j], i, j]);
}
}
}
var numValues = values.length;
for (var k = 0 ; k < numValues - 1; k++) {
if (formats[values[k][1]][values[k][2]] == 'white') {
for (var l = k + 1; l < numValues; l++) {
if (values[k][0] == values[l][0]) {
formats[values[k][1]][values[k][2]] = 'green';
formats[values[l][1]][values[l][2]] = 'green';
}
}
}
}
dataRange.setBackground(formats);
};
function resetCheckDirectory() {
var sheet = SpreadsheetApp.getActiveSheet();
var dataRange = sheet.getDataRange();
var data = dataRange.getValues();
var numRows = data.length;
var numColumns = data[0].length;
var formats = [];
var values = [];
for (var i = 0; i < numRows; i++) {
formats[i] = [];
for (var j = 0; j < numColumns; j++) {
formats[i][j] = 'white';
if (data[i][j] != '') {
values.push([data[i][j], i, j]);
}
}
}
var numValues = values.length;
for (var k = 0 ; k < numValues - 1; k++) {
if (formats[values[k][1]][values[k][2]] == 'white') {
for (var l = k + 1; l < numValues; l++) {
if (values[k][0] == values[l][0]) {
formats[values[k][1]][values[k][2]] = 'white';
formats[values[l][1]][values[l][2]] = 'white';
}
}
}
}
dataRange.setBackground(formats);
};
Use setBackgrounds(). With an s since it's a method that applies multiple background colors to multiple cells

"Reference does not exist" error when executing a custom function

I am writing a function in Google Apps Script and it seems the last error I need to get around is a "reference does not exist" error in Google Sheets when I call my function. I don't know what to do about this because it doesn't seem to be a problem with my code.
This is what my code looks like now. It isn't complete because I need to change it for user input, but this is a test.
In a google sheets cell I type in =sortingtesting()
function sortingtesting()
{
var pInfo1 = ['a','b','c','d','e','f','g','h','i','j','k','l','m','o','p','q','r','s']
var pInfo2 = ['a','b','c','d','e','f','g','h','i','j','k','l','m','o','p','q','r','s']
var pInfo3 = ['a','b','c','d','e','f','g','h','i','j','k','l','m','o','p','q','r','s']
var pWO = ['1','','','2','','','3','4','5','6','7','','','8','','','9','10']
var pSearch = ['c', 'b', 'a']
var WO = [];
var Info1 = [];
var Info2 = [];
var Info3 = [];
var Search = [];
for(var i = 0; i < 18; i++)
WO[i] = pWO[i];
for(var i = 0; i < 18; i++)
{
Info1[i] = pInfo1[i];
}
for(var i = 0; i < 18; i++)
{
Info2[i] = pInfo2[i];
}
for(var i = 0; i < 18; i++)
{
Info3[i] = pInfo3[i];
}
for(var i = 0; i < 1; i++)
Search[i] = pSearch[i];
// Declares secondary storage arrays and their counters
var FinalArray1 = [];
var FinalArray2 = [];
var FinalArray3 = [];
var LastArray = [];
var a = 0;
var b = 0;
var c = 0;
var d = 0;
// loop to run and make all of the cells in the work order row relevant to the work order number
for(var row = 0; row < WO.length; row ++)
{
var counter = row - 1;
while(WO[row] == "")
{
WO[row] = WO[counter];
counter--;
}
}
// loop that goes through saving which work orders meet certain search criteria, each search criteria has its own separate secondary array
for(var row = 0; row < Info1.length; row++)
{
if(Info1[row] == Search[0])
{
FinalArray1[a] = WO[row];
a++;
}
}
for(var row = 0; row < Info1.length; row++)
{
if(Info2[row] == Search[1])
{
FinalArray2[b] = WO[row];
b++;
}
}
for(var row = 0; row < Info1.length; row++)
{
if(Info3[row] == Search[2])
{
FinalArray3[c] = WO[row];
c++;
}
}
// loop to run through and get all the work orders that meet all of the criteria
for(var i = 0; i < FinalArray1.length; i++)
{
for(var j = 0; j < FinalArray2.length; j++)
{
for(var k = 0; k < FinalArray3.length; k++)
{
if(FinalArray3[k] == FinalArray2[j] && FinalArray2[j] == FinalArray1[i])
{
LastArray[d] = FinalArray1[i];
d++;
}
}
}
}
return LastArray;
}
Solution Found:
This is my working code with arrays coming in from google sheets as parameters and I just thought it would be nice to put the working prototype out there:
function sortingtesting(WO, Info, Search)
{
// Declares secondary storage arrays and their counters
var FinalArray1 = [];
var FinalArray2 = [];
var FinalArray3 = [];
var LastArray = [];
var a = 0;
var b = 0;
var c = 0;
var d = 0;
// loop to run and make all of the cells in the work order row relevant to the work order number instead of being blank
for(var row = 0; row < WO.length; row ++)
{
var counter = row - 1;
while(WO[row] == "")
{
WO[row] = WO[counter];
counter--;
}
}
// loop that goes through saving which work orders meet certain search criteria, each search criteria has its own separate secondary array to store the work orders that meet the criteria
for(var col = 0; col < Info[0].length; col++)
{
for(var row = 0; row < Info.length; row++)
{
if(Info[row][col] == Search[0])
{
FinalArray1[a] = WO[row];
a++;
}
else if(Info[row][col] == Search[1])
{
FinalArray2[b] = WO[row];
b++;
}
else if(Info[row][col] == Search[2])
{
FinalArray3[c] = WO[row];
c++;
}
}
}
LastArray[0] = 'N/A';
// loop to run through and get all the work orders that meet all of the criteria
for(var i = 0; i < FinalArray1.length; i++)
{
for(var j = 0; j < FinalArray2.length; j++)
{
for(var k = 0; k < FinalArray3.length; k++)
{
if(FinalArray3[k] == FinalArray2[j] && FinalArray2[j] == FinalArray1[i])
{
LastArray[d] = FinalArray1[i];
d++;
}
}
}
}
return LastArray;
}
TL;DR The function should not return an empty array.
By placing return "a valid string"; in various positions in the script (bisecting the code), you will see that return LastArray;` is causing the error.
By running the code in the debugger, LastArray is an empty array.
From experiments, an empty array is not a valid return value for a function called in a formula, neither is an array containing multiple values. An array of containing one integer is valid.
Changing var LastArray = []; to var LastArray = [1]; demonstrates this.