I am very new to Javascript and Apps Script. I want to create a function that updates another sheet based on a date in a certain range of the active sheet. I run and no error but it doesn't transfer value from active sheet to sheet named "Master", in different target url google sheet
data master post
output 1
output 2
output 3
function updateYTD4() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sheet = ss.getSheetByName("January");
const targetSheet = ss.getSheetByName("Master");
if (sheet && targetSheet) {
if(sheet.getRange("A2:D32").getValues().length > 0){
sheet.getRange("A2:D32").copyTo(targetSheet.getRange("C"+(targetSheet.getLastRow()+1)),
{contentsOnly:true});
}
}
}
copyTo Google Sheets Script for different workbook how targetSheet change to send data sheet to output 1 , output 2, output 3 ( with a different workbook url )
As another approach, how about the following sample script?
I believe your goal is as follows.
You want to use both the source Spreadsheet and the target Spreadsheet.
The source Spreadsheet is the active Spreadsheet, and the target Spreadsheet is a different Spreadsheet from the source Spreadsheet.
Modification points:
In the current stage, when the source Spreadsheet is different from the target Spreadsheet, copyTo of Class Range cannot be used. When this is used an error like Exception: Target range and source range must be on the same spreadsheet. occurs. Please be careful about this.
In the case of sheet.getRange("A2:D32").getValues().length > 0, even when "A2:D32" are empty, the length is always 31. Please be careful about this.
In your situation, it seems that you want to copy only the values. So, how about using getValues and setValues? When these points are reflected in your script, how about the following modification?
Modified script:
function myFunction1() {
const srcSpreadsheet = SpreadsheetApp.getActiveSpreadsheet();
const dstSpreadsheet = SpreadsheetApp.openById("###"); // Please set your spreadsheet ID.
const srcSheet = srcSpreadsheet.getSheetByName("January");
const targetSheet = dstSpreadsheet.getSheetByName("Master");
if (srcSheet && targetSheet) {
const values = srcSheet.getRange("A2:D32").getValues();
if (values.filter(r => r.join("")).length > 0) {
targetSheet.getRange(targetSheet.getLastRow() + 1, 3, values.length, values[0].length).setValues(values);
}
}
}
If you have multiple Spreadsheet IDs, how about the following sample script?
function myFunction2() {
const spreadsheetIds = ["###", "###", "###"];// Please set your spreadshet IDs.
const srcSpreadsheet = SpreadsheetApp.getActiveSpreadsheet();
const srcSheet = srcSpreadsheet.getSheetByName("January");
if (!srcSheet) return;
const values = srcSheet.getRange("A2:D32").getValues();
if (values.filter(r => r.join("")).length == 0) return;
for (let i = 0; i < spreadsheetIds.length; i++) {
const dstSpreadsheet = SpreadsheetApp.openById(spreadsheetIds[i]);
const targetSheet = dstSpreadsheet.getSheetByName("Master");
if (targetSheet) {
targetSheet.getRange(targetSheet.getLastRow() + 1, 3, values.length, values[0].length).setValues(values);
}
}
}
References:
copyTo(destination, options)
getValues()
setValues(values)
That's because you're handling different workbooks.
const ss = SpreadsheetApp.getActiveSpreadsheet(); will only refer to the workbook from which you run the script.
You should add a new variable for the other sheet:
const newss = SpreadsheetApp.openById("1jQ93ylP0MHzSzxH0myS9_AhTjetdvLQMXvFwg18XFEE")
I've put the ID from the link from the mastersheet, but adapt accordingly to your needs. Then you can use newss.getSheetByName("Sheet you need")
UPDATE
Possible code, if I understand you well:
function updateYTD4() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const newss = SpreadsheetApp.openById("1jQ93ylP0MHzSzxH0myS9_AhTjetdvLQMXvFwg18XFEE")
const sheet = ss.getSheetByName("January");
const targetSheet = newss.getSheetByName("Master");
if (sheet && targetSheet) {
if(sheet.getRange("A2:D32").getValues().length > 0){
sheet.getRange("A2:D32").copyTo(targetSheet.getRange("C"+(targetSheet.getLastRow()+1)),
{contentsOnly:true});
}
}
}
Related
I have a function filter in a cell, how can I transform it in an apps script function with parameters like range, condition1, condition2?
This is the filter function:
=FILTER(Master!B:C; month(Master!B:B) = 1; Master!A:A = true)
I believe your goal is as follows.
You want to convert the formula of =FILTER(Master!B:C; month(Master!B:B) = 1; Master!A:A = true) to Google Apps Script.
In this case, how about the following sample script?
Sample script:
Please copy and paste the following script to the script editor of Spreadsheet, and save the script. And, please set the source and destination sheet names.
const filterValues = v => v.filter(([a, b]) => a === true && b.getMonth() == 0).map(([, ...v]) => v);
// Please run this script.
function myFunction() {
// Retrieve values from the source sheet and filter values.
const ss = SpreadsheetApp.getActiveSpreadsheet();
const srcSheet = ss.getSheetByName("Master"); // Please set source sheet name.
const values = srcSheet.getRange("A1:C" + srcSheet.getLastRow()).getValues();
const result = filterValues(values);
console.log(result); // You can see the filtered values in the log.
// Put filtered values to the destination sheet.
const dstSheet = ss.getSheetByName("Sheet1"); // Please set destination sheet name.
dstSheet.getRange(1, 1, result.length, result[0].length).setValues(result);
}
When this script is run, the same values with the above formula are retrieved and put into the destination sheet.
In this sample, you can also use filterValues as a custom function like =filterValues(Master!A1:C).
Note:
About putting the filtered values to the destination sheet, this is a sample script. So, please modify this for your actual situation.
References:
filter()
map()
Context
I'm using Google Apps Scripts to automate some things in Google Sheets. Currently, I can copy the column data for every row without issue. However, I only need to copy rows that aren't empty in a specific column (G) and can't figure out where/how to implement the conditional.
Goal
For each row in the source sheet, check if cell in column G is empty.
If cell is not empty, copy parts of that row to other sheet.
Here is the current script:
function theme_copy_WIP () {
let workbook = SpreadsheetApp.getActiveSpreadsheet(); // get the active sheets workbook
let auditSheet = SpreadsheetApp.getActiveSheet(); // active sheet of workbook to copy from (source)
let auditRangeList = auditSheet.getRangeList(["A2:A", "B2:B", "C2:C", "E2:E", "G2:G", "H2:H"]); //Range of columns to copy data from
let themeSheet = workbook.getSheetByName("Themes"); //themes sheet to paste into (destination)
let destRangeList = themeSheet.getRangeList(["A2:A", "B2:B", "C2:C", "D2:D", "E2:E", "F2:F"]); //Range of destination columns to paste into
for( let i=0; i<auditRangeList.getRanges().length; i++ ) {
let auditRange = auditRangeList.getRanges()[i];
let destRange = destRangeList.getRanges()[i];
auditRange.copyTo(destRange, {contentsOnly: true});
}
}
Copy Values
function myfunk() {
const ss = SpreadsheetApp.getActive();
const ssh = ss.getActiveSheet();
const svs = ssh.getRange(2, 1, ssh.getLastRow() - 1, ssh.getLastColumn()).getValues();
const tsh = ss.getSheetByName("Sheet0");
const tlr = tsh.getLastRow();
if (tlr > 1) {
tsh.getRange(2, 1, tsh.getLastRow() - 1, 6).clearContent();
}
let tvs = svs.map(r => {
if (r[6]) {
return [r[0], r[1], r[2], r[4], r[6], r[7]];
}
}).filter(r => r );
if (tvs && tvs.length > 0) {
tsh.getRange(2, 1, tvs.length, tvs[0].length).setValues(tvs);
}
}
Instead of using rangeList, get the full range, modify it and set back the modified range.
const out = auditSheet
.getRange("A2:H"+auditSheet.getLastRow())
.getValues()
.reduce((acc,[a,b,c,d,e,f,g,h]) => (g && acc.push([a,b,c,e,g,h]),acc),[])
themeSheet
.getRange(2,1,out.length, out[0].length)
.setValues(out)
I've seen this question return quite a few results here, but I'm having trouble getting it to work for my use case. Basically, I have a simple script that I want to run on multiple sheets in my spreadsheet (not every sheet, just the ones I define). I've tried defining the sheets and running a for loop, but it fails when calling the method getRange. Anyway, here's my original script that defines only one sheet, and this works as expected:
var sheetToSort = "Sheet1";
var columnToSortBy = 1;
var rangeToSort = "A2:AB";
function onEdit() {
var sheet = SpreadsheetApp.getActiveSheet();
var editedCell = sheet.getActiveCell();
if (editedCell.getColumn() == columnToSortBy && sheet.getName() == sheetToSort) {
sortFormResponsesSheet();
}
}
function sortFormResponsesSheet() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetToSort);
var range = sheet.getRange(rangeToSort);
range.sort( { column : columnToSortBy, ascending: false } );
}
This is an example of putting settings into an object and then looping through the object.
function onEdit() {
const sheet = SpreadsheetApp.getActiveSheet(),
editedCell = sheet.getActiveCell(),
editedColumn = editedCell.getColumn(),
sheetName = sheet.getName();
// Define all the sheets to sort using an object literal
const objSheetsToSort = {
"Sheet1": {columnToSortBy: 1, rangeToSort: "A2:AB"},
"Sheet2": {columnToSortBy: 2, rangeToSort: "A2:AB"},
"Sheet3": {columnToSortBy: 3, rangeToSort: "A2:AB"},
"Sheet4": {columnToSortBy: 4, rangeToSort: "A2:AB"}
}
// Get the sort info for this sheet (or `undefined` if we didn't define how to sort the edited sheet).
var config = objSheetsToSort[sheetName];
if (config && editedColumn === config.columnToSortBy) {
// We want to sort the edited sheet.
sortSheet_(sheet, config);
}
}
// This function can only be called by other functions in this Script Project, not manually or via menu.
function sortSheet_(sheetToSort, objectOfSettings) {
Logger.log('sheetToSort: ' + sheetToSort.getName())
var range = sheetToSort.getRange(objectOfSettings.rangeToSort);
range.sort( { column : objectOfSettings.columnToSortBy, ascending: false } );
}
I'm looking way to create easier version of my code. I want to, copy information from every sheet to one sheet. First informations from first sheet, then below from second sheet etc. Now I have every each code for sheet, it is any way to make it easier? What code should use? Below my code and drawing with explanation.
function copy() {
var ur = SpreadsheetApp.getActiveSpreadsheet(); // sheet where we copy data
var urgents = ur.getSheetByName("List");
var lastRow = urgents.getLastRow();
var range = urgents.getRange("A2:B");
range.clear(); // every time script clear data
var importsh = SpreadsheetApp.openById('115nqlMpW3dhI-adpWvir5RZeayM01HqvjOcDc2_yLvQ');
var imbrak = importsh.getSheetByName('List_1'); // sheet from we copy data
var imbrak2 = importsh.getSheetByName('List_2'); // sheet from we copy data
var lastcol = importsh.getLastColumn();
var lastcol2 = imbrak2.getLastColumn();
var last = imbrak.getLastRow();
var last2 = imbrak2.getLastRow();
var urlast = last;
var urlast2 = last2;
var data = imbrak.getRange("A2:B"+last).getValues();
var data2 = imbrak2.getRange("A2:B"+last2).getValues();
urgents.getRange("A2:B"+last).setValues(data);
urgents.getRange(getFirstEmptyRowWholeRow3(),1,last2-1,2).setValues(data2);
}
Regards
How about this modification? Please think of this as one of several answers.
Modification points :
Use an array for sheet names.
By this, when it increases the number of sheets, you can use this script by importing the sheet names to the array.
All data of each sheets is imported to an array.
By this, the data can be imported to the destination sheet by one call of setValues().
Modified script :
function copy() {
var ur = SpreadsheetApp.getActiveSpreadsheet(); // sheet where we copy data
var urgents = ur.getSheetByName("List");
var lastRow = urgents.getLastRow();
var range = urgents.getRange("A2:B");
range.clear(); // every time script clear data
// Added
var importsh = SpreadsheetApp.openById('115nqlMpW3dhI-adpWvir5RZeayM01HqvjOcDc2_yLvQ');
var sheets = ['List_1', 'List_2']; // Please import sheet names here.
var data = [];
sheets.forEach(function(e){
var s = importsh.getSheetByName(e);
var values = s.getRange("A2:B"+s.getLastRow()).getValues();
Array.prototype.push.apply(data, values);
});
urgents.getRange(2, 1, data.length, data[0].length).setValues(data); // Please confirm this range.
}
Note :
Please confirm the range of urgents.getRange(2, 1, data.length, data[0].length).setValues(data);. Because I have no information about getFirstEmptyRowWholeRow3().
In the current range, the data is imported to "A2:B".
If I misunderstand your question, please tell me. I would like to modify.
I am pretty new to this forum and also to the google scripts. I have never actually learned JavaScript or any other programming language, however I was forced to start using then since the time I chose the google apps as my main platform for my small business.
My problem is in google ImportRange function limitation to 50 on every spreadsheet. I created a model, where every customer has his own spreadsheet with his personal data, deadlines, etc. located in his own folder in google drive.
I also created a spreadsheet called "Organizer", Organizer has two functions -
1) create automatic correspondention using autoCrat script,
2) show deadlines for every costumer and sort them by priority.
So i need to be able to share / import / copy data from all customer spreadsheets to the "Organizer". Because there are 50+ costumer spreadsheets, I had to give up on ImportRange function and instead of that I am using a simple script to copy files from every spreadsheet directly:
function ImportDataRange() {
// rown number.1
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Databaze");
var range = sheet.getRange(2, 1)
var id = range.getValue()
var ssraw = SpreadsheetApp.openById(id);
var sheetraw = ssraw.getSheetByName("Raw");
var range = sheetraw.getRange("A2:AB2");
var data = range.getValues();
sheet.getRange("B2:AC2").setValues(data)
// row number.2
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Databaze");
var range = sheet.getRange(3, 1)
var id = range.getValue()
var ssraw = SpreadsheetApp.openById(id);
var sheetraw = ssraw.getSheetByName("Raw");
var range = sheetraw.getRange("A2:AB2");
var data = range.getValues();
sheet.getRange("B3:AC3").setValues(data)
}
This script actually works well, but problem is, when I want to add new costumer spreadsheet to "Organizer" using this method, I have to manually add new copy of whole code for every new row and also change the output range of imported data and location of source file ID in "Organizer".
Does anybody know some kind of workaroud, which will help me to add new rows / costumer data easier / automatically ?
Thank you for your help!
You are going to want to use a loop of some sort. I haven't tested the code below, but based on your example, I think this should work for you.
function ImportOtherSheets() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Databaze");
// Get the first column
// lastRow() - 1 because we're starting at row 2
var sheetIds = sheet.getRange(2, 1, sheet.getLastRow() - 1);
// For each ID in the id column
for (var i = 0; i < sheetIds.length; i++) {
var id = sheetIds[i]; // Get the id from the Array
// Get the new sheet, range and values
var ssraw = SpreadsheetApp.openById(id);
var sheetraw = ssraw.getSheetByName("Raw");
var range = sheetraw.getRange("A2:AB2");
var data = range.getValues();
// Get the local range, and write the values
sheet.getRange(i + 1, 2, 1, data[0].length).setValues(data)
}
}
As you learn more about GAS and JS, take advantage of MDN and the GAS Documentation
I took the fooby´s code and after long trial-and-error procedure I came with code that is working for me, so if anyone is interested, here it is:
function ShowDataFromOtherSheet() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Databaze");
var ids = sheet.getRange(2, 1, sheet.getLastRow() - 1).getValues();
for (var i = 0; i < ids.length; i++) {
var id = ids[i];
var ssraw = SpreadsheetApp.openById(id);
var sheetraw = ssraw.getSheetByName("Raw");
var range = sheetraw.getRange("A2:AB2");
var data = range.getValues();
sheet.getRange(i + 2, 2, 1, data[0].length).setValues(data)
}
}
And thank you fooby - i would not make it without your help!