Undefined error on google spreadsheet script - google-apps-script

I am desperately looking for some help about an error I keep getting when running a function on a Google Spreadsheet.
I have written all the code and I get two situations:
if I run the script from the sheet where it is supposed to work, I get the error "Oops
We're sorry. The server encountered an error. Please press "OK" to refresh the sheet" even though all the operations are actually completed below the error popup.
if I run the script from another sheet the script is completed successfully.
I thought this problem could have been related to the active sheet function, so I started debugging to find a solution. I noticed I get absolutely no problems with all of the code except a part in which I ask the spreadsheet to make some operations on the columns: first to create a new one, then to resize two of them and eventually to delete one.
I am attaching all the code so that you can get a better idea of what the script is doing.
Thank you for your attention.
Tony
function forecastSettimanale() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var data = sheet.getDataRange();
// I need to operate on a column that has TOT written on its top, and its
// position can vary
var k = 1;
while (k <= data.getNumColumns()) {
var startRange = sheet.getRange(1, k, 1);
var value = startRange.getValue();
if(value == 'TOT') {
var flagColumn = startRange.getColumn(); //
}
k++;
}
sheet.insertColumnsBefore(flagColumn, 1);
sheet.setColumnWidth(flagColumn - 1, 40);
sheet.setColumnWidth(flagColumn, 50);
sheet.deleteColumn(flagColumn - 6);
sheet.setColumnWidth(flagColumn, 100);
}
NEW edited code with your suggestion:
function forecastSettimanale() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var data = sheet.getDataRange();
var searchElement = 'TOT';
var firstRow = 1, firstColumn = 1, rows = 1;
var lastColumn = sheet.getLastColumn();
var lastRow = sheet.getLastRow();
var range = sheet.getRange(firstRow, firstColumn, rows, lastColumn).getValues();
var flagColumn = range[0].lastIndexOf(searchElement) + 1;
sheet.setColumnWidth(flagColumn - 1, 40);
sheet.deleteColumn(flagColumn - 6);
sheet.insertColumns(flagColumn - 1);
var cellLeggiData = sheet.getRange(2, 3, 1);
var cellData = sheet.getRange(1, flagColumn - 1, 1);
cellData = cellData.setValue(cellLeggiData.getValue());
var last_row = sheet.getLastRow();
var copiaDa = sheet.getRange(2, flagColumn, last_row - 1);
var copiaA = sheet.getRange(2, flagColumn - 1, last_row - 1);
copiaDa.copyTo(copiaA, {contentsOnly: true});
for (var i = 35; i <= lastRow; i+=33) {
var cellaFormula = sheet.getRange(i, flagColumn, 1);
var rigaPrecedente = i - 1;
var totN = sheet.getRange(rigaPrecedente, flagColumn, 1);
var totFore = sheet.getRange(rigaPrecedente, flagColumn - 1, 1);
var letteraColonna = String.fromCharCode(64 + flagColumn);
var letteraColonnaMenoUno = String.fromCharCode(63 + flagColumn);
cellaFormula.setFormula("=" + letteraColonnaMenoUno + rigaPrecedente + "-" + letteraColonna + rigaPrecedente);
}
sheet.setColumnWidth(flagColumn - 1, 100);
sheet.showColumns(flagColumn - 6, 6);
}

I can not reproduce the problem. The code in question works without problem, as you indicate. Maybe you have to do some validations such as, for example, in sheet.deleteColumn(flagColumn - 6); What if flagColumn is less than 6?
I modified a bit the way to get the column that is needed.
/* CODE FOR DEMONSTRATION PURPOSES */
function forecastSettimanale() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var searchElement = 'TOT';
var firstRow = 1, firstColumn = 1, rows = 1;
var lastColumn = sheet.getLastColumn();
var range = sheet.getRange(firstRow, firstColumn, rows, lastColumn).getValues();
var flagColumn = range[0].lastIndexOf(searchElement);
if (flagColumn > -1) {
++flagColumn;
sheet.insertColumnsBefore(flagColumn, 1);
sheet.setColumnWidth(flagColumn - 1, 40);
sheet.setColumnWidth(flagColumn, 50);
sheet.deleteColumn(flagColumn - 6);
sheet.setColumnWidth(flagColumn, 100);
}
}
Try to debug line by line to determine the method generates the error, that way it will be easier to find a solution.

Related

Iterate through column A and do until empty cell

