Exception Error with Google Script when I tried to use moveActiveSheet - google-apps-script

I keep getting "Exception: Service Spreadsheets failed while accessing document with id " while trying to run moveActiveSheet to move a sheet in tab with index 4 to index 1. This just happened very lately. I had been using my code for months before this happened. Does any body is facing the same thing?
My code is below
var ss = SpreadsheetApp.getActiveSpreadsheet();
//==========================================
//Arrange the Sheet
// Store all the worksheets in this array
var sheetNameArray = [];
var sheets = ss.getSheets();
for (var i = 0; i < sheets.length; i++) {
sheetNameArray.push(sheets[i].getName());
};
sheetNameArray.sort();
var sheetName = sheetNameArray[0]; //This tab is currently at index 4
var getSheet = ss.getSheetByName(sheetName);
Logger.log(getSheet.getIndex());
ss.setActiveSheet(getSheet);
ss.moveActiveSheet(1); //Trying to move it to index 1 but exception was thrown

Here is a work-around that worked for me, I loop through the sorted array. I used .batchUpdate from Sheets API. You have to enable it from advanced services first: Resources > Advanced Google Services
function move_sheet_func(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
//==========================================
//Arrange the Sheet
// Store all the worksheets in this array
var sheetNameArray = [];
var sheets = ss.getSheets();
for (var i = 0; i < sheets.length; i++) {
sheetNameArray.push(sheets[i].getName());
};
sheetNameArray.sort();
var sheetName = sheetNameArray[0]; //This tab is currently at index 4
var getSheet = ss.getSheetByName(sheetName);
var sheetsreq = [];
//create requests for each sheet to be moved to its index as sorted
sheetNameArray.forEach(function (name, indx) {
sheetsreq.push({ updateSheetProperties: {
fields: "index, title",
properties: {
index: indx,
title: name,
sheetId: ss.getSheetByName(name).getSheetId()
}
} });
});
var req = { "requests": sheetsreq };
console.log(JSON.stringify(req));
Sheets.Spreadsheets.batchUpdate(req, ss.getId());
}

Related

Printing the result in Google Sheet Console to the page

I found this function at How to get all tab names/gid:
function GetTabs() {
var app = SpreadsheetApp;
var ss = app.openById('1e4zL13L2b8Hs8sJcBw-3_pGjQBecZv_QO_LuSLUrieA');
var name = ss.getName();
Logger.log(name);
var tabs = new Array()
var sheets = ss.getSheets();
for (var i = 0; i < sheets.length; i++) tabs.push([sheets[i].getSheetId()])
//return tabs
Logger.log(tabs)
}
It lets me print the GID number of tabs in a spreadsheet to the console. How do I put these GIDs on Sheet2 of the active spreadsheet instead?
Use Sheet.appendRow(), like this:
function appendSheetIdsToSheet2() {
const sheetToPrintTo = SpreadsheetApp.getActive().getSheetByName('Sheet 2');
const ss = SpreadsheetApp.openById('1e4zL13L2b8Hs8sJcBw-3_pGjQBecZv_QO_LuSLUrieA');
sheetToPrintTo.appendRow([ss.getName()]);
ss.getSheets().forEach(sheet => sheetToPrintTo.appendRow([sheet.getSheetId()]));
}

=URL() Script code issue | ReferenceError: btn is not defined (line 9, file "Code")

