I'm really new to google sheets app script. I need an script which finds a date in row 1, selects the entire row and copy and paste values only. This is because I have formulas in each column which will only work if row 1 matches =today().
To get the range values and save into a variable (copy):
var book = SpreadsheetApp.openByUrl(url); //url=spread sheet url
var sheet = book.getSheetByName("sheet name");
var range = sheet.getRange(a, b, x, y).getValues();
//a=inicial row ,b=inicial column, x=last row, y=last column
// range will be a bidimensional array
// "A1" cell value will be: range[0][0]
To append in new cells (paste): //you have to iterate the array
sheet.appendRow([range]);
Related
Context
So I have a spreadsheet with 11+ sheets, though will be adding more later. I want to dynamically name the columns using named range. I created a macro script and have been using this. Only the problem is for every sheet, I have to go to the script and change the name of the named range:
function NamedRanges() {
var spreadsheet = SpreadsheetApp.getActive();
spreadsheet.setNamedRange('TrainlineDate', spreadsheet.getRange('A:A'));
spreadsheet.setNamedRange('TrainlinePrice', spreadsheet.getRange('B:B'));
spreadsheet.setNamedRange('TrainlineReturns', spreadsheet.getRange('C:C'));
spreadsheet.setNamedRange('TrainlineGrossReturns', spreadsheet.getRange('D:D'));
spreadsheet.setNamedRange('TrainlineGeometricReturns', spreadsheet.getRange('E:E'));
spreadsheet.setNamedRange('TrainlineRisk', spreadsheet.getRange('F:F'));
spreadsheet.setNamedRange('TrainlineNegativeReturns', spreadsheet.getRange('G:G'));
spreadsheet.setNamedRange('TrainlinePositiveReturns', spreadsheet.getRange('H:H'));
spreadsheet.setNamedRange('TrainlineTimeValueMoney', spreadsheet.getRange('I:I'));
};
For example, for the next tab, I have to change Trainline to Softcat.
I tried my hand at creating the columns as an array and then a for loop to create a named range according to the name in cell B2 + the name in the headers (the 3rd row of every column). I will also be adding new columns in the future. But when I tried to log the value in cell B2 it failed. Long story short, I am stuck. This is what I came up with thus far;
function NamedRange() {
const ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var col = ss.getLastColumn(); //Get all the columns in the sheet with data (there will be no gaps/spaces)
var stockName = ss.getRange("B1"); // name in cell B1 (column 2, row 1)
var headerCell = ss.getRange(3, col); // in row 3 of all columns
var rangeName = ss.getValue(stockName);
Logger.log(rangeName) // test to see if the value of stockname is picked up by Appscript
// For every column, get the values in 'stockName and headerCell' and create a named range from them.
An exception is for the second column, instead of 'Close' name, call it 'Stockname' + 'Price'.
};
Here is an example of the spreadsheet format. This script though will be applicable to Aveva Group tab onwards.
Problem
Typically the format of the spreadsheets will all be the same. The only difference will be the name of the stock. I want to be able to automatically set the namedRange of all columns for existing and new columns for every tab/sheet and trigger it using a custom menu (this part I can sort out myself). Is there a better way to get this done?
Explanation:
Create an array of all the sheet names you would like to be part of this process.
ForEach sheet name, set the name ranges according to that name by concatenating the sheet name with the namerange name.
Solution:
function NamedRanges() {
var spreadsheet = SpreadsheetApp.getActive();
//put all the sheets here you want to include
var sheetNames = ["Trainline","Softcat","Avast"];
var namerng=['Date','Price','Returns','GrossReturns','GeometricReturns',
'Risk','NegativeReturns','PositiveReturns','TimeValueMoney'];
sheetNames.forEach(sh=>{
sheet = spreadsheet.getSheetByName(sh);
namerng.forEach((nr,i)=>{
spreadsheet.setNamedRange(sh+nr, sheet.getRange(1,i+1,sheet.getMaxRows(),1));
});
});
};
Save also this code to your script editor and it will create a menu button at the top menu of the spreadsheet file that will execute NamedRanges:
function onOpen() {
SpreadsheetApp.getUi()
.createMenu('Custom Menu')
.addItem('Name Ranges', 'NamedRanges')
.addToUi();
}
I have a large google sheet with 30275 rows and 133 columns in a google sheet. I want to filter the data and copy column AZ to another spreadsheet.
Link to spreadsheet: https://docs.google.com/spreadsheets/d/1aiuHIYzlCM7zO_5oZ0aOCKDwPo06syXhWvhQMKgJE2I/edit?usp=sharing
I have been trying to follow this link
I am not that familiar with javascript and the code is designed to exclude items from filter rather than including items on filter. I have 500+ items to exclude so need to work out something that will be efficient in filtering large dataset in short time before execution limit is reached.
Here is my code so far. Any help to get this working would be appreciated.
NOTE: Filter/ Query with importrange formulas dont work due to the large volume of data. So I need an efficient script to filter large dataset and move them to another sheet before execution time limit.
function filtered() {
var ss = SpreadsheetApp.openById('1u9z_8J-tvTZaW4adO6kCk7bkWeB0pwPcZQdjBazpExI');
var sheet = ss.getSheetByName('Sheet1');
var destsheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('JockeyList');
var demosheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Betting data - Demo');
var jockey = demosheet.getRange('L14').getValues();
// Get full (non-filtered) data
var values = sheet.getRange('A:EC').getValues();
// Apply filter criteria here
//Logger.log(jockey);
var hiddenValues = jockey;
values = values.filter(function(v) {
return hiddenValues.indexOf(v[51]) == 1;
});
Logger.log(values.length);
// Set filtered data on the target sheet
destsheet.getRange(10, 5, values.length, 2).setValues(values);
}
Ok so it seems like you want to copy only the values from AZ in 'Sheet1' that are equal to whatever string value is contained in cell L14 of sheet 'Betting data - Demo.' If that is the case, then here is a change to your original code that will accomplish that:
function filtered() {
var ss = SpreadsheetApp.openById('1u9z_8J-tvTZaW4adO6kCk7bkWeB0pwPcZQdjBazpExI');
var sheet = ss.getSheetByName('Sheet1');
// this assumes that your destsheet and demosheet are in the same spreadsheet. Keep in mind that opening spreadsheets with SpreadsheetApp is costly so you want to minimize your calls to new sheets.
var destsheet = ss.getSheetByName('JockeyList');
var demosheet = ss.getSheetByName('Betting data - Demo');
var jockey = demosheet.getRange('L14').getValue();
var searchTerm = new RegExp(jockey);
// Get full (non-filtered) data
var values = sheet.getRange('A:EC').getValues();
// Apply filter criteria here and return ONLY THE VALUE IN COLUMN AZ
var filteredValues = values.reduce(function(resultArray, row) {
if (searchTerm.test(row[51])) resultArray.push([row[51]]);
return resultArray;
}, [])
// Set filtered data on the target sheet
// Note* not clear why you are starting at row 10, but as is this will overwrite all of the data in column 5 of destsheet starting from row 10 every time this function runs
destsheet.getRange(10, 5, filteredValues.length, 1).setValues(filteredValues);
}
As it says in the code sample, this will only copy and paste the value in column AZ of 'sheet1'. It does not alter 'sheet1' in any way. If that is really all you want to do, then this function works, but it's overkill. Since you are just filtering values in AZ against a single string value, it would be more efficient to simply count the number of times that string occurs in column AZ and then add the string that number of times to your destination sheet.
Also note that your original function is pasting values into destsheet into a constant row (row 10). That means that every time your function runs, the data from row 10 on will be overwritten by whatever data you are copying from 'sheet1'
Hi I have a working program to pull data from one sheet to another sheet and place in the relevant cells, however with one column I want to change the results which reads a "K" from the source sheet and write an "A" to the target sheet using a if function but I can only seem to do one cell and not the full column. How can I do this for multiple cells? If I try.getRange("F18:41") it doesn't seem to work.
Please see the code below:
var sss = SpreadsheetApp.openById('....'); // sss = source spreadsheet
var ss = sss.getSheetByName('.....); // ss = source sheet
//Get full range of data sheet 1
var TypeWire = ss.getRange("F18");
//get A1 notation identifying the range
var A16Range = TypeWire.getA1Notation();
//get the data values in range
var SDataSixteen = TypeWire.getValues();
var tss = SpreadsheetApp.openById('.....'); // tss = target spreadsheet
var ts = tss.getSheetByName('....'); // ts = target sheet
//set the target range to the values of the source data
ts.getRange("C40:C61").setValues(SDataSeven);
if (SDataSixteen == "K")
{
ts.getRange("L16").setValue("A");
}
}
The getValues() method of Class Range returns a multidimentional (2D) array. The elements of the "outer" array are arrays that represent rows. The elements of the inner arrays are objects that represent the cell values for the corresponding row.
There are several ways to do what you are looking for. Perhaps the easier to understand is the technique shown in the Cooper's answer: Use nested for statements.
Use one for statement to iterate over the rows, then another for loop to iterate over the row cells.
IMPORTANT NOTE:
Using loops to write single cells values is very slow. For recommendations please read https://developers.google.com/apps-script/guides/support/best-practices
Related
Hide Row in Google Sheets if Cell Contains "no" - Multiple Sheets
How to compare values of cells in if condition?
I'm new to google app script and not sure how to solve this issue.
I have two sheets, "Main" and "Extract". Throughout the day, data is pasted into the "Extract" sheet, cleaned up (script removes certain columns and removes rows where a value in column A also exist in column A of the "Main" sheet), and then added to the "Main" sheet, which contains all of the cleaned up extracts pulled throughout the day.
I am trying to write a script that will take all of the cleaned up data in the "Extract" sheet and cut and paste it beneath the last row with data in the "Main" sheet.
Once cleaned up the "Extract" sheet always has 8 columns (A-H), but the amount of rows varys each time. I do not need the header or column 8 (H) pasted to the "Main" sheet, only A2:G (stopping at the last row with data).
So far this is all I have been able to come up with (it is likely very wrong)
var data = sheet.getDataRange().getValues()
.offset(0, 0, 1);
I believe this is what you are trying to do.
var spread = SpreadsheetApp.getActiveSpreadsheet();
var sheet = spread.getSheetByName("Extract");
// skip row 1 (header) and beyond column G
var range = sheet.getRange(2,1,sheet.getLastRow()-1,7);
sheet = spread.getSheetByName("Main");
var rows = sheet.getRange(1,1,sheet.getLastRow(),1).getValues();
// search for first blank row column 1
for( var i=0; i<rows.length; i++ ) {
if( rows[i][0] === "" ) {
var offset = sheet.getRange(1,1).offset(i,0);
range.copyTo(offset);
break;
}
}
With the code that I have below I am trying to copy data over to a new sheet but I want it to always start with A2.
I don't want the data to constantly go to the end, I want it to always start in A2. Further more, where the issue comes in is I have formulas in B2:N200 so the data constantly tries to copy to the end.
Originally the code looked like this:
if(data[n][0]){
var dest = ss.getSheetByName(data[n][0].toString().replace(/ /g,''));//find the destination sheet
Logger.log(data[n][0].toString().replace(/ /g,''))
var destRange = dest.getRange(dest.getLastRow()+1,1);// define range
master.getRange(selectedfirstRow+n,2,1,1).copyTo(destRange);// and make copy below last row
}
}
And I realized that the Var destRange was defining where to start inputting the data.
if(data[n][0]){
var dest = ss.getSheetByName('Sunday'.replace(/ /g,''));//find the destination sheet
Logger.log(data[n][0].toString().replace(/ /g,''))
var destRange = dest.getRange(2+1,1);// define range
master.getRange(selectedfirstRow+n,2,1,1).copyTo(destRange);// and make copy below last row
}
}
As you can see I changed the getRange to (2+1,1); It does go to the next row each time I run the function but it only inputs one piece of data rather than consistenly going to the next.
EDIT
And I guess I should ask instead, how do I get the last empty cell in the first column only rather than the entire sheet. I know that the code currently is looking at the last row for the whole sheet, how do I get it to just find the first column?
Get only the first column of data, and then find the first empty element in the array.
Get a 2D array (Arrays inside of one outer array):
//Get the data from the first column only
columnOneData = dest.getRange(1,1,dest.getLastRow()).getValues();
That 2D array needs to be collapsed into an 1D array:
columnOneData = columnOneData.toString();//Convert the 2D array to a comma seperated string
columnOneData = columnOneData.split(",");//Convert the string to a 1D array
Find the first empty element in the new array:
firstRowWithEmptyCell = columnOneData.indexOf("") + 1;//Find the first empty element
Put together:
function test() {
var columnOneData,data,dest,destRange,firstRowWithEmptyCell,n,selectedfirstRow,ss;
ss = SpreadsheetApp.getActive();
if(data[n][0]){
dest = ss.getSheetByName('Sunday'.replace(/ /g,''));//find the destination sheet
//Logger.log(data[n][0].toString().replace(/ /g,''))
columnOneData = dest.getRange(1,1,dest.getLastRow()).getValues();//Get the data from the first column only
columnOneData = columnOneData.toString();//Convert the 2D array to a comma seperated string
columnOneData = columnOneData.split(",");//Convert the string to a 1D array
Logger.log('columnOneData: ' + columnOneData)
firstRowWithEmptyCell = columnOneData.indexOf("") + 1;//Find the first empty element
Logger.log('firstRowWithEmptyCell: ' + firstRowWithEmptyCell)
destRange = dest.getRange(2+1,1);// define range
master.getRange(selectedfirstRow+n,2,firstRowWithEmptyCell,1).copyTo(destRange);// and make copy below last row
}
}