My script is working but it times out. I am unsure as to what I can do to keep it from doing this.
function archived(e) {
var sheet = SpreadsheetApp.getActive().getSheetByName('IVA');
const targetSheet = e.source.getSheetByName('Archived Videos');
const numColumnsToMove = 20;
var sheetTo = SpreadsheetApp.getActive().getSheetByName('IVA');
var myValues = sheetTo.getRange('A:A').getValues();
var i;
for (i = 0; i < myValues.length; i++) {
if (myValues[i][0] === '')
return i + 1;
const rangeToMove = sheet.getRange(e.range.rowStart, 1, 1, numColumnsToMove);
const values = rangeToMove.getValues();
appendRowsV(targetSheet, values, 1);
sheet.deleteRows(e.range.rowStart, 1);
var lRow = sheet.getLastRow();
var lCol = sheet.getLastColumn(), range = sheet.getRange(lRow,1,1,lCol);
sheet.insertRowsAfter(lRow, 1);
range.copyTo(sheet.getRange(lRow+1, 1, 1, lCol), {contentsOnly:false});
}
}
As an FYI my sheet has 1500 rows and 15 columns. don't know if that is important or not.
Just in case. As far as I can tell from your code you're trying to append all data from the sheet 'IVA' at the bottom of the sheet 'Archived Videos'. It can be done this way:
function myFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var src_range = ss.getSheetByName('IVA').getDataRange();
var dest_sheet = ss.getSheetByName('Archived Videos');
var last_row = dest_sheet.getLastRow() + 1;
var dest_range = dest_sheet.getRange('A' + last_row);
src_range.copyTo(dest_range);
}

get active sheet email, and a small problem on my code

I have two issues on my code, due to my luck of experience in coding, the code that I have is made to copy rows with a specific cell value, in my case it's 'commande confirmer', the first problem that I have is the first line of my values even if it has the specific value it's not copying but on other lines it's working perfectly.
And for the 2nd issue I want to get also when the data copied it transfer with it to the active sheet email, I found how to get it, but how to include it and being transferred I couldn't make it.
Here is my code
and thanks in advance.
var ss = SpreadsheetApp.getActiveSpreadsheet();
var copySheet = ss.getSheetByName("Sheet1");
var url = "https://docs.google.com/spreadsheets/d/15nIAXcP0a14OvvBr5lww4tO23stQD4PEu0QDAcgaFyE/edit?ouid=112360896426304156672&usp=sheets_home&ths=true";
var ss2 = SpreadsheetApp.openByUrl(url);
var pasteSheet = ss2.getSheetByName("Sheet2");
// get source range
var max = copySheet.getMaxRows().toString();
var email= Logger.log(Session.getActiveUser().getEmail());
var range = copySheet.getRange(2, 1, max, 10);
var dataValues = range.getValues();
for (i = 1; i < dataValues.length; i++) {
if (dataValues[i][9] === 'COMMANDE CONFIRMER') {
pasteSheet.appendRow([dataValues[i][0],
dataValues[i][email],
dataValues[i][1],
dataValues[i][2],
dataValues[i][3],
dataValues[i][4],
dataValues[i][5],
dataValues[i][6],
dataValues[i][7],
dataValues[i][8],
dataValues[i][9]]);
var clearRow = i + 2;
copySheet.getRange('A' + clearRow + ':J' + clearRow).clear();
}
}
// get destination range
var destination = pasteSheet.getRange(pasteSheet.getLastRow() + 1, 1, max, 1);
// clear source values
Browser.msgBox('Commande Confirmer');
}
Try it this way:
function funko() {
var ss = SpreadsheetApp.getActive();
var csh = ss.getSheetByName("Sheet1");
var ss2 = SpreadsheetApp.openByUrl("https://docs.google.com/spreadsheets/d/15nIAXcP0a14OvvBr5lww4tO23stQD4PEu0QDAcgaFyE/edit?ouid=112360896426304156672&usp=sheets_home&ths=true");
var psh = ss2.getSheetByName("Sheet2");
var email = Session.getActiveUser().getEmail();
var range = csh.getRange(2, 1, csh.getLastRow() - 1, 10);
var cvs = range.getValues();
let oA = [];
cvs.forEach((r, i) => {
if (r[9] == 'COMMANDE CONFIRMER') {
let t = r.slice();
t.splice(1, 0, email);
oA.push(t);
csh.getRange(i + 1, 1, 1, csh.getLastColumn()).clearContent();
}
});
psh.getRange(psh.getLastRow() + 1, 1, oA.length, oA[0].length).setValues(oA);
Browser.msgBox('Commande Confirmer');
}

Google Sheets Concatenate Google Apps Script

I'm new to javascript and a novice coder. I have been trying to write a simple script for a Google Sheet to concatenate two columns of data into another column:
My script below runs fine but only produces Aaron Ward as line 1 of Desired Column C. I'm sure it is really simple what I am missing, but if anyone has a minute to help a rookie, I'd really appreciate it.
function concatenate() {
var sheet = SpreadsheetApp.getActiveSheet();
var data = sheet.getDataRange().getValues();
var lr = sheet.getLastRow()
var values1 = sheet.getSheetValues(1, 1, lr, 1);
var values2 = sheet.getSheetValues(1, 2, lr, 1);
var results = [];
for (var i = 0; i < lr; i++) {
results = [values1[i] + " " + values2[i]];
Logger.log(results);
sheet.getRange(1, 3, results.length).setValues([results]);
}
}
Why not using a formula? In C1 place the formula =JOIN(“ “,A1:B1) and drag it to the last row.
You're very close. In your for-loop, you need to push() the concatenated string into your results array. Then you can setValues(results) after the for-loop.
function concatenate() {
var sheet = SpreadsheetApp.getActiveSheet();
var data = sheet.getDataRange().getValues();
var lr = sheet.getLastRow()
var values1 = sheet.getSheetValues(1, 1, lr, 1);
var values2 = sheet.getSheetValues(1, 2, lr, 1);
var results = [];
for (var i = 0; i < lr; i++) {
results.push([values1[i] + " " + values2[i]]);
}
sheet.getRange(1, 3, results.length).setValues(results);
}
You can either use this
function conCat(){
var ss = SpreadsheetApp.getActiveSpreadsheet()
var ws = ss.getSheetByName("your sheet name")
var data = ws.getDataRange().getValues()
for(var k = 1;k<data.length;k++){
var row = data[k]
var merge = row[0]+" "+row[1]
ws.getRange(k+1,3).setValue(merge)
}
}
This code will simply take values from first and second column and concatenate result will show in third column