I am having an issue trying to use a script to extract the URL from one test with hyperlink.
Here is the script I am using:
function URL(reference) {
var sheet = SpreadsheetApp.getActiveSheet();
var formula = SpreadsheetApp.getActiveRange().getFormula();
var args = formula.match(/=\w+\((.*)\)/i);
try {
var range = sheet.getRange(args[1]);
}
catch(e) {
throw new Error(args[1] + 'is not a valid range');
}
var formulas = range.getFormulas();
var output = [];
for (var i = 0; i < formulas.length; i++) {
var row = [];
for (var j = 0; j < formulas[0].length; j++) {
var url = formulas[i][j].match(/=hyperlink\("([^"]+)"/i);
row.push(url ? url[1] : '');
}
output.push(row);
}
return output
}
After I run the script I get this error message:
TypeError: Cannot read property '1' of null (line 9, file "Code")
Any idea where the issue comes from and I can solve this?
You have try/catch block that throws error, but in catch block you are trying to iterate null object again:
try {
var range = sheet.getRange(args[1]);
}
catch(e) {
throw new Error(args[1] + 'is not a valid range'); // <- `args[1]` is producing new error
}
If you change catch content to throw new Error(formula + 'is not a valid range');, it should work.
Retrieve the hyperlink with the Advanced Sheets Service and assign the script to a button
The way you are following so far (extracting a hyperlink from a formula) is an old solution that does not work anymore
Currently, to retrieve a spreadsheet you need to use the Sheets API method spreadsheets:get
To use the Sheest API in Apps Script, you need to enable it in the editor
Sample script:
function URL() {
var spreadsheet =SpreadsheetApp.getActive();
var sheet = spreadsheet.getActiveSheet();
var id = spreadsheet.getId();
var range = sheet.getActiveRange();
var linkArray = Sheets.Spreadsheets.get(id, {ranges: sheet.getName() + "!" + range.getA1Notation(), fields: "sheets/data/rowData/values/hyperlink"});
var link = linkArray.sheets[0].data[0].rowData[0].values[0].hyperlink;
var cellInB = sheet.getRange(range.getRow(), 2);
cellInB.setValue(link);
}
As mentioned in the comments, in your use case it is not possible to use custom formulas, instead create a drawing and assign the script to it:
Now, select a cell in column A, click on the button and the link will be populated in column B.
UPDATE:
To retrieve all URLs at once you can use the followign script and run it manually:
function getAllURLs() {
var spreadsheet = SpreadsheetApp.getActive();
var sheet = spreadsheet.getActiveSheet();
var id = spreadsheet.getId();
var lastRow = sheet.getRange("A2").getNextDataCell(SpreadsheetApp.Direction.DOWN).getRow();
var range = sheet.getRange(2,1,lastRow-1, 1);
var linkArray = Sheets.Spreadsheets.get(id, {ranges: sheet.getName() + "!" + range.getA1Notation(), fields: "sheets/data/rowData/values/hyperlink"});
var links = [];
for (var i = 0; i< linkArray.sheets[0].data[0].rowData.length; i++){
var link = linkArray.sheets[0].data[0].rowData[i].values[0].hyperlink;
links[i] = [];
links[i].push(link);
}
var cellsInB = sheet.getRange(2,2,lastRow-1, 1);
cellsInB.setValues(links);
}

Is it possible to export (using Google Scripts) a single sheet to PDF without hiding sheets?

I would like to be able to export a single specific sheet from a large workbook without having to hide the unrequired sheets. Is that actually possible with Google Scripts?
At the moment I am looping through a list of products, updating a query for each one and then exporting each result to an individual PDF. Basically creating a product "Printout" page for many products.
The code below works quite nicely but it starts by hiding all sheets other than my Printout page. That would be fine except some of the other sheets are protected and not all users that would be using my export functionality have the right to hide sheets.
I've considered adding an unprotect/protect function to my macro but it would be good to know if exporting a single sheet was an option before i went down this route?
The hiding sheets trick was from this post Export Single Sheet to PDF in Apps Script
function exportLoopedSheet(firstRow, lastRow) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheetName = 'Printout'; // update for print sheet name
var productSheetName = 'ProductList'; // update for final product list
var folderName = 'productPDFs';
var main = ss.getSheetByName(sheetName);
var sheets = ss.getSheets();
var productList = ss.getSheetByName(productSheetName);
var lastProductRow = lastRow;
var firstProductRow = firstRow;
// Hide all sheets other than the Print Sheet
for (var i = 0; i < sheets.length; i++) {
if (sheets[i].getSheetName() !== sheetName) {
sheets[i].hideSheet();
}
}
for (var prodNo = firstProductRow; prodNo < lastProductRow + 1; prodNo ++) {
var currentProduct = productList.getRange('A'+ prodNo).getValue();
main.getRange('B9').setValue(currentProduct);
// Ensure all changes are updated
SpreadsheetApp.flush();
// call the export sheet function
exportSheet();
}
// Unhide the sheets
for (i = 0; i < sheets.length; i++) {
sheets[i].showSheet();
}
}
function exportSheet() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheetName = 'Printout';
var main = ss.getSheetByName(sheetName);
var sheets = ss.getSheets();
//Hide All Empty Rows in the Print Sheet
var maxRows = main.getMaxRows();
var lastRow = main.getLastRow();
if (maxRows-lastRow != 0){
main.hideRows(lastRow+1, maxRows-lastRow);
}
// Save pdf version
var folder = 'productPDF';
var parentFolder = DriveApp.getFolderById('1234'); //add this line...
var folder, folders = DriveApp.getFoldersByName(folder);
if (folders.hasNext()) {
folder = folders.next();
} else {
folder = parentFolder.createFolder(folder);
}
var name = main.getRange("B8").getValue();
folder.createFile(ss.getBlob().setName(name));
// Unhide the rows again
var fullSheetRange = main.getRange(1,1,main.getMaxRows(), main.getMaxColumns());
main.unhideRow(fullSheetRange);
}

