having trouble with a simple copy and paste function in google scripts - javascript

i'm trying to call a function from the menu bar to copy a set of values in google sheets to an "archive" tab. The error i'm getting is "Exception: The parameters (SpreadsheetApp.Range) don't match the method signature for SpreadsheetApp.Range.setValues." here is the code:
function archiveCompleted () {
var spreadsheet = SpreadsheetApp.getActive();
var copyFrom = spreadsheet.getSheetByName("completed autofill");
var copyDest = spreadsheet.getSheetByName("Completed Orders");
var sourceRange = copyFrom.getRange(1,1,copyFrom.getLastRow(),copyFrom.getLastColumn());
var destRange = copyDest.getRange(copyDest.getLastRow() + 1,1,copyFrom.getLastRow(),copyFrom.getLastColumn());
//1,1,copyFrom.getLastColumn());
sourceRange.copyValuesToRange(destRange);
spreadsheet.setActiveSheet(spreadsheet.getSheetByName('Copy From Feildpine'),true);
}
thanks for any help!

I thought that about your error message of Exception: The parameters (SpreadsheetApp.Range) don't match the method signature for SpreadsheetApp.Range.setValues., unfortunately, I cannot find setValues in your showing script. So I'm worried that you miscopied your current script.
But, when I saw your script, I thought that sourceRange.copyValuesToRange(destRange); is required to be modified. Because the arguments of copyValuesToRange are gridId, column, columnEnd, row, rowEnd or sheet, column, columnEnd, row, rowEnd. Ref1, Ref2
So, in this modification, I would like to propose modifying the line as follows.
From:
sourceRange.copyValuesToRange(destRange);
To:
sourceRange.copyTo(destRange, {contentsOnly: true});
Reference:
copyTo(destination, options)

Related

How to get row and col from e with onEdit

I'm trying to get the coordinates of the modified cell with a script in order to perform some actions, in the documentation I see that e.range returns a range object, so according to this documentation
if I'm not mistaking, I should be able to perform e.range.getRow() or e.range.getCol().
I tried this :
function onEdit(e) {
const RANGE = e.range;
let row = RANGE.getRow();
let col = RANGE.getCol();
Logger.log('line : ', row, 'column : ', col)
}
but nothing happens except this in th executions tab:
TypeError: RANGE.getCol is not a function
at onEdit(script:5:19)
Whet am I doing wrong?
Use the properties of the event object as Cooper recommends. To answer your question, the Range() object does not have a .getCol() method. The correct method is .getColumn().
See these onEdit(e) optimization tips.

App Script new Google Sheet creation issue

I am trying to write an App Script that takes string data from multiple different spreadsheets (completely separate documents) and puts them all in a new spreadsheet. When I run the logger, it shows me all the data I want. I want each piece of data to show up in Column A, but when I run my script, it only puts 1 data point in the spreadsheet instead of all of them. Can someone give me some guidance? Here is my code:
function pullTogether() {
var files = DriveApp.getFolderById('Folder ID').searchFiles('title != "nothing"');
const rangeName = 'Sheet1!B2:C';
while(files.hasNext()){
var xFile = files.next();
var name = xFile.getId();
const values = Sheets.Spreadsheets.Values.get(name, rangeName).values;
for (const row in values) {
var a1 = (values[row][0]);
Logger.log(a1);
var ss = SpreadsheetApp.openById("ID of new spreadsheet"); //I have the real ID in my code
var cell = ss.getRange("A2");
cell.setValue(a1);
}
}
}
I believe your goal is as follows.
You want to retrieve the values from the column "B" of each Spreadsheet under the specific folder.
You want to put the retrieved values to the column "A" of the destination sheet.
Modification points:
About but when I run my script, it only puts 1 data point in the spreadsheet instead of all of them., when I saw your script, the retrieved value is always put to the cell "A2" of the destination sheet. I think that this might be the reason for your issue.
In your script, I thought that when the following flow is used, the process cost will become low. By this flow, your issue can be also removed.
In your situation, even when Sheets API is not used, the script might work using getValues().
When these points are reflected in your script, it becomes as follows.
Modified script:
Please set the folder ID and the destination Spreadsheet ID.
function pullTogether() {
// Retrieve values from each Spreadsheet.
var values = [];
var files = DriveApp.getFolderById('Folder ID').searchFiles(`title != 'nothing' and mimeType='${MimeType.GOOGLE_SHEETS}'`);
var sheetName = 'Sheet1'
while (files.hasNext()) {
var xFile = files.next();
var sheet = SpreadsheetApp.open(xFile).getSheetByName(sheetName);
if (sheet) {
var v = sheet.getRange("B2:B" + sheet.getLastRow()).getValues();
values = [...values, ...v];
}
}
// Put values to the destination sheet.
var ss = SpreadsheetApp.openById("ID of new spreadsheet"); //I have the real ID in my code
var dstSheet = ss.getSheets()[0];
dstSheet.getRange(2, 1, values.length, values[0].length).setValues(values);
}
Note:
Although I'm not sure about your actual situation, when the above script didn't work by the large data, please modify as follows.
From
dstSheet.getRange(2, 1, values.length, values[0].length).setValues(values);
To
Sheets.Spreadsheets.Values.update({ values }, ss.getId(), `'${dstSheet.getSheetName()}'!A2`, { valueInputOption: "USER_ENTERED" });
References:
getValues()
setValues(values)

