I am getting an unexpected error when trying to write a Javascript object - javascript

I get the following message when I try to save this code from the script editor on Google Sheets: "We're sorry, an unexpected error occurred during compilation." The code creates a class with a method.
If it doesn't create a method I don't get the error, but the point of the object is the method. I did this in the past in another Sheets application, but I can't even get it to work for a simple example.
function myFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet(); // curr active spreadsheet
var theSheet = ss.getActiveSheet(); // current active sheet
var aLogger = tLogger(theSheet, 5, 1, 5); // set up a logger
aLogger.tLog("A test line: 1");
}
// object to do logging on a sheet
function tLogger(ourSheet, startLine, startCol, logLength) {
// object properties:
this.curline = startLine;
this.sheetRef = ourSheet;
this.theColumn = startCol;
this.maxLog = startLine + logLength;
ourSheet.getRange(startLine, startCol, logLength, 1).clear(); // clear old
// including this is what causes the error:
function this.tLog(tText) { // log an entry on the sheet
this.sheetRef.getRange(this.curline++, this.theColumn).setValue(tText);
return;
}
return;
}

Re-code it with ES6 something like above
class tLogger {
constructor(ourSheet, startLine, startCol, logLength) {
this.curline = startLine;
this.sheetRef = ourSheet;
this.theColumn = startCol;
this.maxLog = startLine + logLength;
}
}

Related

Google Sheets Scripts - run scripts as administrator / owner

I have Google Sheet, name TEST https://docs.google.com/spreadsheets/d/1HsRwknyZBmZZ9nibDfNpOwqkVsFGThDyrTwspV-5_4U/edit?usp=sharing
Sheet: Arkusz 1
Column A: all people can edit
Column B: only owner can edit
Library (for everyone): https://script.google.com/macros/s/AKfycbzpnEMhIG-0dMp54q3W4UxoT71-lSdfF7Qxf7rq_j6gJMNIxuCS/exec
A user cannot add a row because it is blocked by column B, which belongs only to the admin.
How can I create macro, which allow user to add new rows?
I have three scripts:
function insertRow() {
var ss = SpreadsheetApp.getActive()
var sheetName = ss.getActiveSheet().getName()
var row = ss.getActiveRange().getRow()
var numRows = Browser.inputBox('Insert Rows', 'Enter the number of rows to insert', Browser.Buttons.OK);
Logger.log(numRows)
var url ="https://script.google.com/macros/s/AKfycbzpnEMhIG-0dMp54q3W4UxoT71-lSdfF7Qxf7rq_j6gJMNIxuCS/exec"
var queryString = "?sheetName="+sheetName+"&rowNo="+row+"&noOfRows="+numRows
url = url + queryString
Logger.log(url)
var request = UrlFetchApp.fetch(url)
if (request != 'Success')
Browser.msgBox(request)
}
Second:
function doGet(e) {
var param = e.queryString
var parameters = param.split("&")
// This just checks only 3 parameters are present else gives a invalid link
if (param != null && parameters.length == 3){
param = e.parameter
var name = param.sheetName
var row = Number(param.rowNo)
var numOfRows = Number(param.noOfRows)
} else{
return ContentService.createTextOutput("Invalid query")
}
try{
var ss = SpreadsheetApp.openById("https://docs.google.com/spreadsheets/d/1HsRwknyZBmZZ9nibDfNpOwqkVsFGThDyrTwspV-5_4U")
var sheet = ss.getSheetByName(name)
sheet.insertRowsAfter(row, numOfRows);
var source_range = sheet.getRange(row,1,1,sheet.getLastColumn());
var target_range = sheet.getRange(row+1,1,numOfRows);
source_range.copyTo(target_range);
}
catch (err){
return ContentService.createTextOutput("error: "+err)
}
return ContentService.createTextOutput("Success")
}
And after clicked function insertRow and filled number of rows I have doPost(e) information.
Could you help me?
On the solution you provided below, I see that the issue is in mainScript
function mainScript(e) {
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet()
// assign the sheet to a variable and use it below instead of spreadsheet
var sheet = spreadsheet.getSheetByName('ZNC')
sheet.getRange('A2').activate()
sheet.insertRowsBefore(sheet.getActiveRange().getRow(), 1);
}
Hmm, I created solution, but I think there's a bug somewhere, because it doesn't add the line, even though everything is correct and the script is published as public.
function ZNCWiersz() {
var spreadsheet = SpreadsheetApp.getActive();
spreadsheet.setActiveSheet(spreadsheet.getSheetByName('ZNC'), true);
const activeSheet = SpreadsheetApp.getActiveSheet().getSheetName();
const url = ScriptApp.getService().getUrl();
UrlFetchApp.fetch(`${url}?sheetName=${activeSheet}`, {
headers: { authorization: "Bearer " + ScriptApp.getOAuthToken() },
});
// DriveApp.getFiles() // This is used for automatically detecting the scope of "https://www.googleapis.com/auth/drive.readonly". This scope is used for the access token.
}
// When runScript() is run, this function is run.
const doGet = (e) => ContentService.createTextOutput(mainScript(e));
// This script is run by Web Apps.
function mainScript(e) {
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet()
spreadsheet.getSheetByName('ZNC')
spreadsheet.getRange('A2').activate()
spreadsheet.insertRowsBefore(spreadsheet.getActiveRange().getRow(), 1);
}

