I don't manage to parse JSON in google app script - json

I'm trying to grab song lyrics from the orion.apiseeds lyrics API - it works and I get a JSON, that I'm incapable of parsing.
https://orion.apiseeds.com/api/music/lyric/Oasis/Wonderwall?apikey=xx
gives back
{"result":{"artist":{"name":"Oasis"},"track":{"name":"Wonderwall","text":"Today is gonna be the day that they're gonna throw it back to you.\r\nBy now you should've somehow realized what you gotta do.\r\nI don't believe that anybody, feels the way I do, about you now.\r\n\r\nBackbeat, the word is on the street that the fire in your heart is out.\r\nI'm sure you've heard it all before but you never really had a doubt.\r\nI don't believe that anybody, feels the way I do, about you now.\r\n\r\nAnd all the roads we have to walk are winding.\r\nAnd all the lights that lead us there are blinding.\r\nThere are many things that I, would like to say to you but I don't know how.\r\n\r\nBecause maybe, you're gonna be the one that saves me?\r\nAnd after all, you're my wonderwall.\r\n\r\nToday was gonna be the day but they'll never throw it back to you.\r\nBy now you should've somehow realized what you're not to do.\r\nI don't believe that anybody, feels the way I do, about you now.\r\n\r\nAnd all the roads that lead you there were winding.\r\nAnd all the lights that light the way are blinding.\r\nThere are many things that I, would like to say to you but I don't know how.\r\n\r\nI said maybe, you're gonna be the one that saves me?\r\nAnd after all, you're my wonderwall.\r\n\r\nI said maybe, (I said maybe)\r\nYou're gonna be the one that saves me?\r\nAnd after all, you're my wonderwall.\r\n\r\nI said maybe, (I said maybe)\r\nYou're gonna be the one that saves me? (that saves me)\r\nYou're gonna be the one that saves me? (that saves me)\r\nYou're gonna be the one that saves me? (that saves me)","lang":{"code":"en","name":"English"}},"copyright":{"notice":"Wonderwall lyrics are property and copyright of their owners. Commercial use is not allowed.","artist":"Copyright Oasis","text":"All lyrics provided for educational purposes and personal use only."},"probability":100,"similarity":1}}
My code to fetch this is:
function getLyrics(url) {
var response = UrlFetchApp.fetch(url);
var responseObject = JSON.parse(response.getContentText());
}
Then, that's where the problem arises.
1)
Logger.log(reponseObject); ==> gives the thing I pasted above.
2)
for (var i=0;i<responseObject.length;i++) {
var item = responseObject[i];
Logger.log(JSON.stringify(item));
==> gives NOTHING in the console...
3)
function printJson(myObject) {
// define an array of all the object keys
var headerRow = Object.keys(myObject);
// define an array of all the object values
var row = headerRow.map(function(key){ return myObject[key]});
// define the contents of the range
var contents = [
headerRow,
row
];
// select the range and set its values
var ss = SpreadsheetApp.getActive();
var rng = ss.getActiveSheet().getRange(1, 1, contents.length, headerRow.length )
rng.setValues(contents)
}
===> fills one row with "result" and the next row with all the rest of the JSON.
I feel like i'm missing a basic JSON-related thing...
Thanks for your help

var responseObject = JSON.parse(response.getContentText());
var lyrics = responseObject.result.track.text;
That was easy enough ;-)

Related

Trying to pull a word out of a string, in google script, on google sheets. Not familiar with the language, cant make the functions work

