Google Apps Script - copying TextStyles fails with Exception - javascript

I am writing GAS script that copys some sheets from one spreadsheet to another - can't use copyTo as I don't want all the named ranges pulled in, for one thing.
A script gets data from one sheet, creating a sheet object, including the initializer:
textStyles: sheet.getLastColumn() != 0 ? sheet.getRange(1, 1, sheet.getLastRow(), sheet.getLastColumn()).getTextStyles() : [[]],
another script copies the sheet info into a new sheet ...
newSheet.sheet.getRange(newSheet.sheetRange).setTextStyles(newSheet.textStyles);
which results in the error
Exception: The parameters (number[]) don't match the method signature for SpreadsheetApp.Range.setTextStyles.
I copied oldsheet -> newsheet using let newSheet = JSON.parse(JSON.stringify(oldSheet));
but I have tried :
newSheet.sheet.getRange(newSheet.sheetRange).setTextStyles(oldSheet.textStyles);
with the same result.
Any ideas what I am doing wrong, please?

Related

Using Google Apps Script, how can I replace text in a Google Sheets template to make a new Sheet?

I have a Google Sheet which is being populated by a Google Form. I am using Google Apps Script to add some extra functionality. Please feel free to access and modify these as needed in order to help.
My goal is to be able to take responses from a Google Form, have that come into a Google Sheet, and then, using a template file, populate the template with the responses and have that sent out as an email attachment to whomever I specify.
This is a dumbed down version of my ultimate project, but the process should remain the same so that I can transpose from this small scale example to that bigger one.
Currently, in my Apps Script, I have code which is successfully able to make a copy of the template file and name it accordingly:
//Enter collected info into Requirements Template
const googleSheetTemplate = DriveApp.getFileById('1wqCwMhpuDLReU1hE1CbcDL-Vdw_4zge1xM6oOl34Ohg');
const destinationFolder = DriveApp.getFolderById('1GxNZQmP8mxHBhVl5AMoqBFs8sAIYzcm3');
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Form Responses 2');
const copy = googleSheetTemplate.makeCopy(`${row[3]}, ${row[0]} Vehicle Order` , destinationFolder);
const newSheet = SpreadsheetApp.openById(copy.getId());
const A1 = newSheet.getActiveRange();
But the next few lines which are meant to be able to find and replace certain strings within the newly copied Sheet does not seem to function properly.
A1.createTextFinder("{{Customer}}").replaceAllWith(row[3]);
A1.createTextFinder("{{Car}}").replaceAllWith(row[1]);
A1.createTextFinder("{{Color}}").replaceAllWith(row[2]);
A1.createTextFinder("{{Delivery}}").replaceAllWith(row[5]);
I just get the same dummy lines back in the new copy.
I was following another post which I found on a different issue but with the same goal. The majority of the concept I was looking to copy came from this blog post, but where they used a Google Doc, I was hoping to use a Google Sheet. Ultimately, the person that receives this new sheet will need to do some calculations and things with the provided information, so it still needs to be in Sheet form.
What modifications do I need to make in order to successfully replace the text in the template with the answers provided from the Google Form responses?
As far as I can tell, this line means some cells on the sheet were selected:
const A1 = newSheet.getActiveRange();
And script will search and replace within these cells only.
Probably you need to define the range with no reference on active range. Something like this:
const A1 = newSheet.getRange("A1:A"); // or "A1:Z", or .getDataRange()
I don't know what the range you need.
From the documentation, createTextFinder(findText) only works on a Sheet class, this means you need to define a Sheet variable before replacing text:
const copy = googleSheetTemplate.makeCopy(`${row[3]}, ${row[0]} Vehicle Order` , destinationFolder);
const newSheet = SpreadsheetApp.openById(copy.getId()).getSheets()[0];
newSheet.createTextFinder("{{Customer}}").replaceAllWith(row[3]);
newSheet.createTextFinder("{{Car}}").replaceAllWith(row[1]);
newSheet.createTextFinder("{{Color}}").replaceAllWith(row[2]);
newSheet.createTextFinder("{{Delivery}}").replaceAllWith(row[5]);

