I want to split a text on spaces () and paste them in separate columns in sheet 2. I also want to remove "Hello" from the text before/after splitting the texts in columns. I was successful in using getValues.split(" "), but unsuccessful in pasting the new values in my destination range (in sheet2).
Input:
Output:
My current code:
function myFunction() {
var ss1 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1");
var lr = ss1.getLastRow();
var ss2 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet2");
for (var i = 2; i <= lr; i++) {
var title = ss1.getRange(i, 1).getValue().split(" ");
ss2.getRange(i, 2).setValue(title[0]);
}
}
Any help rendered would be highly appreciated.
Try the code below. It doesn't include your headings as I'm not sure what you'd like to do with that exactly. It does take care of stripping the "hello" word from your string and put every word in its separate column. Comments in the code explain why I'm doing stuff.
function myFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet(); // Selects the spreadsheet
var ss1 = ss.getSheetByName("Sheet1"); // Selects sheet 1
var data = ss1.getDataRange().getValues(); // Gets all values in the sheet
var ss2 = ss.getSheetByName("Sheet2"); // Selects sheet 2
for (var i=0;i<data.length;i++) {
var words = data[i][0].split(" "); // Create an array of all words
if (words[0].toLowerCase().indexOf('hello') > -1) { // True when the first word of the sentence contains hello
words.splice(0, 1); // Remove 1 item, starting from position 0 - remove the word that contains hello
}
// Get range on Sheet2, same row number as sheet 1, starting from column 1, select 1 row, and the same amount of columns as the amount of words
// Because we set values for a range that can span multiple rows, we put the words array in another array (where the words array represents one row)
// We add 1 to variable i as the index of an array starts at 0 instead of 1.
ss2.getRange(i+1, 1, 1, words.length).setValues([words])
}
}
Tested in this document
Related
I have a button that I want to click, which will scroll me to a certain position. I've done this in order to get me to row 100:
function ScrollMe(){
var file = SpreadsheetApp.getActiveSpreadsheet();
var sheet = file.getActiveSheet();
var row = 100;
file.setActiveCell(sheet.getRange(row,1));
}
What I want to do if a find a list of all cells that are in column 'B' that contain (REGEX=>"Version: [0-9]?[0-9]?[0-9][.]?[0-9]?[0-9]? [a-zA-Z]+"), and then go to the last value that this is like. So basically, go to the last cell in column 'B' that starts with "Version: " and then has a single, double, or triple-digit number, a decimal point, and then two numbers after, and then any amounts of letter text after the fact. I want it to look like this:
function ScrollMe(){
var file = SpreadsheetApp.getActiveSpreadsheet();
var sheet = file.getActiveSheet();
//C# lambda
var row = FindAll(a=> a.COLUMN == 'B' && a.VALUE.RegexMatch("Version: [0-9]?[0-9]?[0-9][.]?[0-9]?[0-9]? [a-zA-Z]+"));
file.setActiveCell(sheet.getRange(row,1));
}
I assume that you expect the script to find the last cell in the column B that match your regex. If that is the case, you can use this code:
function ScrollMe() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var data = sheet.getRange("B:B").getValues();
var regex = new RegExp(
'Version: [0-9]?[0-9]?[0-9][.]?[0-9]?[0-9]? [a-zA-Z]+');
for (var i = 0; i < data.length; i++) {
if (regex.test(data[i][0])) {
var lastMatch = i;
}
}
sheet.setActiveRange(sheet.getRange(lastMatch + 1, 2));
}
The previous code used your approach. It will first read the full column B, and after that will iterate to find the last cell that match the regex; and when it finds the cell, it will select it. Please, ask me if you have any doubts about the function.
I am trying to have the user input text like , 9188675309 in the input box and store that into searchstring variable.
Then it needs to scan the entire column of R which is formatted to look like (918) 867-5309
If the user puts in 5309 or 86753 can it also find the matches?
If any or all matches are found and then highlight the whole row,
function seekAndselect(){
var searchString = Browser.inputBox("Search For Phone Number?");
var sh = SpreadsheetApp.getActiveSpreadsheet();
var ss = sh.getActiveSheet();
var cell = ss.getActiveCell();
cell.setBackground('#ffff55');// replace by cell.setBackground(null); to reset the color when "leaving" the cell
var activeR = cell.getRow()-1;
var activeC = cell.getColumn()-1;
var data = ss.getDataRange().getValues();
var step = 0
for(var r=0;r<data.length;++r){
for(var c=0;c<data[0].length;++c){
step++
Logger.log(step+' -- '+searchString+' = '+data[r][c]);
if(data[r][c]==''||step==1){ continue };
if(searchString.toString().toLowerCase()==data[r][c].toString().toLowerCase()){
ss.setActiveSelection(r+1,c+1);
return;
}
}
}
}
Will there be more than one match? It was a bit unclear. If there could be more than one match, then loop through the R column and match() the input/values. This way also allows for partial matches.
function seekAndselect(){
var sh = SpreadsheetApp.getActiveSpreadsheet();
var ss = sh.getActiveSheet();
// User input
var searchString = Browser.inputBox("Search For Phone Number?");
// Remove non numbers
var clean_search = searchString.replace(/[^0-9]/g, "");
// Get the R column values
var r_col = ss.getRange(1, 18, ss.getLastRow()).getValues();
// Search each row in col R for a match and highlight the row
r_col.forEach(function (e, i) {
// Remove non numbers from data before matching
if (e[0].replace(/[^0-9]/g, "").match(clean_search)) {
var found_range = ss.getRange((i + 1), 1, 1, ss.getLastColumn())
// Highlights the row from col A to R
found_range.setBackground('#ffff55')
// Sets the active selection to the last matched row from col A to R
ss.setActiveSelection(found_range)
}
});
}
I wasnt sure what you wanted with the setActiveSelection(), if there are multiple matches it will only select the last one. Also, if there are a lot of matches, this could take a long time to run, possibly even time-out. If that happens, a batchUpdate() would be needed
I want to merge several sheets into 1 spreadsheeet and want to paste all data below each other.
My current code looks like that:
function updateMaster() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var allSheets = ss.getSheets();
var repArray = new Array();
// build array of all sheets
for (i in allSheets) {
repArray.push(allSheets[i].getName());
}
// store all sheets in array
var sheetArray = [];
// loop through all rep sheets
for (var j in allSheets) {
// 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("Master");
// clear the whole sheet
mSheet.clear({contentsOnly:true});
// write to the Master sheet via the array
mSheet.getRange(1, 1, sheetArray.length, 4).setValues(sheetArray); //I GET THE ERROR BECAUSE OF THIS LINE
// 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);}
}
However, I get an error, because other sheets have not the same column length.
The error message:
Incorrect range width, was 5 but should be 4
Here I get the error:
mSheet.getRange(1, 1, sheetArray.length, 4).setValues(sheetArray);
I basically, just want to post the data below. Any recommendation how I could make the column length variable?
Here is a link to my spreadsheet:
https://docs.google.com/spreadsheets/d/1TuHaqs20PvNwOJ46bQOAwN3Nt5vyRl7Win1Lul4m-e8/edit?usp=sharing
I appreciate your replies!
The sheetArray array has inner row elements of different lengths. Some inner arrays have 4 elements, some have 5 elements. You can't set values from an array with different inner element lengths. If you change the column width to 5, the error states that it should be 4, if you change it to 4, it says that it should be 5. You need to either add an extra empty element to the range with 4 columns, or write each sheet to the master individually.
Get one of the inner arrays, and find the length of an inner array. That is your column length.
On this line:
var dataRange = tempSheet.getDataRange().getValues();
You are using the getDataRange() method. That causes the range to be different dimensions for each sheet that has a different number of columns. If you set the column width to the biggest number of columns in the sheet with the most columns, then all your inner elements would be the same length. Your code would write a lot of empty cells. But don't know if there is any downside to that .
var columsToWriteTo = sheetArray[0].length
mSheet.getRange(1, 1, sheetArray.length, columsToWriteTo).setValues(sheetArray);
The above code gets the first inner array of the two dimensional sheetArray, and gets the length of the inner array.
The other answer pointed the issue but did not provide a solution.
What you should simply do is to make the final array homogeneous before setting its value with setValues().
Below is a code demo that does it by adding empty items in rows that are too short. I added comments in code to explain
function ArrayNormalize() {
var sh = SpreadsheetApp.getActive();
var data1 = sh.getSheets()[0].getDataRange().getValues(); // get data from sheet1
var data2 = sh.getSheets()[1].getDataRange().getValues();// same from sheet2 that has a different width
var combine = data1.concat(data2);
Logger.log("combine = "+JSON.stringify(combine));
//get Max array width
var maxWidth=0
for(var n=0;n<combine.length;n++){
Logger.log(n+' - '+combine[n]+" length = "+combine[n].length);
if(combine[n].length>=maxWidth){maxWidth=combine[n].length};
}
Logger.log("maxWidth = "+maxWidth);
//normalize
for(var n=0;n<combine.length;n++){
while(combine[n].length<maxWidth){
combine[n].push('');// while row is shorter add empty "cells" (=array elements)
}
}
sh.insertSheet().getRange(1,1,combine.length,combine[0].length).setValues(combine);// insert the result in new sheet to check the result but you can insert it anywhere else of course
}
Let's say I have a lot of columns and one of them contains "impressions" string (on row 3). What I need to do is to:
1) Find the cell with "impressions" string
2) Get column number or i.e. "D"
3) Based on what I got paste a formula into i.e. D2 cell which gets AVERAGE from a range D4:D*last*
I couldn't find it anywhere so I have to ask here without any "sample" code, since I have no idea on how to achieve what I want. (3rd one is easy but I need to get that "D" first)
There's no way to search in Google Apps Script. Below is a function that will accomplish the first 2 parts for you (by iterating over every cell in row 3 and looking for "impressions"):
function findColumnNumber() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Sheet1'); // insert name of sheet here
var range = sheet.getDataRange(); // get the range representing the whole sheet
var width = range.getWidth();
// search every cell in row 3 from A3 to the last column
for (var i = 1; i <= width; i++) {
var data = range.getCell(3,i)
if (data == "impressions") {
return(i); // return the column number if we find it
}
}
return(-1); // return -1 if it doesn't exist
}
Hopefully this will allow you to accomplish what you need to do!
The indexOf method allows one to search for strings:
function findColumnNumber() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet() //whatever tab the code is run on
var data = sheet.getDataRange().getValues();
var header_row_num = 1; // TODO: change this to whichever row has the headers.
var header = data[header_row_num -1] //Remember JavaScript, like most programming languages starts counting (is indexed) at 0. For the value of header_row_num to work with a zero-index counting language like JavaScript, you need to subtract 1
//define the string you want to search for
var searchString = "impressions";
//find that string in the header and add 1 (since indexes start at zero)
var colNum = header.indexOf(searchString) + 1;
return(colNum);
I'm trying to get some data from the federal reserve and paste into my spreadsheet.
So here is my code
function myFunction() {
var response = UrlFetchApp.fetch("http://research.stlouisfed.org/fred2/data/TWEXMANL.txt");
a=response.getContentText();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var InputSheet = ss.getSheetByName("Sheet5");
InputSheet.getRange("E5:E5").setValue(a);
}
This code pastes all of the output into E5. I just want the data following the "Date" and "Value" pasted into 2 columns.
Can anybody help me with this? I'm sure it's pretty simple for you guys.
Thanks.
Using a little string manipulation, this becomes very easy:
function myFunction() {
var response = UrlFetchApp.fetch("http://research.stlouisfed.org/fred2/data/TWEXMANL.txt");
a=response.getContentText();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var InputSheet = ss.getSheetByName("Sheet1");
//Slice off the text above the columns
var allData = a.slice(a.indexOf("DATE VALUE"));
//Trim spaces between date and value to just 1 space for splitting
allData = allData.replace(/ +/g, " ");
//Split the text so each line is a row
var splitData = allData.split("\n");
//For some reason, there is an extra line, so remove it
splitData.pop();
//Split each row so data is one column and value is another
for(var i = 0; i < splitData.length; i += 1) {
splitData[i] = splitData[i].split(" ");
}
//Save to spreadsheet. +4 because you start at E5. Note the change to F on the right.
InputSheet.getRange("E5:F" + (splitData.length + 4)).setValues(splitData);
}
I start by taking off the little intro text. I then split the string into an array containing the rows of data. I split each row (a string) into an array as well. This gives me a array I can use setValues() on at the bottom. Because this isn't just one cell, I have to specific the exact width and height or it fails.
If you'd like to see the data at any point in there, I recommend Logger.log(splitData);