Copying Google Sheets table to Google Document - Error with Boolean cells - google-apps-script

I am very new to programming google app script, just trying to make some custom function. Sorry if this question is too basic...
I was following a tutorial to copy a table from Google Sheets into Google document but the exact same code the instructor was using did not worked for me.
I was getting this error:
Exception: The parameters (number[]) don't match the method signature for DocumentApp.Body.appendTable.
The simplified version of the code is:
function fun4(){
var ss = SpreadsheetApp.openById('17-23aFf6mN5oQrKNwNDy3Zh24_foTN5mXzNkjvd3V5w');
var sheet = ss.getSheets()[0];
var doc = DocumentApp.create('Sample Sheet Data');
var body = doc.getBody();
var numLines = sheet.getLastRow();
var numColumns = sheet.getLastColumn();
var rowData = sheet.getRange(1, 1, numLines, numColumns).getValues();
console.log(rowData);
var table = body.appendTable(rowData); // ERROR IN THIS LINE
table.getRow(0).editAsText().setBold(true);
}
After some search I found that the problem was caused by the last column containing Boolean values and changed .getValues() to .getDisplayValues().
It is working now but I am very confused...
How it was working in the instructor code but not in mine?
Why did not work if the output looks to be in the same format (double array?)
Code: (Gives an error when I append the table to doc , but worked in the instructor video)
var rowData = sheet.getRange(1, 1, numLines, numColumns).getValues();
console.log(rowData);
Output:
11:36:05 AM Info
[ [ 'NAME', 'EMAIL', 'AGE', 'ACTIVE' ],
[ 'Alex', 'alex#gmail.com', 50, true ],
[ 'Brian', 'brian#gmail.com', 34, false ],
[ 'Julian', 'julian#gmail.com', 42, true ],
[ 'John', 'john#gmail.com', 24, false ] ]
Code:
var rowData = sheet.getRange(1, 1, numLines, numColumns).getDisplayValues();
console.log(rowData);
Output:
11:36:05 AM Info
[ [ 'NAME', 'EMAIL', 'AGE', 'ACTIVE' ],
[ 'Alex', 'alex#gmail.com', '50', 'TRUE' ],
[ 'Brian', 'brian#gmail.com', '34', 'FALSE' ],
[ 'Julian', 'julian#gmail.com', '42', 'TRUE' ],
[ 'John', 'john#gmail.com', '24', 'FALSE' ] ]

I believe your goal as follows.
You want to know the reason the following situation.
After some search I found that the problem was caused by the last column containing Boolean values and changed .getValues() to .getDisplayValues().
It is working now but I am very confused... How it was working in the instructor code but not in mine? Why did not work if the output looks to be in the same format (double array?)
Answer:
About the error at the script of var rowData = sheet.getRange(1, 1, numLines, numColumns).getValues();, I thought that the reason of the issue might be due to using V8 runtime. Ref
When V8 runtime is enabled at the script editor, I confirmed that the error of The parameters (number[]) don't match the method signature for DocumentApp.Body.appendTable. occurred.
When V8 runtime is disabled at the script editor, I confirmed that no error occurred.
The table can be created using the value of var rowData = sheet.getRange(1, 1, numLines, numColumns).getValues(); and your sample values.
From your question, unfortunately, I cannot understand about the instructor video of Code: (Gives an error when I append the table to doc , but worked in the instructor video). But, above situation, I guess that the instructor video might not use V8 runtime.
So, in your script, when you want to test whether var rowData = sheet.getRange(1, 1, numLines, numColumns).getValues(); works, how about disabling V8 runtime at the script editor as follows and testing it again?
Reference:
V8 Runtime Overview

Related

Problem with basic array filtering not working

Array filtering not working as expected:
function getTest( myArray ) {
keySetTest = new Set('B-L002');
var t2= myArray[2][0];
var myResult = myArray.filter(dataRow =>keySetTest.has(dataRow[0]));
return myResult;
};
In the debugger it looks like this:
Why is myResult empty?
As can be seen from variable t2 it should contain at least the entry myArray[2],right?
I am using this logic almost identical in another context and it works fine.
About your question of Why is myResult empty?, when I saw your script, it seems that keySetTest = new Set('B-L002'); is required to be modified. Because I think that in your situation, when keySetTest = new Set('B-L002'); is used, each character is split like [ 'B', '-', 'L', '0', '2' ]. I thought that this might be the reason for your current issue.
When your script is modified, how about the following modification?
From:
keySetTest = new Set('B-L002');
To:
var keySetTest = new Set(['B-L002']);
Testing:
When the modified script is tested using a sample value, it becomes as follows.
var myArray = [["B-L002", "b1", "c1"], ["a2", "b2", "c2"], ["B-L002", "b3", "c3"]];
var keySetTest = new Set(['B-L002']);
var myResult = myArray.filter(dataRow => keySetTest.has(dataRow[0]));
console.log(myResult)
Note:
In this sample, I guessed your sample value of myArray. When you use this modified script in your actual situation, when your unexpected result is obtained, please provide the sample value of myArray and your sample expected value. By this, I would like to confirm it.
In your situation, the following modified script might be able to also obtain the same result.
var myArray = [["B-L002", "b1", "c1"], ["a2", "b2", "c2"], ["B-L002", "b3", "c3"]];
var myResult = myArray.filter(dataRow => dataRow[0] == "B-L002");
console.log(myResult)
Reference:
Set