Creating a new menu and an item right under it for uploading excel template in google sheet(Javascript)

I created an item named “import” under the menu “database” in my google sheet. What I want to execute with this item is that the excel file, with two columns only, can be uploaded and the values nested within them can be stored in an array without appending a new spreadsheet for this excel file. However, I got stuck in “how to upload excel file” this way. After loading the array with the newly uploaded data, another function will be called to add the name-style pair which doesn’t exist in sheet 1 from the array to the unoccupied cells. So this item is designed for updating the sheet1 automatically.
function interface() {
var ui = SpreadsheetApp.getUi();
var menu=ui.createMenu("Data base")
menu.addItem("Import","cal")
menu.addToUi()
}
function onOpen(){
interface()
}
function cal() {
var ss = SpreadsheetApp.getActive().getSheetByName("updated list");// I don't know how to accomplish this part so I created a sheet to store the data as an alternative for the time being.
var lastRow=ss.getLastRow()
var dataBase=ss.getRange(2,1,lastRow,1).getValues()// I want to store the valuse nested within this two columns but there is an error when I use "indexOf" to pick out the data which doesn't exist in sheet1 and push it to the unoccupied cells so I only take one column of values here(Making it one level deep only).
var dataBase2=ss.getRange(2,2,lastRow,1)
var ss1 = SpreadsheetApp.getActive().getSheetByName("sheet1")
var lastRow1=ss1.getLastRow();
var storedData=ss1.getRange(2,1,lastRow1,1).getValues()// Faced with the same problem as described above.
for(var i=0; i<lastRow1;i++){
if(storedData.indexOf(dataBase[i])==-1){
var counter=1
ss1.getRange(lastRow1+counter,1),setValue=dataBase[i]
ss1.getRange(lastRow1+counter,1),offset(0,1),setValue=dataBase2[i]// The error "offset is not defined" shows up here
Logger.log(ss1.getRange(lastRow1+counter,1),setValue=dataBase[i])
counter++
}
}
}
Sheet1 is the worksheet used for looking up who takes charge of which style
Updated list contains the data which I want to add to the array
The logic is that me and my team mates can just take a look at the sheet1 to look for the merchandiser(Name) to know the style he or she takes charge of. But this list should be updated at least once a week. So I wonder if it's possible to automatically add the names and styles in the "updated list" to sheet1 when there is no match found.
For example:
Jason S55567899 and
Nick Jack52578 should be added into worksheet1 right below the last occupied row since these two styles don't exist in sheet1 yet.

GAS: is getLastRow() only valid for sheets, not arrays?

I want to save server calls and try to load the sheet into memory before other actions:
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Condo1");
var allSheetData = sheet.getDataRange().getValues(); // load all sheet data into memory
var lastRow = allSheetData.getLastRow();
But the web console states:
Error TypeError: allSheetData.getLastRow is not a function
at [unknown function](Code:9:28)
Is getLastRow() only applicable for sheets, not for other arrays of data?
I could not get an explicit answer in the documentation.
After help with the getLastRow() - thanks Marios! - I still am puzzled about the underlying objective, to minimize server calls. I have made a similar script where I get annoyed with the long execution time due to calling for every row, especially in longer tables. Now I wanted to make it better and manipulate the table locally. I am sure there are plenty similar issues on SO for google apps script, if I only could get a good search term. "async bulk request" did not give me good hits on SO.
Then I can start with selfstudy. Thank You!
Issue:
As you can see in the official documentation getLastRow is a function applied to a sheet object.
You are trying to apply getLastRow() to a 2D JavaScript array: [[x1,y1],[x2,y2]] and this is why you are getting a message that getLastRow can not be applied to a JavaScript array.
Solution:
You have two options:
Use the built in JavaScript array method length on allSheetData to get the number of "rows" this data array occupies:
var lastRow = allSheetData.length;
Apply getLastRow on the sheet object:
var lastRow = sheet.getLastRow();
Please note:
Make sure to understand what getLastRow() returns which is the last row in the sheet that has content.
In your case you are using getDataRange which implicity uses getLastRow to calculate the range. But if you want to manually define a range object, then length and getLastRow might give different results!