If GoogleJsonResponseException: then skip and move to next row

I have a working script. need to improvise to have no manual interruption. We have multiple Profiles in Analytics, sometimes we lose access and sometimes we have. So when i run the Script, If we lost access to 1 of 60 profiles, i have to delete that entry manually then rerun the script.
What i want is, If there is below error, Then skip and continue with next row
"GoogleJsonResponseException: API call to analytics.data.ga.get failed with error: User does not have sufficient permissions for this profile."
function GoogleAnalytics() {
var doc2 = SpreadsheetApp.getActiveSpreadsheet();
var dashboard = doc2.getSheetByName("Dashboard");
for(var i=52;i<65;i++){
var viewId = dashboard.getRange(i,13).getValue(); // Your Google Analytics view ID
var metric = 'ga:metric, ga:metric2, ga:metric3';
var option = {'segment': 'gaid::-5'};
var result = Analytics.Data.Ga.get(viewId, metric, option);
var metric = result.totalsForAllResults['ga:metric'];
var metric2 = result.totalsForAllResults['ga:metric2'];
var metric3 = result.totalsForAllResults['ga:metric3'];
var doc = SpreadsheetApp.getActiveSpreadsheet(); // Current document
var sheet = doc.getActiveSheet(); // Current sheet
sheet.getRange(i,14,1,1).setValue(metric);
sheet.getRange(i,15,1,1).setValue(metric2);
sheet.getRange(i,16,1,1).setValue(metric3);
} }
try it this way:
function GoogleAnalytics() {
var doc2 = SpreadsheetApp.getActiveSpreadsheet();
var sh = doc2.getSheetByName("Dashboard");
var sheet = doc2.getActiveSheet(); // Current sheet
const vs = sh.getRange(52, 13, 13).getValues();
var metric = 'ga:metric, ga:metric2, ga:metric3';
var option = { 'segment': 'gaid::-5' };
for (var i = 0; i < vs.length; i++) {
var viewId = vs[i][0]; // Your Google Analytics view ID
try {
var result = Analytics.Data.Ga.get(viewId, metric, option);
}
catch(e){
continue;
}
if (result) {
sheet.getRange(i + 52, 14, 1, 3).setValues([[result.totalsForAllResults['ga:metric'], result.totalsForAllResults['ga:metric2'], result.totalsForAllResults['ga:metric3']]]);
}
}
}
Without the benefit of working data some of this may not be correct but using setValues and getValues should speed it up considerably and the try catch blocks should help with not getting result consistently. Also you want to avoid making unnecessary declarations in loops.
I might understand the question incorrectly (if so, please clarify) but it sounds to me like you just need to add...
function GoogleAnalytics() {
var doc2 = SpreadsheetApp.getActiveSpreadsheet();
var dashboard = doc2.getSheetByName("Dashboard");
for(var i=52;i<65;i++){
try { //...this line and...
var viewId = dashboard.getRange(i,13).getValue(); // Your Google Analytics view ID
var metric = 'ga:metric, ga:metric2, ga:metric3';
var option = {'segment': 'gaid::-5'};
var result = Analytics.Data.Ga.get(viewId, metric, option);
var metric = result.totalsForAllResults['ga:metric'];
var metric2 = result.totalsForAllResults['ga:metric2'];
var metric3 = result.totalsForAllResults['ga:metric3'];
var doc = SpreadsheetApp.getActiveSpreadsheet(); // Current document
var sheet = doc.getActiveSheet(); // Current sheet
sheet.getRange(i,14,1,1).setValue(metric);
sheet.getRange(i,15,1,1).setValue(metric2);
sheet.getRange(i,16,1,1).setValue(metric3);
} catch(e) { //...this part
console.log(e); //optional, catch(e){} is perfectly valid as well, or any code you might want to execute on error
}
} }