setValues Exception: Service error: Spreadsheets How to fix range errors?

function chk(){
//PDD data setting
var today=new Date();
var Date = Utilities.formatDate(new Date(today.getFullYear(),today.getMonth(),today.getDate()), Session.getScriptTimeZone(), "yy-MM-dd");
[{
sheetName: "Sheet1" ,
folderID: '(google drive Folder)',
sheetId: '(sheetId1)',
tab: ['1', '2', '3', '4'],
conver: Date
},{
sheetName: "Sheet2" ,
folderID: '(google drive Folder)',
sheetId: '(sheetId1)',
tab: ['1', '2', '3', '4'],
conver: Date
}{
sheetName: "Sheet3" ,
folderID: '(google drive Folder)',
sheetId: '(sheetId1)',
tab: ['1', '2', '3', '4'],
conver: Date
}].map(obj => cloneValues(obj))
}
function cloneValues(obj){
let string = obj.conver;
let A = obj.sheetName;
let B = DriveApp.getFolderById(obj.folderID);
let C = DriveApp.getFileById(obj.sheetId);
var totalurl = PastetoDrive.makeCopy('Date '.concat( obj.conver , ' ',obj.sheetName ), dstFolder).getUrl();
var copy_url = totalurl.split("/");
let linkSheet = SpreadsheetApp.openById('(Backup Link sheetId)').getSheetByName('LINK');
linkSheet.appendRow([ string , A , totalurl ]);
for(let i = 0; i < obj.tab.length ; i++ ){
let fromSheet = SpreadsheetApp.openById(obj.sheetId).getSheetByName(obj.tab[i]);
let toSheet = SpreadsheetApp.openById(copy_url[5]).getSheetByName(obj.tab[i]);
setValues(fromSheet,toSheet)
}
}
function setValues(fromSheet,toSheet){
let maxCols = fromSheet.getMaxColumns();
let maxRows = fromSheet.getMaxRows();
let frvalues = fromSheet.getRange(1,1,maxRows,maxCols).getValues();
toSheet.getRange(1,1,maxRows,maxCols).setValues(frvalues);
}
Exception: Service error: Spreadsheets
I am writing and using Google AppScript, a work sheet that performs daily backups.
Exception: Service error: Spreadsheets error started to occur about a month ago in a script that I have been using well.
Looking at the log, there was a problem with setValues.
It seems that the ranges of fromSheet and toSheet don't match.
Daily backups should be stored as values in fromSheet > toSheet .
function setValues(fromSheet,toSheet){
const range = fromSheet.getDataRange().getValues();
return toSheet.range;
}
Once I changed the function setValues syntax and used it, I tried using setValues(range) to save it as a value, but it was not enough.
I'm a script beginner. I am testing and using various articles I need on stackoverflow and GitHub by combining and changing them.
Can anyone help me again this time?
function setValues(fromSheet,tosheet){
try {
const range = fromSheet.getRange(1, 1, tosheet.getMaxRows(), tosheet.getMaxColumns());
const values = range.getValues();
const toRange = tosheet.getRange(1, 1, tosheet.getMaxRows(), tosheet.getMaxColumns()).getA1Notation();
return tosheet.getRange(toRange).setValues(values);
} catch (e) {
Logger.log(e);
}
}
to-be
as-is
As a result, it was successful.
Posting a question and waiting for help from many people, I tried various methods, but nothing improved and I kept getting Service Error: Spreadsheet text.
In the end, I changed some of the setValues syntax and
I tried setting the range again, but the same error occurred.
After confirming that the result of the clone sheet is the result I want,
Decided to avoid this issue.
catch(e)
Thank you for your interest.

format JSON data import in google sheets

