I'm trying to create a script to copy data from sheet 1 to sheet 2 and at the same time reorder it. I get my data from a Google form, so data is constantly updating.
Here are two images as examples. N°1 is how I have my data, N°2 is how I want it to be in sheet 2.
The idea is to have the script copying the data every time a new row appears.
Data from Forms.
This is how I would like it to be.
This is my initial code:
function copyrange() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Ingreso'); //source sheet
var testrange = sheet.getRange('J:J');
var testvalue = (testrange.getValues());
var csh = ss.getSheetByName('Auxiliar Ingreso'); //destination sheet
var data = [];
var columnasfijas = [];
var cadena = [];
//Condition check in G:G; If true copy the same row to data array
for (i=1; i<testvalue.length;i++) {
data.push.apply(data,sheet.getRange(i+1,1,1,9).getValues());
if ( testvalue[i] == 'Si') {
data = (sheet.getRange(i+1,1,1,9).getValues()).concat (sheet.getRange(i+1,11,1,9).getValues()); // this beaks up into 2 rows Idon't know why
/*cadena = (columnasfijas);
data.push.apply(data, columnasfijas);*/
}
csh.getRange(csh.getLastRow()+1,1,data.length,data[0].length).setValues(data);
}
//Copy data array to destination sheet
//csh.getRange(csh.getLastRow()+1,1,data.length,data[0].length).setValues(data);
}
In this line, I'm also having trouble concatenating different lengths of data. It should be: (i+1,1,1,6). concat.....(i+1,11,1,3)
data = (sheet.getRange(i+1,1,1,9).getValues()).concat (sheet.getRange(i+1,11,1,9).getValues()); // this beaks up into 2 rows Idon't know why
When I run it as it should by I receive an error that the length should be 9 instead of 3.
This can be accomplished more simply using formulas instead of app scripts:
=sort(importrange("spreadsheetURL", "Sheet1!A2:AA10000"),sort_col#,TRUE/FALSE,[sort_col2#],[TRUE/FALSE]...)
Documentation on importrange function: https://support.google.com/docs/answer/3093340
Documentation on sort function: https://support.google.com/docs/answer/3093150
Once you input the formula, there will likely red triangle on the cell, be sure to click on the cell and click the Allow Access button to give one spreadsheet access to the other.
Related
I am looking for help to create a filter on Google Sheets Script.
I want the following:
I have a database Schedule which has table with information that I want to filter
Once the database A is updated I want to filter Colum b row 8 and only take the cells that have information and are filled with words, numbers, etc.
After that I want to copy the data filtered and paste on a new Sheet Data “Foreman on specific columns
Also, I want to copy and paste the format such as color, size, etc.
I have the following code which it does the partial job but I cannot figure it out to only get the specific data needed
function Foreman(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var scheduleCCC_sheet = ss.getSheetByName("Schedule");
var Foreman_sheet = ss.getSheetByName("Foreman");
var pasteforemans = Foreman_sheet.getRange(8,2);
var originalData = scheduleCCC_sheet.getRange(9,2,scheduleCCC_sheet.getLastRow()1,11).getValues();
var filter1 ="";
Foreman_sheet.getRange(8,2,Foreman_sheet.getLastRow(),11).clearContent().clearFormat();
var data = originalData.filter(filterlogic);
Foreman_sheet.getRange(9,2,data.length,data[0].length).setValues(data);
}
var filterlogic = function(item){
if(item[1] == ""){
return false;
}else {
return true;
}
In order to filter the values based on the condition that the cells are not empty, you can use the below snippet of code:
Snippet
function myFunction() {
var ss = SpreadsheetApp.openById("ID_OF_THE_SS").getSheetByName("Schedule CCC");
var otherss = SpreadsheetApp.openById("ID_OF_THE_SS").getSheetByName("Foreman");
var range = ss.getRange("START_ROW", "START_COL", ss.getLastRow(), ss.getLastColumn());
var filter = range.getFilter();
var filterCriteria = SpreadsheetApp.newFilterCriteria().whenCellNotEmpty().build();
filter.setColumnFilterCriteria("COL_POSITION", filterCriteria);
for (var i = 1; i <= ss.getLastRow(); i++) {
if (ss.isRowHiddenByFilter(i) == false) {
ss.getRange("RANGE_FROM_THE_CCC_SHEET").copyTo(otherss.getRange("RANGE_FROM_THE_FOREMAN_SHEET"));
}
}
}
Explanation
The above code gathers the filter from the source sheet and sets it the whenCellNotEmpty criteria. Afterwards it loops through the data and checks if a specific row is hidden by the filter; if the result of this is false, then it copies the row with its format onto the destination sheet. The format of the row is preserved by using the copyTo method.
Note
You will need to adjust the ranges to match the ones in your sheet and might need to add another condition when looping through the data from the source sheet.
Reference
Apps Script Sheet Class - isRowHiddenByFilter(rowPosition);
Apps Script Filet Class - setColumnFilterCriteria(columnPosition, filterCriteria);
Apps Script Sheet Class - copyTo(spreadsheet).
I'm new with this drivesheets thing, but its great! I have worked with Excel and Vba and I'm very excited to see this whole new world.
Here is my problem: In Excel, I have file with a "template". This template is linked to data that changes depending on a cell value. For example, in cell K26 there is a key number; if its value is 1, the template will show you the information related with 1. If it is 2, it will show you the information related with 2 and so on. There's a list of the numbers that I want to generate, so when I run the code the template will add a new sheet, copy its current values and paste them in the new sheet, rename the sheet from "SheetX" to the value of cell K26 and then continue with the next row.
Question: I want to do the same in drivesheets, but dont know how to start.
My template sheet is called "Generador", and the current registry is in cell K26 (this would be the sheet's name too). The range I want to copy is from A1 to I67. If it possible, I would like to have a new workbook, and in this workbook create all the sheets of the list. The list can be anywhere in the "List" sheet.
Thanks in advance.
EDIT:
My code so far:
based on this
function createEmployeeSheets() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
// Get the range of cells that store employee data.
var ssLista = ss.getSheetByName("Lista");
var rgEData = ssLista.getRange(2,1);
var eData=rgEData.getValue();//número de registros
var employeeDataRange = ssLista.getRange(2,1,eData,1);//Nombres de hoja empezando en columna 1 desde fila 2
var employeeObjects = employeeDataRange.getValues();
var template = ss.getSheetByName('Generador');
for (var i=0; i < employeeObjects.length; i++) {
// Put the sheet you want to create in a variable
var sheet = ss.getSheetByName(employeeObjects[i]);
// Check if the sheet you want to create already exists. If so,
// log this and loop back. If not, create the new sheet.
if (sheet) {
Logger.log("Sheet " + employeeObjects[i] + "already exists");
} else {
template.getRange("K3").offset(0,0).setValue(employeeObjects[i]);
template.copyTo(ss).setName(employeeObjects[i]);
}
}
return;
i = 0;
}
I have managed to generate every sheet, change K3 of the template value and rename it. I'm missing two things:
I'm still getting an error: when the code starts generating the sheets it goes on and doesn't stop in the last row of the "List" sheet. For example, I have 3 rows with values, and when the loop goes for the 4 it shows the error line, because it can't name the sheets with nothing (null).
The other thing is that I want to generate the sheets in a new workbook, not in the current one. Is there a way that these sheets can be created in a new one? Considering that information is linked with formulas, so it should be values only.
Thanks.
Try this:
The getValues() function returns a 2D array Objec[][]
function createEmployeeSheets() {
var ss = SpreadsheetApp.getActive();
var shLista = ss.getSheetByName('Lista');
var rgEData = shLista.getRange(1,3);
var eData=rgEData.getValue();//the number of names I think
var employeeDataRange = ssLista.getRange(2,1,eData,1);//Sheet names in column1 starting from row2
var employeeObjects = employeeDataRange.getValues();//sheet names in column 0
var template=ss.getSheetByName('Generador');//template
for (var i=0;i< employeeObjects.length; i++) {
if(!ss.getSheetByName(employeeObjects[i][0])){
template.getRange("K3").setValue(employeeObjects[i][0]);
var sheet=ss.insertSheet(employeeObjects[i][0], {template:template});
}
}
}
Insert Sheet(Sheetname, options)
getValues()
This code has not been tested.
I'm new to Google App Scripts and JavaScript as I work on the marketing side. I'm currently trying to create a database in Google Sheets to use in DataStudio as I want to blend data from various sources.
I have Google Sheets with a sheet to feed the data (through add-ons) and another sheet which I intend to use as the database. What I'm trying to do is to save data in the database, new data being saved at the end of the spreadsheet each time (I will set a time-based trigger when my script works). I've written a script using Google's documentation but it's only copying the first line of my Data sheet to the database. I would need it to copy all the content from the data sheet to the database sheet.
Here is the script I have for now :
// function to save data
function saveData() {
// starts with active sheet for data entry
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Data");
// collects values in data entry row
var url = sheet.getRange("Data!A1:A").getValues();
var follower_count = sheet.getRange("Data!B1:B").getValues();
var date = sheet.getRange("Data!C1:C").getValues();
// identifies and adds data to Database
var data1 = ss.getSheetByName("Database");
var aVals = data1.getRange("A1:A").getValues();
var aLastRow = aVals.filter(String).length;
Logger.log(aLastRow);
var newAttData = [[url,follower_count,date]];
Logger.log(newAttData);
data1.getRange(aLastRow +1,1,1,3).setValues(newAttData);
}
I've tried to change the range width and length in the last line but I always get an error:
Incorrect range height, was 1 but should be 3 (line 31, file "Code")
I've spent a lot of time on this but I can't get it to work. Any help would be great !
As Described in the documentation:
setValues(values)
Sets a rectangular grid of values (must match dimensions of this range).
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
// The size of the two-dimensional array must match the size of the range.
var values = [
[ "2.000", "1,000,000", "$2.99" ]
];
var range = sheet.getRange("B2:D2");
range.setValues(values);
Reference
I have been searching for a way to copy certain cells from a row and paste them into another spreadsheet, but all I can seem to find are ways to do that just from sheet to sheet within one spreadsheet or questions that deal with code way above my head. I'm just now learning to code in Google Spreadsheets and I can't seem to get it right. Here is my code for now, I'm working on just copying one cell first and after I can do that I'll get a loop to iterate through the row and pick the cells I want to copy.
var ss = SpreadsheetApp.getActiveSpreadsheet();
var master = SpreadsheetApp.openById('0AgcCWQn-aoI1dFpLVE4tSENwcThrYnlMUzhuRmdWU2c');
var target = SpreadsheetApp.openById('0AgcCWQn-aoI1dF96X2dBT2dVVFZ2SU1NRWdYTDJhT2c');
var master_sheet = master.getSheetByName("Steve2");
var target_sheet = target.getSheetByName("Corbin1");
var master_range = master_sheet.getRange("A1");
var target_range = target_sheet.getRange("A1");
master_range.copyTo(target_range);
Right now it is giving me an error saying that it cannot call the getRange method of null. I'm not sure if I'm using OpenById correctly or if I can even use that in this situation.
OK I've got it working now. It copies the row perfectly and it copies only the cells I want. Now I need help with the pasting part. It copies everything fine and puts it into the other sheet great, but I need it to copy into the next available row and into the first available columns. So if row 5 is the last column of data, I need it to paste into row 6 and take up the first 6 or so columns.
This is what I have so far.
function menuItem1() {
var sss = SpreadsheetApp.openById('0AgcCWQn-aoI1dFpLVE4tSENwcThrYnlMUzhuRmdWU2c'); // sss = source spreadsheet Steve2
var ss = sss.getSheetByName('Sheet1'); // ss = source sheet
//Message box asking user to specify the row to be copied
var answer = Browser.inputBox('What row would you like to copy?');
var range = parseInt(answer);
var array = [1,2,3,9,12,30];
//Runs a loop to iterate through array, using array elements as column numbers
for(var i = 0; i < array.length; i++){
var SRange = ss.getRange(answer,1,1,array[i]);
//get A1 notation identifying the range
var A1Range = SRange.getA1Notation();
//get the data values in range
var SData = SRange.getValues();
}
var tss = SpreadsheetApp.openById('0AgcCWQn-aoI1dF96X2dBT2dVVFZ2SU1NRWdYTDJhT2c'); // tss = target spreadsheet Corbin1
var ts = tss.getSheetByName('Sheet1'); // ts = target sheet
//set the target range to the values of the source data
ts.getRange(A1Range).setValues(SData);
//Confirmation message that the row was copied
Browser.msgBox('You have successfully copied Row: ' + answer);
}
You are getting this error maybe because your spreadsheet does not have a sheet called Steve2 or Cobin1. Try using the method master.getSheets()[0], this way you will get the first sheet without using their name.
You can algo use this piece of code to check the sheets names:
for(var x in master.getSheets()) {
Logger.log(master.getSheets()[x].getSheetName());
}
best,
I have written a code for this but getting an error
The coordinates or dimensions of the range are invalid. (line 44)
Code:
function updateMaster() {
var repArray = new Array();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var allSheets = ss.getSheets();
// build array of all sheets
for (i in allSheets) {
if ((allSheets[i].getName()).match(/.*?\-Rep$/))
{repArray.push(allSheets[i].getName());}
}
// store all sheets in array
var sheetArray = [];
// loop through all rep sheets
for (var j in repArray) {
// get each sheet
var tempSheet = ss.getSheetByName(repArray[j]);
// get sheet data
var dataRange = tempSheet.getDataRange().getValues();
// remove the first header row
dataRange.splice(parseInt(0), 1);
// append sheet data to array
var sheetArray = sheetArray.concat(dataRange);
}
// Time to update the master sheet
var mSheet = ss.getSheetByName("summary");
// save top header row
var headerRow = mSheet.getRange(1,1,1,12).getValues();
// clear the whole sheet
mSheet.clear({contentsOnly:true});
// put back the header row
mSheet.getRange(1, 1, 1, 12).setValues(headerRow);
This is where i am getting error while writing to master sheet:
// write to the Master sheet via the array
mSheet.getRange(2, 1, sheetArray.length, 12).setValues(sheetArray);
// force spreadsheet updates
SpreadsheetApp.flush();
// pause (1,000 milliseconds = 1 second)
Utilities.sleep("200");
// delete empty rows at bottom
var last = mSheet.getLastRow();
var max = mSheet.getMaxRows();
if (last !== max) {mSheet.deleteRows(last+1,max-last);}
}
I am not able to figure out the error.
You need a sheet with "Rep" inside the name.
"The first array stores all the Sales Rep sheets. Since some sheets could be something other than Sales Rep sheets, the script stores sheets only if the sheet name has a “-Rep” suffix (e.g. “JohnDoe-Rep”)"
code source: http://blog.ditoweb.com/2012/01/consolidate-spreadsheet-sheets-with.html
That's why it's not working.
mSheet.getRange(2, 1, sheetArray.length, 12).setValues(sheetArray)
I faced the same issue and solved it by following the "Rep" solution. Then I ran into another problem and realized that my number of columns was different... so just go back in and change the no 12 to the number of rows you have in your sheet.
Also try to keep the format of the all sheets the same.
Rename the sheet where you would like the data to combine