I'm a vanilla C guy, and just having trouble wrapping my head around google script, in a google sheets project. I want to copy/paste a blob of text into cell(1, 1), press a button, then pull data out of that string and turn it into a pretty table. Just having trouble parsing the string...
My thought is to search for the word "DUG", then give me the word after it.
The format of the blob is:
garbage garbage DUG Username garbage garbage DUG Usernumber garbage garbage DUG Username garbage garbage DUG Usernumber (etc etc).
The problem: I can locate the first instance of the word DUG, but I can't seem to chop the string at that location. I've heard to use left(), right(), or mid(), but it's saying those functions don't exist. It seems like I'm missing something easy. Any tips for a noob?
Thank you so much!
// function runs when button is clicked
function SortCustomerList() {
var spreadsheet = SpreadsheetApp.getActiveSheet();
var sheetName = spreadsheet.getName();
var pastedDataRange = spreadsheet.getRange(1, 1); // location of the pasted data
var pastedData = pastedDataRange.getValue(); // get the data from that cell
var pastedText = pastedData.toString(); // convert that data into a string
// returns an index location of where "DUG" starts in the string
var foundLoc = pastedText.indexOf("DUG");
// show me that location for testing (number. int?) ***works!!***
spreadsheet.getRange(4, 1).activate();
spreadsheet.getCurrentCell().setValue(foundLoc);
// i want to chop the string at "DUG", show me everything to the right, starting where you found "DUG"
// ****doesnt work. returns the entire paste, not chopped
spreadsheet.getRange(10, 1).activate();
spreadsheet.getCurrentCell().setValue(pastedText.split(foundLoc));
// future: rather than the rest of the string, just give me the word after "DUG"
// set index (foundLoc) to AFTER the "DUG Username", to find the next instance of "DUG"
// loop it, until there are no more instances of the word "DUG"
// put it into pretty rows and columns
spreadsheet.getRange(5, 1).activate();
spreadsheet.getCurrentCell().setValue('Test Ran!');
};
it looks like the tool i needed is substring(). just replace split() with substring() and it "just works". thank you to the friend who helped, and thank you all for the help ive looked up over the years. cheers!

Scanning range and paste copied information if a certain cell is empty

i'm still a beginner in this, so I might ask a lot of stupid questions.
My problem is the following:
I wrote this script:
function ThisTry() {
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var Ssheet = sheet.getSheetByName("Recap");
var nSheet = sheet.getSheetByName("Aktuell");
var rang1 = sheet.getRange("Aktuell!A1:Q28");
var colum = 1;
var columEnd = 20;
var ro = 85;
var roEnd = 112;
var clean = nSheet.getRange(29, 20);
var ad = clean.getValue();
if (ad == "", ro+=28, false);
if (ad == "", roEnd+=28, false);
var past = rang1.copyValuesToRange(Ssheet, colum, columEnd, ro, roEnd);
}
What I am doing is I copy some information from one sheet and paste it in another. But i want to create a code that watches if a certain cell is empty or not and if it is not I want to change the values of the variables that I use to define the range in copyValuesToRange in the code above.
This code currently works but it doesn't save the new values of the variables, so it does what it should the first time but after that it doesn't change the range
I know that my if statements are wrong but I have no idea how to fix them so that the code works.
Any suggestions? Thanks!
If someone is editing the contents of clean' you can check the value after an onEdit trigger event to see if the current value is different from the past value. You can maintain state between function calls by storing information in PropertiesService. I also like just storing stuff in files as ascii text because you can store so much stuff all in one place and if need be you can edit it with something like Drive Notepad. If your interested in that then spend some time learning about Drive.
If you wish to poll that value, then you could run code from a sidebar or dialog using Javascript timer functions and you can call any server side with google.script.run. In addition, that's a way to build sort of a control panel to watch the process from.
I don't know exactly what your trying to accomplish but I hope that I've given you some useful things to consider.

Google Docs: sending email with variable content from the spreadsheet

i want to send emails that contains text and variable values from the spreadsheet.
For that i ran the sendemails-script which works well. But at the example the cell that was declared as "var message" didnt contain variable values but only text.
Is it possible to add "references to values" to this text?
Something like:
Hello,
last week you bought (value of B3) apples and (value of B4) cherries.
I think in Excel you can split text and formular units in one row, is there something like that in GoogleDocs?
Thanks for your help in Advance, i hope you could understand what i mean :)
Marten
Amit's suggestion is a good idea although it might be a bit complex if you want to keep the whole thing simple and/or adapt it to your needs... It's never easy to analyse a script that is the result of a lot of work... from someone else.
So I wrote a very simple script that does exactly what you ask, nothing more (and nothing less I hope)
It uses 3 columns and the base message has 3 placeholders but you can of course expand it the way you want.
It will be easy to customize it to your use case. I added many log in the code so you see exactly what is going on.
function simpleMerge(){
var sh = SpreadsheetApp.getActiveSheet();
var data = sh.getDataRange().getValues();
var headers = data.shift();
for(var n=0 ; n<data.length ; n++){
var baseMessage = "Hello #0#, \n\nlast week you bought #1# apples and #2# cherries.";
for(var c=0 ; c<data[n].length ; c++){
var placeHolder = '#'+c+'#';
var value = data[n][c];
Logger.log('replacing '+placeHolder+' with '+value);
baseMessage = baseMessage.replace(placeHolder,value);
}
Logger.log('message '+n+' = '+baseMessage);
//send message to who you want
}
}
Install the ultradox or mailchimp add-on or many others that do this with more flexibility.