with the help of member / friend #Tanaike we were able to develop a code to import the data from a JSON list, but the data in the "price" field is imported as follows '16 .4700000000 'and I would like to import only the first 2 digits after the' . ' getting "16.47".
could you help me on this mission?
this is the current code I am using:
// Call the Bling API
var response = UrlFetchApp.fetch("https://bling.com.br/Api/v2/produtos/json&apikey=APIKEY?imagem=S&estoque=S");
//Logger.log(response.getContentText());
// Parse the JSON reply
var json = response.getContentText();
var data = JSON.parse(json);
// Aquisição de dados.
var values = data.retorno.produtos.map(({produto: {codigo, gtin, descricao, preco, situacao}}) => [codigo, gtin, descricao, preco, situacao]);
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("produtos");
sheet.getRange(/*sheet.getLastRow() + */ 2, 1, values.length, values[0].length).setValues(values); ```
Here is a snippet from one of my projects where I set the number format as well as borders and background.
sheet.getRange(summaryAnnRetsFirstRow, 1, summaryAnnRetsLen, 4).setValues(summaryAnnRets);
sheet.getRange(summaryAnnRetsFirstRow,2, summaryAnnRetsLen, 2).setNumberFormat("$#,##0;$(#,##0)");
sheet.getRange(summaryAnnRetsFirstRow,4, summaryAnnRetsLen, 1).setNumberFormat("0.00%");
sheet.getRange(summaryAnnRetsFirstRow,1, summaryAnnRetsLen, sheet.getLastColumn()).setBorder(true, true, true, true, true, true, 'black', SpreadsheetApp.BorderStyle.SOLID_LIGHT);
sheet.getRange(summaryAnnRetsFirstRow,1, summaryAnnRetsLen, sheet.getLastColumn()).setBackground("#bdd4f9");

For Loop for Event Object variables in Google App Script

Again newbee in app scripting I am trying to do the following
How to store array values in a variable for event object while on form submit i.e I need to get all values from form responses column in a sheet J to AF from a single row into a variable
something like var value = j,k,l,m,n,o(obviously as string without any spl chars like ,.etc)
instinctively there should be better way get all the values in a variable? tried some loop since the range starts from in-between columns(J-AF) of the sheet cant get it right
function onFormSubmit(e) {
Logger.log("%s", JSON.stringify(e));
//Get information from form and set as variables
var amount = [e.values[9],e.values[10],e.values[11],e.values[12],e.values[13],e.values[14],...e.values[31]];
Logger.log('Lets see if its here:'+ amount);
}
The e object from onFormSubmit(e) has the following structure:
{
authMode: {... },
namedValues:
{ 'Question 2': [ 'Answer 2' ],
Timestamp: [ '3/2/2020 9:48:53' ],
Question: [ 'Answer' ] },
range: { columnEnd: 3, columnStart: 1, rowEnd: 6, rowStart: 6 },
source: {},
triggerUid: '3xxxxxx825600xxx',
values: [ '3/2/2020 9:48:53', 'Answer', 'Answer 2' ]
}
As you can see, there are a couple of properties that can be useful for your case. (namedVales and values).
It is up to you to choose which to use.
An example:
function onFormSubmit(e) {
// Get values from response and put them in named variables
var amountDict = {
'Question 2' : e.namedValues['Question 2'],
'Question' : e.namedValues['Question'],
'Timestamp' : e.namedValues.Timestamp,
moreCols:'...', colAB: e.namedValues[10]
};
// Log them
console.log(amountDict);
// Get values from response and put them in unnamed variables
var amountList = [e.values[0],e.values[2], '...', e.values[3]];
// Log them
console.log(amountList);
}
Output:
Try this:
Don't forget to change the sheet name if needed.
And create the trigger.
function onFormSubmit(e) {
var ss=SpreadsheetApp.getActive();
var sh=ss.getSheetByName('Sheet1');
sh.getRange(sh.getLastRow()+1,10,1,e.values.length).setValues([e.values]);
}

"The coordinates or dimensions of the range are invalid"

I am working on a Google Apps Script that links with a REST API and puts the data into a Google Sheet.
I have successfully done this once, but upon accessing some different data I get the error message
"The coordinates or dimensions of the range are invalid"
when they work perfectly fine on my other script. All data accessed is JSON so I am bit confused and is from the same source. The code I am using is:
function stats () {
var logIn = {
"Authorization" : "Basic " + Utilities.base64Encode("XXXX" + ':' + "XXXX")
};
var url = "XXXXX";
var params = {
"method":"GET",
"headers":logIn, };
var response = UrlFetchApp.fetch(url, params);
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("XXXX");
var dataAll = JSON.parse(response.getContentText()); //
var dataSet = dataAll;
var rows = [],
data;
for (i = 0; i < dataSet.length; i++) {
data = dataSet[i];
rows.push([XXXX]); //your JSON entities here
}
dataRange = sheet.getRange(1, 1, rows.length, 1);
dataRange.setValues(rows);
}
I have combined pieces of code from around the web and this works on my other script. The error appears on this line:
dataRange = sheet.getRange(1, 1, rows.length, 1);
I believe the issue is with the data I am accessing but I do not know how to alter the script for it to work.
The JSON data that works is shown like:
{
id: XXX,
group: XX,
text: "XXXX?",
creation_date: XXXX,
created_by: "XXXXX",
tags: [
"XXXX"
]
}
And the data that is causing the error is shown as:
{
2016-02-29: {
XXX: 0,
XXX: 0
},
I have had to 'XXXX' out a lot of the private information - apologies. Any help would be appreciated.
Javascript's length property is for indexed arrays and does not apply to Objects so dataSet.length returns undefined and the loop never executes.
To get the length of the object you can use Object.keys(dataSet).length as outlined here.