How do I group multiple tab ranges in array literal dynamically(by using wildcard)?

I have one spreadsheet with multiple tabs, e.g.
"Summary"
"Week 1"
"Week 2"
"Backlog"
The number of Weeks is not fixed. In the future, I may add more tabs as time goes on, for example
"Week 3"
"Week 4"
...
In the "summary" tab, I want to list all the data from Column A (remove title) from all "Week" tabs.
Currently, I have to add all the tab names of "Week" manually in the query range parameter, e.g.
=query({'Week 1'!A2:A; 'Week 2'!A2:A}, "select *")
But I want to make it automatically if I add more tabs in the future by doing something like this:
=query({"Week *"}!A2:A, "select *")
How do I do that?
An option would be to get rid of the QUERY formula altogether and use an Apps Script Custom Function instead.
First, open a bound script by selecting Tools > Script editor, and copy the following functions to the script:
function SUMMARIZE_WEEKTABS() {
const ss = SpreadsheetApp.getActive();
const weekSheets = ss.getSheets().filter(sheet => sheet.getName().startsWith("Week "));
const summarySheet = ss.getSheetByName("Summary");
let weekData = weekSheets.map(weekSheet => {
return weekSheet.getRange(2, 1, weekSheet.getLastRow()).getValues().flat();
});
weekData = weekData[0].map((_, colIndex) => weekData.map(row => row[colIndex]));
return weekData;
}
The function SUMMARIZE_TABS returns the data from column A from all sheets whose name starts with "Week ". Once it is defined in your script, you can use it the same way you would use any sheets built-in function. See, for example, this:
Update:
If you want all data to be written on the same column, use this instead:
function SUMMARIZE_WEEKTABS() {
const ss = SpreadsheetApp.getActive();
const weekSheets = ss.getSheets().filter(sheet => sheet.getName().startsWith("Week "));
const summarySheet = ss.getSheetByName("Summary");
let weekData = weekSheets.map(weekSheet => {
return weekSheet.getRange(2, 1, weekSheet.getLastRow() - 1).getValues();
}).flat();
return weekData;
}
Reference:
Custom Functions in Google Sheets
Explanation:
You can use Google Apps Script to accomplish this task.
The following script:
gets all the sheets of your spreadsheet file that contain the name
Week,
iterates over these sheets and construct a string object which can be
used inside the query formula,
sets the resulting formula to cell A1 of the Summary sheet. Feel free to modify A1 in the code below.
I also added a function that creates a macro button on top of your sheet, so you can use this functionality from the sheet itself (see instructions below).
Solution:
Please follow the instructions (gif) on how to use the following code:
function getQuery() {
const ss = SpreadsheetApp.getActive();
const summary_sheet = ss.getSheetByName('Summary');
const sheet_names = ss.getSheets().filter(fsh=>fsh.getName().includes("Week")).map(sh=>sh.getName())
var weeks = [];
sheet_names.forEach(wk =>
weeks.push(`'${wk}'!A2:A`)
)
summary_sheet.getRange('A1').setFormula(`=query({${weeks.join(";")}}, "select *")`)
}
function onOpen() {
SpreadsheetApp.getUi()
.createMenu('Macros')
.addItem('Get Query', 'getQuery')
.addToUi();
}
Instructions:
After you save the code snippet in the script editor, refresh your sheet/browser.
References:
Google Apps Script libraries:
Class Spreadsheet
setFormula()
onOpen trigger
JavaScript libraries:
forEach()
map()