Google Apps Scripts: Class notation and new Objects

I am trying to create a class to import Google Sheets tables into a more maneuverable. The code:
class SheetData{
constructor(worksheet, spreadsheet=null) {
this.spreadsheet = spreadsheet ? spreadsheet : SpreadsheetApp.getActive();
this.sheet = this.spreadsheet.getSheetByName(worksheet);
this.values = this.sheet.getDataRange().getValues();
}
get records() {
let cols = this.values[0], temp = {}, out = [];
for (let row of this.values.slice(1)){
cols.forEach( (colName,idx) => temp[colName] = row[idx] );
out.push(temp);
temp = {};
}
}
How ever when I try to run it on a sheet Logger.log(new SheetData('Sheet1').values), I get an Unexpected identifier at the new. What am I doing wrong? I also am not getting any syntax highlighting in the editor, even though I have the V8 runtime enabled.
How about this modification?
Modification points:
If you are testing your script in your question, I think that in your script, } is required to be added at the last line (
} is one shortage.).
I think that this might be the reason of your issue.
And, new SheetData('Sheet1').records is run, undefined is returned. Because no value is returned.
When above points are reflected to your script, it becomes as follows.
Modified script:
class SheetData{
constructor(worksheet, spreadsheet=null) {
this.spreadsheet = spreadsheet ? spreadsheet : SpreadsheetApp.getActive();
this.sheet = this.spreadsheet.getSheetByName(worksheet);
this.values = this.sheet.getDataRange().getValues();
}
get records() {
let cols = this.values[0], temp = {}, out = [];
for (let row of this.values.slice(1)){
cols.forEach( (colName,idx) => temp[colName] = row[idx] );
out.push(temp);
temp = {};
}
return out; // <--- Added
}
} // <--- Added
// Please run this function.
function main() {
var s = new SheetData('Sheet1');
console.log(s.values); // or Logger.log(s.values);
console.log(s.records); // or Logger.log(s.records);
}
Note:
Please confirm whether V8 runtime is enabled again.

Cannot read property "0" from undefined