Trying to view sheet after opening spreadsheet with openById() in google sheets

I have a Google Sheets that has D3.JS, i'm trying to use a specific sheet in the spreadsheet file, since that's where the table is located for the graph i'm trying to show. So far, the openById works but still is unable to locate the specific sheet in the spreadsheet.
function getChartData() {
var ss = SpreadsheetApp.openById("some id");
var sheet = ss.getActiveSheet();
var headings = sheet.getRange(1, 1, 1, sheet.getLastColumn()).getValues()[0]
.map(function(heading) {
return heading.toLowerCase();
});
...
}
EDIT: I've tried the following code changes below:
function getChartData() {
var ss = SpreadsheetApp.openById("some id");
var sheet = ss.getSheetByName("Tracker1");
// new code above
var headings = sheet.getRange(1, 1, 1, sheet.getLastColumn()).getValues()[0]
.map(function(heading) {
return heading.toLowerCase();
});
Logger.log(headings);
var values = sheet.getRange(3, 1, sheet.getLastRow()-2, sheet.getLastColumn()).getValues();
var data = [];
for (var i = 0; i < values.length; i++) {
var obj = {};
for (var j = 0; j < values[i].length; j++) {
obj[headings[j]] = values[i][j];
}
data.push(obj);
}
return data;
}
EDIT 10/2/18 11:00 PM : I'm still getting null, no error messages, no chart showing in app. I'm sure I'm doing something wrong, even without having getActiveSheet();

Google App Script - getCommenter

I'm brand new to Google Apps Script, and I'm trying to create a simple spreadsheet that will allow me to share files by user email through a single spreadsheet.
I have written the following script, which will allow me to add editors and viewers, but not commenters.
I keep getting an error that states that the function addCommenter cannot be found in object spreadsheet.
function shareSheet () {
var ss = SpreadsheetApp.getActiveSpreadsheet();
ss.toast('Updating access level...');
var sheet = ss.getSheets()[0];
var lastRow = sheet.getLastRow();
var range1 = sheet.getRange (3,1, lastRow,9);
var data = range1.getValues();
for (var i= 0; i < data.length; i++) {
var row = data [i];
var accessLevel = row [5];
var values = row [8];
var ss2 = SpreadsheetApp.openById(values);
var values2 = row [4];
// Add new editor
if (accessLevel == 'Edit') {
var addEditors = ss2.addEditor(values2);
}
// Add new viewer
if (accessLevel == 'View'){
var addViewers = ss2.addViewer(values2);
}
// Add new commenter
if (accessLevel == 'Comment') {
var addCommenters = ss2.addCommenter(values2);
}
}
}
The Spreadsheet object does not support the addCommentor() method. You should use DriveApp service instead.
DriveApp.getFileById(id).addCommenter(emailAddress)