Retrieve Google Sheets column by header name

Is there a way to retrieve a column dynamically by it's column name (header)?
Instead of:
var values = sheet.getRange("A:A").getValues();
Something like: (Just for simplicity)
var values = sheet.getRange(sheet.column.getHeader("name").getValues();
Please keep in mind that Google Apps Script is roughly ES3.
You can write one ;)
function getColValuesByName(sheet, name) {
var index = sheet.getRange(1,1,1,sheet.getLastColumn()).getValues()[0].indexOf(name);
index++;
return sheet.getRange(1,index,sheet.getLastRow(),1).getValues();
}
Here's a very simple one-line function you can copy. It returns the column number (A = 1, B = 2, etc.) for use in getRange, for example.
function getColByHeader(name) {
return SpreadsheetApp.getActiveSheet().getRange('1:1').getValues()[0].indexOf(name) + 1;
}
Although there is no direct way, there are plenty of ways to get what you want with a little set up:
Get all data and filter it(no set up):
var values = sheet.getDataRange().getValues();
var headers = values.splice(0,1);
headerIdx = headers[0].indexOf("name");
values = values.map(function(row){return [row[headerIdx]];})
Named ranges set up:
If you have named ranges associated with that column,
spreadsheet.getRangeByName('Sheet Name!name').getValues();//where 'name' is a named range
Developer metadata set up:
If you have developer metadata associated with that column,
SpreadsheetApp.getActive()
.createDeveloperMetadataFinder()
.withKey(/*METADATA_KEY_ASSOCIATED_WITH_COLUMN*/)
.find()[0]
.getLocation()
.getColumn()
.getValues();

how to insert multiple rows in a spreadsheet using google script

Is there any way i can insert multiple Rows into Google SpreadSheet without using any loops.
Need to do this task using google Apps Script only.
function testMultipleEntry(){
var sheet = SpreadsheetApp.openById(INSERT-SHEET-ID);
var mainSpreadSheet= sheet.getActiveSheet();
var fiveRows= mainSpreadSheet.getRange(2, 1, 5,mainSpreadSheet.getMaxColumns() );
var tempSheet= SpreadsheetApp.create("TestSheetAppend").getActiveSheet();
fiveRows.copyValuesToRange(tempSheet, 1, mainSpreadSheet.getMaxColumns(), 2, 5);//used the array[][]
}
last line is showing -- Service error: Spreadsheets
I'm still not clear on what it is you're looking for, but this code takes data from one sheet, and inserts it into another one:
function enterData(){
var ss = SpreadsheetApp.openById('SHEET-ID');
var mainSheet= ss.getActiveSheet();
var fiveRows= mainSheet.getRange(2, 1, 5,mainSheet.getMaxColumns());
var createSheet= ss.insertSheet("TestSheetAppend");//This line will fail if a sheet by this name exists.
var tempSheet = ss.getSheetByName('TestSheetAppend');
fiveRows.copyValuesToRange(tempSheet, 1, tempSheet.getMaxColumns(), 2, 5);//used the array[][]
}
If you're looking to send it to another sheet entirely, you can modify this code to do so.
I've spent some time looking into the official documentation on google app scripts, and based on that I can confirm you that there are many ways you can achieve this, one of which is explained below
getRange() + setValues()
Sample code
const startRowNumber = 1;
const starColumnNumber = 1;
const endRowNumber = dataToPut.length;
const endColumnNumber = dataToPut[0].length;
const range = sheet.getRange(startRowNumber, starColumnNumber, endRowNumber, endColumnNumber);
range.setValues(dataToPut);

Categories

Resources