Cannot read property "0" from undefined.
I can not find the problem
function sendSurvey() {
var recipient = Browser.inputBox("Send Survey", "Enter Recipient Email", Browser.Buttons.OK_CANCEL);
if (recipient === 'cancel') return;
var subject = 'Commuting Survey';
var scriptUrl = ScriptApp.getService().getUrl();
if (!scriptUrl) throw new Error( 'You must Deploy as Web App first.' );
var template = HtmlService.createTemplateFromFile('emailTemplate');
template.scriptUrl = scriptUrl;
template.serialNumber = getGUID(); // Generate serial number for this response
var html = template.evaluate().getContent();
var plainText = 'Please complete this survey online at: ' + scriptUrl;
html += '<p>Alternatively, you may complete this survey online.';
GmailApp.sendEmail(recipient, subject, plainText, {htmlBody:html} );
Browser.msgBox("Survey Sent");
}
function doGet() {
// Build survey body
var template = HtmlService.createTemplateFromFile('emailTemplate');
template.scriptUrl = ScriptApp.getService().getUrl();
template.serialNumber = getGUID(); // Generate serial number for this response
var app = template.evaluate();
return app;
}
function doPost(e) {
Logger.log(e);
var ss = SpreadsheetApp.openById(_spreadsheetId);
var sheet = ss.getSheets()[0]; // Assume first sheet collects responses
var row = [
new Date(), // Timestamp
e.parameters.serial[0], // Serial Number
e.parameters.pytanie1[0], // Pytanie 1
e.parameters.pytanie2[0], // Pytanie 2
];
var lock = LockService.getPublicLock();
// Wait for up to 30 seconds for other processes to finish.
var locked = lock.tryLock(30000);
if (locked) {
var rowNum = sheet.getLastRow()+1;
sheet.getRange(rowNum, 1, 1, row.length).setValues([row]);
// Release the lock so that other processes can continue.
lock.releaseLock();
var result = "Response Recorded: \n "+row.join('\n ');
}
else {
// Failed to get lock
result = "System busy, please try again.";
}
// Report result of POST, in plain text
return ContentService.createTextOutput(result)
.setMimeType(ContentService.MimeType.TEXT);
}
Cannot read property "0" from undefined.
I can not find the problem
Cannot read property "0" from undefined.
I can not find the problem
Cannot read property "0" from undefined.
I can not find the problem
Cannot read property "0" from undefined.
I can not find the problem
You have one of this problems:
The ss.getSheets function returns undefined (After I've read the documentation I saw that this isn't possible)
One of this properties of the e.parameters object doesn't exist:
serial
pytanie1
pytanie2
You can add some console.logs to see which is the property that doesn't exist...
Try to remove the comma (,) after e.parameters.pytanie2[0]
var row = [
new Date(), // Timestamp
e.parameters.serial[0], // Serial Number
e.parameters.pytanie1[0], // Pytanie 1
e.parameters.pytanie2[0]**,** // Pytanie 2
];

pass argument to mouseCallback

I have a simple, but problematic question.
Is there a way, using google script to send an argument to a mouseCallback?
Some examples are explained here, but each time the cell in written in the function.
I want this cell to change over time, and I need to pass a string to the callback.
This works
function foo() {
var doc = SpreadsheetApp.getActiveSpreadsheet();
var app = UiApp.createApplication();
var button = app.createButton('submit');
app.add(button);
var handler = app.createServerClickHandler('b');
button.addClickHandler(handler);
doc.show(app);
}
function b() {
var doc = SpreadsheetApp.getActiveSpreadsheet();
var cell = doc.getRange('a1');
cell.setValue(Number(cell.getValue()) + 1);
var app = UiApp.getActiveApplication();
app.close();
// The following line is REQUIRED for the widget to actually close.
return app;
}
I would like something like this
function foo() {
var doc = SpreadsheetApp.getActiveSpreadsheet();
var app = UiApp.createApplication();
var button = app.createButton('submit');
app.add(button);
var value = 'A1';
var handler = app.createServerClickHandler('b', value);
button.addClickHandler(handler);
doc.show(app);
}
function b(value) {
var doc = SpreadsheetApp.getActiveSpreadsheet();
var cell = doc.getRange(value);
cell.setValue(Number(cell.getValue()) + 1);
var app = UiApp.getActiveApplication();
app.close();
// The following line is REQUIRED for the widget to actually close.
return app;
}
Can anyone help me in this?
Thanks !
There is answers to this question in here :
Thansk to google forum users :)
http://www.google.com/support/forum/p/apps-script/thread?fid=2ef3693fc9aee1050004ad903de88dd4&hl=en

Categories