Google Apps script:Trying to open each doc in a folder, extract its TOC and write it to another doc

First, thanks to Serge insas for enough help to even write this script!
The script runs, but doesn't give me anything like the desired result.
What I want to do is
(1) Create a new document in a given folder(Let's call it 'myfolder') and write a title for it.
That works--sort of. I get a document, but it's icon is a tiny image for a doc file but with its corner turned over. It only opens in the viewer. It does have the title, but nothing that I tried to write to it subsequently.
(2) Get an array of all the files in 'myfolder'. That's where the Serge's help came in. They need to be converted into readable documents. I THINK that worked (More on this later). At least the debugger did not throw an error. I ended up with a 'contents' array.
(3) For each of those documents, get the file name and extract the Table of Contents. Append each of those to the doc created in (1). To do this, I used a for loop which iterated from one to contents.length. Now the FIRST problem arose. Whatever contents.length brought back wasn't right because the next loop, where the processing occurred errored out at approximately the number of documents, not counting these little half-docs the script generated. I got around this by a try-catch construction that stopped when it hit an undefined file. That and the execution transcript suggested that the script did go through that loop.
So here's the BIG problem. Whatever those little half-docs were, nothing other than the first introductory line was written to them.
The debugger is useless.
(a) It doesn't show me the log file. Just a date.
(b) If I place a breakpoint, it MAY stop at it, but I see mostly a list of objects. If I click on the + sign, I get a list of methods. A few of the non-object variables are shown. It's impossible to step through the code because it can take up to three minutes to go from one line to the next, so it's been rather tough to debug this.
The only info I could garner was that the execution transcript did suggest that I did get doc objects from the files.
I think the problem is with a*doc = DocumentApp.openById(docObject[jj]);* which is in bold in the code below.
Sorry for the strange error handling; I was trying to get some insight into what was wrong. Alas, the debugger tells me that Err is an string and gives me no value.
Whether the rest of the code works or not, I can't tell if it does, indeed error out the first time it hits the bolded line.
Thanks for your patience.
function listDocTOCsInFolder()
{
// Thanks to crucial help from Serge insas via Stack Overflow.
var afolder; // Folder you want to work on
var contents; // Files in the folder
var TOCListDoc; // Document you will create to hold your TOC List
var docObject = []; // Holds a list of documents created from contents
var aname;
var adoc;
var err = "";
var isErr = false;
TOCListDoc = DocsList.createFile("TOCList", "Document TOC List");
afolder = DocsList.getFolderById("0B-UcimyrHLl2bm1OanExaHotc2M")
//Can't figure out what exactly constitutes the path of a folder.
TOCListDoc.addToFolder(afolder);
// Get all the document files in your named folder. Unfortunately,they are not document objects
var contents = afolder.getFilesByType(DocsList.FileType.DOCUMENT);
// This loop gives you an array of DocumentApp objects.
for (var ii = 0; ii < contents.length; ii++)
{
docObject.push(DocumentApp.openById(contents[ii].getId()));
}
// Now you can do a for loop to gather up the contents into one document.
Logger.log(contents.length);
// It isn't clear what this actually gets, because unless I set a trap of
// undefined documents, the loop keeps right on going.
var len = docObject.length;
var jj = 0;
for(jj = 0; jj < len; II++ )
{
try
{
**adoc = DocumentApp.openById(docObject[jj]);**
}
catch(err)
{
isErr = true;
}
if(!isErr)
{
// Get the information you want to write to your list doc
var TOC = adoc.getAs(DocumentApp.ElementType.TABLE_OF_CONTENTS);
logger.log(TOC);
aname = adoc.getName();
Logger.log(aname);
body.appendParagraph(counter, name);
body.appendParagraph(TOC);
//.setHeading(DocumentApp.ParagraphHeading.HEADING1);
}
else
{
Logger.log("Errored out");
}
}
}
when you say
"For each of those documents, get the file name and extract the Table
of Contents. Append each of those to the doc created in (1)
that's indeed what you should do... you used this code :
// Get the information you want to write to your list doc
var TOC = adoc.getAs(DocumentApp.ElementType.TABLE_OF_CONTENTS);
logger.log(TOC);
but doing this you assume that the first element in this document is necessarily the TOC and I'm not sure you can do that !!
What I I would try is to iterate through all the document's elements and check the type of each element, then copy the one that is a TOC to your new document.
See eventually this post to check how you could iterate into the document's elements and check their types, the purpose of this script was different but I guess the approach should help you.
Good luck
instead of
for(jj = 0; jj < len; II++ ) try for(jj = 0; jj < len; jj++ ) instead
and: read again the troubleshooting guide...

Cannot find method open()

Cannot find method open().
If it can't find it, why does it let me choose it when I type the dot?
So how am I supposed to open a file? openByID()? Really? Where do I get this magical ID? From getURL? Seriously? This is the only thing that comes up:
SpreadsheetApp.openById(id).getUrl()
but I fail to understand how I'm supposed to get the URL if I don't have an ID to hang it on... leading to a catch 22. Further, I presume in the event I do get the URL I still need to parse it to get the ID... and what magical method have they supplied for that particular incantation?
Clearly, my understanding is lacking. Any help?
function copyTemplate() {
var targetSpreadsheetName="The file";
var targetSpreadsheetID=SpreadsheetApp.open(targetSpreadsheetName).getId();
targetSpreadsheetID.insertSheet("CellData", 1, {template:temp});
// The code below will duplicate the sheet named "CellData" and insert it after
// the 1st sheet and call it "CellData"
var ss = SpreadsheetApp.getActiveSpreadsheet();
var temp = ss.getSheetByName("CellData");
ss.insertSheet("CellData", 1, {template:temp});
}
The question is multi-part.
The error message returned was "Cannot find method open()."
The first question is "Why can't it find method open()?".
The second question is "If in fact, it can't find it, why does it let me choose it when I type the dot?"
The third question is "Considering the fact that the open() method fails to work, how am I supposed to open a file?" The presumed answer I expect to receive from the community is "with openByID()".
That leads to the fourth question which is "Where do I get the ID?". The apparent answer seems to be "getURL()".
And that leads to the fifth question which is "How do I use getURL()?" getURL seems to require an ID. If getURL requires an ID to get the URL, and openByID requires a URL to get the ID, you have an infinite loop. Surely I'm misunderstanding something.
The sixth question is "In the event getURL() ends up being part of the solution, how does one distinguish the ID from the rest of the string returned?"
I hope that clarifies my question.
Well I'll finally try to answer your question, hoping you'll find it clear enough... ;-)
First thing first :
var ss = SpreadsheetApp.open()
does indeed appear in the autocomplete after the dot, what you didn't pay attention to is that the argument is a file, ie an object returned by an appropriate statement.
Now let's see how to get it and , with this example how the other parameters of this file can be obtained :
function myFunction() {
var files = DocsList.find('thisisthesheetIwant');// this is an array of file objects that include the term 'thisisthesheetIwant'
var file = files[0];// I take the first one
var filename = file.getName();//and get its name
var fileId = file.getId();// its ID
var fileurl = file.getUrl();//and its url
// then I show the results in the logger
Logger.log('number of file found = '+files.length+'\n\n'+filename+'\n\n'+fileId+'\n\n'+fileurl+'\n\n')
var ss = SpreadsheetApp.open(file);// using that file object I can open a spreadsheet
var content = ss.getSheets()[0].getDataRange().getValues().toString();// and get the whole content of the first sheet
Logger.log('content = '+content);// there it is
}
The spreadsheet with its code is available here so you can test it by yourself, I named it thisisthesheetIwant hoping you don't have any file with a similar name or content since it wouldn't work as I expected if more than 1 file was returned.
Look at the logger and I hope it will answer your question(s).
it should appear like this below :
And the sheet itself is like this :
EDIT : note that the ID and the URL have a common part, the url is what you can see in your Browser's adress bar, the ID is just a part of it.
Now you can open the same spreadsheet with
SpreadsheetApp.openById(fileId)