I currently have a script that I use to apply mass changes to multiple spreadsheets
function onOpen() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var menuEntries = [];
menuEntries.push({name: "Update Sheets", functionName: "updateSheets"});
ss.addMenu("Actions", menuEntries);
}
function ChangesAug1() {
var data = SpreadsheetApp.openById('XXX').getSheetByName('ListOfSheetsToBeUpadated').getDataRange().getValues();
for (var row = 2; row < data.length; row++ ) {
var spreadsheet = SpreadsheetApp.openById(data[row][0]).getSheetByName('Template');
And I have this other script I am using to copy and paste a range from one spreadsheet to another
var sss = SpreadsheetApp.openById('SourceID'); //replace with source ID
var ss = sss.getSheetByName('TemplateSheet'); //replace with source Sheet tab name
var range = ss.getRange('A1:EJ5'); //assign the range you want to copy
var data = range.getValues();
var tss = SpreadsheetApp.openById('DestID'); //replace with destination ID
var ts = tss.getSheetByName('DestSheet'); //replace with dest
ts.getRange(ts.getLastRow()+1, 1,5,140).setValues(data); //you will need to define the size of the copied data see getRange()ination Sheet tab name
Any Idea on how I can combine the 2 scripts to mass apply a copied range from one sheet to a list of sheets ?
Thank you for responses :)
You should just create a function that is used to copy the data wanted from one sheet to another and then call this function when accessing the sheets in the for loop you are using.
Therefore, you can use something similar to this:
function copyFromOneSheetToAnother(var sourceSheet,
var destinationSheet) {
var range = sourceSheet.getRange('A1:EJ5');
var data = range.getValues();
destinationSheet.getRange(ts.getLastRow() + 1, 1, 5, 140).setValues(data);
}
The above function is expecting two parameters: the sourceSheet and the destinationSheet. As for calling this function, you can just use this:
function ChangesAug1() {
var data = SpreadsheetApp.openById('XXX').getSheetByName('ListOfSheetsToBeUpadated').getDataRange().getValues();
for (var row = 2; row < data.length; row++) {
var spreadsheet = SpreadsheetApp.openById(data[row][0]).getSheetByName('Template');
//get THE_DESTINATION_SHEET as well
copyFromOneSheetToAnother(spreadsheet, THE_DESTINATION_SHEET);
}
}
Reference
Sheet Class Apps Script;
Range Class Apps Script.
Related
Pretty new to coding and I've been trying to solve this one, but I can't find out how and now I'm turing to you guys:
There is a spec sheet, containing a couple of information on an item:
Product Name (on A3)
Product Code (on A4)
Volume (on c3)
Und (on C4)
Cost (on A5), etc.
Then, underneath this "header", there is a table containing the ingredients that make up that item:
ItemNumber, Product, Manufacturer, Unt, Cost, Remarks
These are set on a range (A12:T50)
The need is to have this table moved to a sheet, which the below code does, but how I can I have the header moved as well, repeating each of the header ranges, forming a database-like table for further consulting?
Here is the working script:
function copyrange() {
var sourceSheet = 'New Item';
var destinationSheet = 'Consolidated';
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName(sourceSheet);
var LastRowSource = sheet.getLastRow();
var LastColumnSource = sheet.getLastColumn();
var values = sheet.getRange(11,1,LastRowSource,LastColumnSource).getValues();
var csh = ss.getSheetByName(destinationSheet);
var data = [];
var j =[];
for (var i = values.length-1; i != ""; i--) {
if ( values[i][0] != '') {
data.push(values[i]);
//sheet.deleteRow(i+1)
}
}
//Copy data array to destination sheet
csh.getRange(csh.getLastRow()+1,1,data.length,data[0].length).setValues(data);
}
Here is the link to the file in question:
https://docs.google.com/spreadsheets/d/1GlD_VIOFHj7PGfCCnfVZqdZbE22aVoUw91BSCZecsRc/edit#gid=371161645
Any help is appreciated.
I am trying to come up with a function that could extract data from one workbook to another that has a separate format. I will refer to the workbooks as "Source" and "Destination". So, on the "Source", I have the data arranged in yearly tabs. However, on "Destination", I have tabs indicating the regions. I have attached snapshots of the two workbooks.
Since I have no basics in programming, I tried to come up with a code but it didn't quite work. The following is my attempt at a nested for-loop which first extracts the data from the "2015" tab of the first region ("Ampang"), and pastes it into the other workbook in the "Ampang" tab and the "2015" row. I ran the debugging function and it says that the "var data" is undefined.
function D() {
var ss = SpreadsheetApp.getActiveSpreadsheet();//open destination worksheet
var sss = ss.getSheets(); //get all destination sheets
//var sheetname = ss.getSheetName(); //get sheet names
var sheet1 = SpreadsheetApp.openByUrl("https://docs.google.com/spreadsheets/d/1jJ8QysQTmS5tG4wvNCxqdbWvAbdbmJm5uatdgIHe6tw/edit#gid=793399042"); //open where data is located
var sheet = sheet1.getSheets(); //get all the sheets required
for (j = 0; j<sss.length; j++) {
for (i = 0; i <sheet.length; i++) {
switch(sheet[i].getSheetName()) {
case "Main Menu" :
break;
default:
var data = sheet.getSheets()[i].getRange(i+1, i+2, 1, 2); //get the data for Specific Region and then Changing the Year
var destination = sss[j].getRange(j,j+1,1,2); //pasting the data to the specific year at the Specific Region Tab/
data.copyTo(destination);
}
}
}
}
[Update 1]
So, I realized that the copyTo() function doesn't work when the data are in separate workbooks so I have come up with a new code below:
function D() {
// define the source sheets
var ss = SpreadsheetApp.openByUrl("https://docs.google.com/spreadsheets/d/1jJ8QysQTmS5tG4wvNCxqdbWvAbdbmJm5uatdgIHe6tw/edit#gid=793399042");
// get all source sheets
var source = ss.getSheets();
// define the target sheets
var ts = SpreadsheetApp.getActiveSpreadsheet();
// get all target sheets
var target = ts.getSheets();
// set nested for-loop
for (j = 0; j < target.length; j++) {
for (i = 0; i < source.length; i++) {
if (source[i].getSheetName() !== "Main Menu") {
var rangeSource = source[i].getRange(i+1,i+1,1,2); // get the source range
var values = rangeSource[i].getValues(); // get the values from the set range
}
if (target[j].getSheetName() !== "Main Menu") {
var rangeTarget = target[j].getRange(j+1,j+1,1,2); //get the target range
rangeTarget.setValues(values[i]); // paste the values to the target range
}
}
}
}
However, the var rangeSource and values are currently undefined. I still am trying to find the source of the error.
Source Sheets Snapshot
Destination Sheets Snapshot
You've defined sheet as all the sheets
var sheet = sheet1.getSheets(); //get all the sheets required
So data needs to be
var data = sheet[i].getRange(i+1, i+2, 1, 2); //get the data for Specific Region and then Changing the Year
See is that helps.
Ok...not sure how to do this. Right now I 4 sheets and 4 scripts for each sheet producing 4 json feeds. What I am trying to experiment with is having one script that will produce 1 json that I can use in a web page and just call the type of class. They are all formatted the same with columns etc.
Here is the Google Script App code I have.
function doGet(e){
// Change Spread Sheet url
var ss = SpreadsheetApp.openByUrl("https://docs.google.com/spreadsheets/d/SpreadsheetID/edit#gid=0");
// Sheet Name, Change Sheet to whatever name you used to name your sheet
var sheet = ss.getSheetByName("Class Sheet 1");
return getClasses(sheet);
}
function getClasses(sheet){
var dataObj = {};
var dataArray = [];
// collecting data starting from 2nd Row , 1st column to last row and last column
var rows = sheet.getRange(2,1,sheet.getLastRow()-1, sheet.getLastColumn()).sort([{column: 1, ascending: true}, 1]).getValues();
for(var i = 0, l= rows.length; i<l ; i++){
var dataRow = rows[i];
var record = {};
record['Name'] = dataRow[0];
record['Note'] = dataRow[1];
record['Address'] = dataRow[2];
record['StreetAddress'] = dataRow[3];
record['City'] = dataRow[4];
record['State'] = dataRow[5];
record['ZipCode'] = dataRow[6];
record['ContactName'] = dataRow[7];
record['EMailAddress'] = dataRow[8];
record['CustomerServicePhone'] = dataRow[9];
dataArray.push(record);
}
dataObj = dataArray;
var result = JSON.stringify(dataObj);
return ContentService.createTextOutput(result).setMimeType(ContentService.MimeType.JSON);
}
Scratching my head on this a little bit....I'm sure its something simple and I am probably over thinking things, but any help would be appreciated.
Possible Solution:
The e object in your doGet(e) provides a way to send parameters to your script. You can access different sheets with different url parameters. You can then easily get the requested SheetName through e.parameter. Use
https://script.google.com/.../exec?sheet=ClassSheet1 //for ClassSheet1
https://script.google.com/.../exec?sheet=ClassSheet2 //for ClassSheet2
Code.gs:
function doGet(e){
var ss = SpreadsheetApp.openByUrl("https://docs.google.com/spreadsheets/d/SpreadsheetID/edit#gid=0");
var sheetName = e.parameter.sheet;
var sheet = ss.getSheetByName(sheetName);
return getClasses(sheet);
}
You can also provide UI in your web-app to select a sheet.
I'm doing a data transfer of several spreadsheets to a single one, what I do is transfer the last data of certain columns to the master spreadsheet and also insert them in the last available row of certain columns, for now, I insert all the data but I would like to to know how I can have it examine the master spreadsheet so that if those data already exist, it does not delete them but update them. The script that I have is the following ...
function Gas10(){
var ss1 = SpreadsheetApp.openById("ID");
var ssh1 = ss1.getSheetByName("Sheet 1");
var lastRow1 = ssh1.getLastRow();
var gtRange1 = ssh1.getRange("C"+(lastRow1)+":K"+(lastRow1)).getValues();
var gtRange2= ssh1.getRange("A" + (lastRow1)).getValue();
var ss2 = SpreadsheetApp.getActiveSpreadsheet();
var ssh2 = ss.getSheetByName("Sheet 2");
var lastRow2 = ssh2.getLastRow() + 1;
var setRange1 = ssh2.getRange(lastRow2, 4, gtRange1.length, gtRange1[0].length).setValues(gtRange1);
var setRange2 = ssh2.getRange(lastRow2, 3).setValue(gtRange2);
}
I need to know how I can do it when I insert a piece of information (I already do that), but update it if it already exists. This is the example that I created so that it can be better understood, in this example I have two sheets of which from sheet 1 I pass data to sheet 2 and what I'm looking for is that sheet 2 updates all the data that are equal to (Name, Num, Proyect). I hope that now I understand better what I'm looking for.
Basically what you have to do is
get the new Line you want to add to the destination spreadsheet
get all the required datas of the destination spreadsheet
Check if the new Line datas have the same datas than in the destination data array
If so change ID value
paste changed datas in the destination spreadsheet
based on this spreadsheet The code should look something like this
function Gas10(){
var ss1 = SpreadsheetApp.getActiveSpreadsheet();
var ssh1 = ss1.getSheetByName("Sheet 1");
var ssh2 = ss1.getSheetByName("Sheet 2");
var lastRow1 = ssh1.getLastRow();
var lastCol1 = ssh1.getLastColumn();
var newLine = ssh1.getRange(lastRow1, 2, 1, lastCol1 - 1 ).getValues();
var destDatas = ssh2.getDataRange().getValues();
for (var i = 1; i < destDatas.length; i++)
{
if (newLine[0][0] == destDatas[i][0]
&& newLine[0][1] == destDatas[i][1]
&& newLine[0][2] == destDatas[i][2])
{
destDatas[i][3] = newLine[0][3];
}
}
// add newLine to destDatas
destDatas.splice(destDatas.length, 0, newLine[0]);
var lastColumn = ssh2.getLastColumn();
var lastRow2 = ssh2.getLastRow() + 1;
ssh2.getRange(1, 1, destDatas.length, lastColumn).setValues(destDatas);
ssh1.deleteRow(lastRow1);
}
Here's an example I played around with:
It looks at the slave sheet for any data. When it finds data it puts the row and col and value into an obj which is then added to an array. When it finishes it calls the updMaster which then looks for data in those same cells (assuming that the cells are in the same place if those cells are blank then it adds data and I also changed the background to lightblue to show me where it updated the cells.
You could run the getSlaveData() for different sheets if you wish.
function getSlaveData(){
var ss=SpreadsheetApp.getActive();
var ssh=ss.getSheetByName('Sheet2');
var sA=[];
var srg=ssh.getDataRange();
var svA=srg.getValues();
for(var i=0;i<svA.length;i++){
for(var j=0;j<svA[i].length;j++){
//if(svA[i][j]){
if(!ssh.getRange(i+1,j+1).isBlank()){//optional way to look for values
var sObj={};
sObj['row']=i + 1;
sObj['col']=j + 1;
sObj['value']=svA[i][j];
sA.push(sObj);
}
}
}
updMaster(sA);
}
function updMaster(sA){
var ss=SpreadsheetApp.getActive();
var msh=ss.getSheetByName('Sheet1');
for(var i=0;i<sA.length;i++){
if(msh.getRange(sA[i].row,sA[i].col).isBlank()){
msh.getRange(sA[i].row,sA[i].col).setValue(sA[i].value);
msh.getRange(sA[i].row,sA[i].col).setBackground('lightblue');
}
}
}
I'm trying to create an input field in a google spreadsheet to enable simple data collection, but I'm having some trouble with a for loop. I'm a JS novice, and this is the first time I've attempted to use Google Apps Script.
App logic:
- data entered into a input field ("Sheet1!F13:F36")
- button with script assigned is clicked
- data is loaded from the input field and appended to a dataset in Sheet2
Please see my code below:
function appendToDB() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var dashboard = ss.getSheetByName("Dashboard");
var inputRange = dashboard.getRange("F13:F36");
var db = ss.getSheetByName("Database");
var storeName = dashboard.getRange("C7").getValue();
var category = dashboard.getRange("C9").getValue();
for(var i=0; i<inputRange.length; i++){
var currentCellValue = inputRange[i].getValue();
db.appendRow([storeName,category,currentCellValue]);
}
}
The following dashboard.getRange("F13:F36") function returns a range class not an array. Hence when you do try to get a length like so inputRange.length you get a return of undefined and loop is never run.
You can get the values of the cells by using getValues and run through the array in loop and append the values to the db sheet like so
function appendToDB() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var dashboard = ss.getSheetByName("Dashboard");
var inputRange = dashboard.getRange("F13:F36").getValues(); //returns a 2D array
var db = ss.getSheetByName("Database");
var storeName = dashboard.getRange("C7").getValue();
var category = dashboard.getRange("C9").getValue();
for(var i=0; i<inputRange.length; i++){
var currentCellValue = inputRange[i][0];
db.appendRow([storeName,category,currentCellValue]);
}
}
Equivalently, you can use getNumRows() function of range class, to get the number of rows. Use that as a counter to loop through to get individual values of individual cell by getCell(row,column).getValue()
Which would look like this:
function appendToDB() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var dashboard = ss.getSheetByName("Dashboard");
var inputRange = dashboard.getRange("F13:F36");
var db = ss.getSheetByName("Database");
var storeName = dashboard.getRange("C7").getValue();
var category = dashboard.getRange("C9").getValue();
for(var i=1; i<=inputRange.getNumRows(); i++){
var currentCellValue = inputRange.getCell(i,1).getValue();
db.appendRow([storeName,category,currentCellValue]);
}
}