parse data fetch from html - google-apps-script

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);

Related

Get Collection Of Cells With A Certain Value Google Sheets

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.

Split text from columns and then rewrite after processing

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

Automatically add variables to array?

In a google script I have written something to check my monthly expenses, which are listed in a google sheet.
Based on words the script finds, every line gets a category tag. It works fine, but the number of words to search for is getting big. And the array is getting big too.
I have listed 6 pairs (words to find, tag to add) - but in real version I have as many as 35. How can I create the pairs, and load everything automatically in the array?
This is my script:
function myFunction() {
// check usual suspects
var A1 = ["CAFE", "HORECA"]
var A2 = ["ALBERT", "AH"]
var A3 = ["VOMAR","Vomar"]
var A4 = ["HEMA","HEMA"]
var A5 = ["KRUID","Drogist"]
var A6 = ["RESTA", "Horeca"]
// in Array
var expenses = [A1,A2,A3,A4,A5,A6]
var ss = SpreadsheetApp.getActiveSheet();
var data = ss.getDataRange().getValues(); // read all data in the sheet
for (i in expenses)
{for(n=0;n<data.length;++n){ // iterate row by row and examine data in column A
if(data[n][3].toString().toUpperCase().match(expenses[i][0])==expenses[i][0]){ data[n][4] = expenses[i][1]};
// if column D contains 'xyz' then set value in index [5] (is column E)
}
Logger.log(data)
ss.getRange(1,1,data.length,data[0].length).setValues(data); // write back to the sheet
}
}
I can propose you that:
function multiPass(){
var searchCriterions = [
["CAFE","HORECA" ],
["ALBERT", "AH"],
["VOMAR","Vomar"],
["HEMA","HEMA"]
];
var dico = {};
var patt = "";
for (var i in searchCriterions) {
dico[searchCriterions[i][0]] = searchCriterions[i][1];
patt += "("+searchCriterions[i][0]+")";
if((Number(i)+1)<searchCriterions.length){
patt += "|";
}
}
var re = new RegExp(patt,"");
var ss = SpreadsheetApp.getActiveSheet();
var data = ss.getDataRange().getValues(); // read all data in the sheet
Logger.log(re);
for(n=0;n<data.length;++n){ // iterate row by row and examine data in column A
// THAT'S NOT COLUMN "A", 3 --> "D"
var test = data[n][3].toString().toUpperCase().match(re);
Logger.log(test);
if(test!==null){
data[n][4] = dico[test[0]]
};
}
ss.getRange(1,1,data.length,data[0].length).setValues(data); // write back to the sheet
}
instead of using variable for your "pairs" prefer to use a big table (it's less painfull to write)
then transform your pairs in object to quickly access the second argument of the pair and create a big regexp that check at once all the keywords instead of parsing them one by one.
Now as we are using a big array as search criterions we can totally imagine that this big array is loaded instead of hard coding it. If you have a sheet where the data is you can change the code this way:
var searchCriterions = SpreadsheetApp.getActive().getRange("namedRange").getValues();

Find string and get its column

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);

writing delimited text as a string to a spreadsheet

i have a short script where i'm trying to grab data from a URL and write it to a sheet of an existing spreadsheet. the script is as follows:
function urlDataImport() {
var input = "https://reports.acc-q-data.com/clientreports/ecaldwell_201206192722/ecaldwell_20122722.txt";
// The code below gets the HTML code.
var response = UrlFetchApp.fetch(input);
var data = response.getContentText();
Logger.log(data);
var ss = SpreadsheetApp.getActiveSpreadsheet();
var ptSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("pt");
ptSheet.getActiveRange().setValues(data);
}
the information in data is tab delimited and shows up properly in the log but because it's a string i can't use .setValues to write it to the sheet pt and i'm not sure how to get the information from the URL in any other way.
i'm sorry for the rudimentary nature of this question but i'm very new to scripting so any help would be appreciated.
Updated Code:
function ptDataImport() {
var input = "https://reports.acc-q-data.com/clientreports/ecaldwell_201206192722/ecaldwell_2012062.txt";
var response = UrlFetchApp.fetch(input); // Get the data from the URL as an object.
var data = response.getContentText(); // Convet the object to text
var dataSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("pt"); // Get the sheet to write the data to
var rows = data.split('\n'); // Splits the text into rows
dataSheet.clear();
var dataSet = new Array();
for ( var i in rows){
dataSet[i] = rows[i].split('\t'); // Split the rows into individual fields and add them to the 2d array
}
dataSet.pop(); // Had a blank row at the bottom that was giving me an error when trying to set the range - need to make this conditional somehow
var numColumns = dataSet[0].length;
var numRows = dataSet.length;
var lastRow = dataSet[(numRows -1)];
dataSheet.getRange(1,1,numRows,numColumns).setValues(dataSet); // Get a range the size of the data and set the values
}
#Serge, I think Evan's question was different. Evan is concerned that the split does not take rows into consideration.
The solution to that is to use two splits. First,
var rows = data.split('\n');
And then
for ( var i in rows){
tmp = rows[i].split('\t'); // Use Serge's method if this doesn't work
/* Get the range here */
range.setValues([tmp]);
}
Range.setValues() takes a 2-D array as input.
I'm not sure what you want to do. If all you want to do is write data into a cell, then use this piece of code
ptSheet.getActiveRange().setValues([[data]]);
If you want to write each of the elements in data to a row in a spreadsheet, then you can use
var tmp = data.split(DELIMITER);
/* Get the correct range here */
range.setValues([tmp]);
Notice how you are creating a 2-D array in the first case and in the second case.
I guess the easiest thing to do is to convert those tabs in something else, commas for example, that's after all where the 'c' of csv comes from... you can then write it wherever you want.
Exemple :
commaString = tabString.replace(\t/g,',') ; should work but I'm not an expert in regEx... if I'm wrong someone will for sure correct it ;-)