Google App Script - Custom Importrange Function, Need Auto-Update

I am porting data from 9 different Google Sheets to a master overview dashboard to track company metrics. Instead of using ImportRange, I created a custom function with Google Apps Script because I need all the formatting to come with it. The sheet that I want to copy over uses formulas, so I first create a copy of the sheet in the source spreadsheet without formulas and then copy that sheet over to the destination spreadsheet.
The nice thing about ImportRange is that it is constantly fetching the data and auto-updating. The function I wrote below creates and deletes sheets to get the formatting to port over to the masterSS. Is there a work around that anyone can think of to just get the values to auto-update, without having to create and delete a bunch of new sheets?
Also, everytime I create and delete a new sheet, the sheet count increases by 1. Is there a way to reset this counter?
function importPortComp(portComp, srcRange, destRange) {
// Create temporary sheet in source spreadsheet
var tempSheet = portComp.insertSheet();
// Copy values, formatting, and column widths to temporary sheet
srcRange.copyTo(tempSheet.getRange(1, 1), SpreadsheetApp.CopyPasteType.PASTE_VALUES, false);
srcRange.copyTo(tempSheet.getRange(1, 1), SpreadsheetApp.CopyPasteType.PASTE_FORMAT, false);
srcRange.copyTo(tempSheet.getRange(1, 1), SpreadsheetApp.CopyPasteType.PASTE_COLUMN_WIDTHS, false);
// Copy temporary sheet destination spreadsheet
var copiedSheet = tempSheet.copyTo(masterSS);
// Delete temporary sheet from source spreadsheet
portComp.deleteSheet(tempSheet);
// Copy source range to destination range
copiedSheet.getRange(srcRange.getA1Notation()).copyTo(destRange);
copiedSheet.getRange(srcRange.getA1Notation()).copyTo(destRange, SpreadsheetApp.CopyPasteType.PASTE_COLUMN_WIDTHS, false);
// Delete copied sheet from T/R spreadsheet
masterSS.deleteSheet(copiedSheet);
}
if I correctly understand your question:
use:
array = sheet.getSheetValues(startRow, startColumn, numRows, numColumns)
to get the values
then push to the array at the correct index (I guess it's array[row][column])the other datas you want to "concat/add" set the correct range and the use
sheet.range.setValues(array)
you can check this documentation

Retrieve number of rows in Google Sheets

I need a JavaScript method for my webpage to count how many rows are in a Google sheet (it's used as a response sheet for a form). I've been scouring the web for easy tutorials on how to make Google Sheets into a database.
Is there a simpler way to do it?
I don't have much experience in Google scripts, but all I need is a way I can have read access to the spreadsheet using preferably Ajax or some similar JavaScript method.
To retrieve the number of rows in your Google Spreadsheet use the following:
var ss = SpreadsheetApp.openById("1qNCf0wKl................");
var sheet = ss.getSheetByName("sheet_name");
var number = sheet.getMaxRows().toString();
var number = number.replace(".0","");
Logger.log(number);
In order to have read access to a Spreadsheet the guidance provided in the following link is good enough:
Query Google Spreadsheet with URL Parameters
For example, if you want to get all the cells with the word «budget» in your Spreadsheet, use the following script:
var id = "1qNCf0wKlx1RF......";
var column = "A";
var query = "budget";
var url = "https://docs.google.com/spreadsheets/d/"+id+"/gviz/tq?tq=SELECT%20*%20where%20"+column+"%20contains%20%22"+query+"%22";
var text = UrlFetchApp.fetch(url).getContentText().toString();
Logger.log(text);
For this, the Spreadsheet has to be published previously. After retrieving the «budget» rows the text has to be formated, but that's another issue.
Here is what you can do
Write a simple Apps script using ContentService that will return a JSON with the number of rows in the spreadsheet (and any other info you need). To get the number of rows, you can use the getLastRow() function
Publish your script as a service(web app) and make an AJAX call from your JS code.

Categories

Resources