Google Apps Script : Insert x rows after every cells in range

I'm trying to add x blank rows after every no blank cells in a range.
I use a loop but with my loop, only the first cell is affected.
Here, my code :
I think I know where I'm wrong (I need to loop in sheet.insertRowsAfter(i, 5); but I can not do it...)
Thank you !
function insertRows() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("test");
var sourceRange = sheet.getRange(10, 1, sheet.getLastRow());
var sheetData = sourceRange.getValues();
var numRows = sourceRange.getNumRows();
Logger.log(numRows);
for (var i=10; i < numRows; i++) {
sheet.insertRowsAfter(i, 5);
}
}
In your case we need to start at the end of the range and work our way up, adding rows where appropriate. The code below will do this and add a 5 rows below any row which has data, even adding rows if there is a blank row following the one with data. You could pass startRow to the function if you wish for more flexibility
function insertRows() {
var startRow = 10;
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("test");
var sourceRange = sheet.getRange(startRow, 1, sheet.getLastRow());
var sheetData = sourceRange.getValues();
var numRows = sourceRange.getNumRows() - startRow;
// Logger.log(numRows);
for (var i=numRows; i > -1; i--) {
if (sheetData[i].join("")) {
sheet.insertRowsAfter(i + startRow, 5);
}
}
}
As a general comment: You are retrieving more rows as necessary as sheet.getLastRow() gets the last row number with data and the use in getRange() is telling the app to pull that number of rows as opposed to that number minus the starting position.
Try the below. This will add 3 rows when there is a no blank cell.
function insertRows() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("test");
var sourceRange = sheet.getRange(1, 1, sheet.getLastRow());
var sheetData = sourceRange.getValues();
for (var i=0; i < sheetData.length; i++) {
if(sheetData[i][0]!=""){
sheet.insertRowsAfter(i+1, 3);
sheetData = sheet.getRange(1, 1, sheet.getLastRow()).getValues();
}
}
}

Google Script to delete row if date in certain cell is smaller than current date

I want a Google Script which checks once a day on my spreadsheet and copies the values to another sheet and than deletes all the rows if the date in that cell is small than the current.
The file looks like this:
And this is what I wrote so far:
function DeleteIfDateIsToSmall(event) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = event.source.getActiveSheet();
var r = event.source.getActiveRange();
var today = new Date();
var today2 = Utilities.formatDate(today,'GMT+0200','dd.MM.yyyy');
var startRow = 2; // First row of data to process
var numRows = sheet.getLastRow()-1
for (var i=2; i < numRows; i++) {
var DateCell = s.getRange(i, 13);
var sheetDate = DateCell.getValue()
var sheetDate2 = Utilities.formatDate(sheetDate,'GMT+0200','dd.MM.yyyy');
var row = i;
var numColumns = s.getLastColumn();
var targetSheet = ss.getSheetByName("Ended or Deleted");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
if (s.getName() == "Start" && sheetDate != 0 && sheetDate != "" && today2.valueOf() > sheetDate2.valueOf()){
s.getRange(row, 1, 1, numColumns).moveTo(target);
s.deleteRow(row);
}
}
}
It doesn't seem to work, please help.
A few things are wrong or suboptimal here.
For a timed trigger, the event object does not have any range/source data; it only has time data. You need to pick a sheet by name (or loop through all sheets obtained by getSheets, if this is what you want).
Utilities.formatDate returns a string, which is not the best way to compare dates; in any case calling valueOf on it seems pointless.
Instead of using getValue in a loop, it is more efficient to obtain values before entering the loop, with getValues. There are some other things you do in the loop that should be outside.
Deleting rows when moving top to bottom in a sheet is tricky, because rows shift, messing up their indexing. For this reason, I collect the rows to be deleted in an array, and then delete them in bottom-to-top order.
function DeleteIfDateIsTooSmall() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getSheetByName("Start");
var numColumns = s.getLastColumn();
var targetSheet = ss.getSheetByName("Ended or Deleted");
var today = new Date();
var dates = s.getRange(2, 13, s.getLastRow()-1, 1).getValues();
var rowsToDelete = [];
for (var i = 0; i < dates.length; i++) {
if (dates[i][0] && dates[i][0] < today) {
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(i + 2, 1, 1, numColumns).moveTo(target);
rowsToDelete.push(i + 2);
}
}
for (i = rowsToDelete.length - 1; i >= 0; i--) {
s.deleteRow(rowsToDelete[i]);
}
}