Google sheets API script - rest

I'm trying to use the following REST API within one of my sheets, and am struggling to return a specific result from the JSON array (first timer here!!)
Here's what I have so far....
function Bittrex_API() {
// Call the Bittrex API for market rates
var response = UrlFetchApp.fetch(
"https://bittrex.com/api/v1.1/public/getmarketsummaries");
// Parse the JSON reply
var json = response.getContentText();
var data = JSON.parse(json);
Logger.log(data);
}
This returns the full array in the Logs, but how do I get it to pull all information from a specific result in the array?
I can return specific results from the first section, by calling the index position "0" as follows:
function Bittrex_API() {
// Call the Bittrex API for market rates
var response = UrlFetchApp.fetch(
"https://bittrex.com/api/v1.1/public/getmarketsummaries");
// Parse the JSON reply
var json = response.getContentText();
var data = JSON.parse(json);
Logger.log(data["result"][0]);
}
But how do I specify a different section of the array without using the index number??
i.e. I want to return all information relating to MarketName=BTC-RCN.

There is nothing wrong with using the index nunber. Whatever notation you use you will need to find BTC-RCN. You can loop through the index number to find it. This will find it and return the results to Sheet1:
function Bittrex_API() {
// Call the Bittrex API for market rates
var response = UrlFetchApp.fetch(
"https://bittrex.com/api/v1.1/public/getmarketsummaries");
// Parse the JSON reply
var json = response.getContentText();
var data = JSON.parse(json);
var lgt=data.result.length
for(i=0;i<lgt;i++){
var test=data["result"][i]["MarketName"]
if(test=="BTC-RCN"){
var num=i;
}
}
var MarketName=data["result"][num]["MarketName"]
var High=data["result"][num]["High"]
var Low=data["result"][num]["Low"]
var Volume=data["result"][num]["Volume"]
var Last=data["result"][num]["Last"]
var BaseVolume=data["result"][num]["BaseVolume"]
var TimeStamp=data["result"][num]["TimeStamp"]
var Bid=data["result"][num]["Bid"]
var Ask=data["result"][num]["Ask"]
var OpenBuyOrders=data["result"][num]["OpenBuyOrders"]
var OpenSellOrders=data["result"][num]["OpenSellOrders"]
var PrevDay=data["result"][num]["PrevDay"]
var Created=data["result"][num]["Created"]
var ss=SpreadsheetApp.getActiveSpreadsheet()
var s=ss.getSheetByName("Sheet1")
s.getRange("A1").setValue("MarketName")
s.getRange("B1").setValue(MarketName)
s.getRange("A2").setValue("High")
s.getRange("B2").setValue(High)
s.getRange("A3").setValue("Low")
s.getRange("B3").setValue(Low)
s.getRange("A4").setValue("Volume")
s.getRange("B4").setValue(Volume)
s.getRange("A5").setValue("Last")
s.getRange("B5").setValue(Last)
s.getRange("A6").setValue("BaseVolume")
s.getRange("B6").setValue(BaseVolume)
s.getRange("A7").setValue("TimeStamp")
s.getRange("B7").setValue(TimeStamp)
s.getRange("A8").setValue("Bid")
s.getRange("B8").setValue(Bid)
s.getRange("A9").setValue("Ask")
s.getRange("B9").setValue(Ask)
s.getRange("A10").setValue("OpenBuyOrders")
s.getRange("B10").setValue(OpenBuyOrders)
s.getRange("A11").setValue("OpenSellOrders")
s.getRange("B11").setValue( OpenSellOrders)
s.getRange("A12").setValue("PrevDay")
s.getRange("B12").setValue(PrevDay)
s.getRange("A13").setValue("Created")
s.getRange("B13").setValue(Created)
}

Related

Google Script to Send Email containing values from Sheet

I am trying to get a script working that hooks into a google sheet, pulls information that is taken of the phone, and sends it via email once marked. So far I have this, from sources on the internet and a bit of customising.
function sendApprovalEmail() {
var sheetNameToWatch = "SHEETNAMEGOESHEREUSUALLY";
var columnNumberToWatch = 12; // column A = 1, B = 2, etc.
var valueToWatch = "SENT";
var date = 5;
var name = 9;
var number = 10;
var message = 11;
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getActiveCell();
if (sheet.getName() == sheetNameToWatch && range.getColumn() == columnNumberToWatch && range.getValue() == valueToWatch) {
var emailAddress = "MYEMAILGOESHEREUSUALLY";
var subject = "Missed Call Notifcation";
var email = "Hello! "+date+" "+name+" "+number+" "+message+"";
MailApp.sendEmail(emailAddress, subject, email);
}
}
The above works, triggers, and sends properly. The only thing it doesn't do is suck in the Date, Name, Number and Message.
These need to be unique for each email, based on the line that was just marked as SENT. Usually, there are only a couple a day, never at the same time.
So if Row 23 is marked as SENT, it needs A23, B23, and C23.
If row 66 is marked as SENT, it needs A66, B66, and C66.
How do I get the script to look up values in column 5, 9, 10 and 11 OF THE ROW that it has detected 'SENT' in?
The code is using var range = sheet.getActiveCell() the get the active cell. Then you could use range.getRow() to get the row number, then you could use something like sheet.getRange(range.getRow(), columnNumber) to get the desired cells where columnNumber could be 5, 9, 10 and/or 11. In other words, instead of
var date = 5;
use
var date = sheet.getRange(range.getRow(), 5).getValue();
but put the above line after
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getActiveCell();
Do the same for the name, number and message variables.
Note: There are other more efficient ways like using sheet.getDataRange().getValues() which will return an array of arrays having all the sheet values, the use
var date = data[range.getRow()][5];
and so on.
This is probably close to what your looking for:
First you have to settle on a format for your spreadsheet so that all operators will record the information in a standard format. I used the following format for each of my sheets.
All of the sheets used for recording information start with the prefix of 'ph:'. I get the entire array of sheets and I loop through them looking for the sheets that begin in 'ph:' name.slice(0,3). Once found I get the range of A1:B6 and collect all of the data into one array and then loop through the array putting all of the information into an associative array using the following algorithm dObj[value in column1]=value in column2. So in my example you can get the name with dObj.Name and the message is obtained by using dObj.Message and so on. So this associates the key in column one with the value in column2.
Now here is the code:
function sendApprovalEmails(){
var ss=SpreadsheetApp.getActive();
var shts=ss.getSheets();
for(var i=0;i<shts.length;i++){
var sh=shts[i];
var name=sh.getName();
if(name.slice(0,3)=='ph:'){//finds the operator log sheets
var dObj={};
var rg=sh.getRange('A1:B6');//Use a fixed range so you can use the rest of the sheet for whatever
var vA=rg.getValues();
for(var j=0;j<vA.length;j++){
dObj[vA[j][0]]=vA[j][1];//Builds the associative array
}
if(dObj.Approval=='Yes'){
Logger.log('Send Email:\nDate: %s\nNumber: %s\nName: %s\nMessage: %s,To: %s',Utilities.formatDate(new Date(dObj.Date),Session.getScriptTimeZone(),"E MMM dd, yyyy"),dObj.Number,dObj.Name,dObj.Message,dObj.Email);
var recipient=dObj.email;
var subject="Missed Call Notification";
var body = Utilities.formatString('Hello! %s %s %s %s',Utilities.formatDate(new Date(dObj.Date),Session.getScriptTimeZone(),"E MMM dd, yyyy"),dObj.Name,dObj.Number,dObj.Message);
//MailApp.sendEmail(recipient, subject, body);
}
}
}
}
In my example B1 has a data validation of either Yes or No.
Of course this is probably just a starting point. You can create the code to copy a master sheet and open it up with each phone call. I don't know if there is a limit to the number of sheets but there is a a limit to the number of cells in one Spreadsheet.
Documentation Reference:
By the way this version of your code works.
function sendApprovalEmail() {
var sheetNameToWatch = "test";
var columnNumberToWatch = 1;
var valueToWatch = "SENT";
var date = 5;
var name = 9;
var number = 10;
var message = 11;
var ss = SpreadsheetApp.getActive();
var sheet = ss.getActiveSheet();
var range = sheet.getActiveCell();
if (sheet.getName()==sheetNameToWatch && range.getColumn()==columnNumberToWatch && range.getValue() == valueToWatch) {
var emailAddress = "foundit#found.com";
var subject = "Missed Call Notifcation";
var email = Utilities.formatString('Hello! %s %s %s %s',date,name,number,message);
//MailApp.sendEmail(emailAddress, subject, email);
Logger.log('\nemailAddress: %s\nsubject: %s\nemail: %s',emailAddress,subject,email);
}
}
I don't like to send out a lot of useless emails while debugging so I just use the Logger to record the email information.

Generic Type array with UITableView and Realm

I am using realm for database. I have Favourite Object and History Object.
I want to show in TableViewController. However, I don't want to do duplicated code. For now, in FavouriteViewController , it has var favs: Results<OGFav>? and HistoryViewController, it has var history: Results<OGHistory>?
Most of the code are the same and different is data type.
Example: it only different like following
if let object:OGFav = self.favs?[indexPath.row] {
In some place , I use like
let fav:OGFav = favs[indexPath.row]
For History
if let object:OGHistory = self.history?[indexPath.row] {
History also use like below
let history:OGHistory = self.history[indexPath.row]
How can I clean the code ? I am using two viewcontroller and code are the same excepted OGFav and OGHistory.
Update:
OGFav and OGHistory have the same data.
class OGFav: Object {
dynamic var word = ""
dynamic var def = ""
}
class OGHistory: Object {
dynamic var word = ""
dynamic var def = ""
dynamic var updatedAt = NSDate()
}

How to get unique value from Realm database in swift

I do news application in swift using Realm database. In my database have same news categories. How to get unique value from Realm database?
I use primary key
class News: Object {
dynamic var newsID: String = ""
dynamic var newsTitle: String = ""
dynamic var newsFullText: String = ""
dynamic var newsImage: String = ""
dynamic var newsAutor: String = ""
dynamic var newsCommentCount: String = ""
dynamic var newsSeenCount: String = ""
dynamic var newsDate: String = ""
dynamic var newsCategory: String = ""
override static func primaryKey() -> String? {
return "newsID"
}
}
I'm try to get
let realm = try! Realm()
let menuName = realm.objects(News)
for i in menuName.filter("newsCategory") {
nameLabel.text = i.newsCategory
}
But it is not work.
Starting from Realm 3.10 it's now possible to
Add Results.distinct(by:) / -[RLMResults
distinctResultsUsingKeyPaths:], which return a Results containing only
objects with unique values at the given key paths.
Old response - before Realm 3.10
It is not possible yet to obtain a "distinct"-like functonality from a Realm query (track the open issue here)
However, there are some workarounds suggested in the thread I mentioned above (please read it to get the full context), by user apocolipse :
// Query all users
let allUsers = Realm().objects(User)
// Map out the user types
let allTypes = map(allUsers) { $0.type }
// Fun part: start with empty array [], add in element to reduced array if its not already in, else add empty array
let distinctTypes = reduce(allTypes, []) { $0 + (!contains($0, $1) ? [$1] : [] )
Or better yet, a different approach using Sets (by user jpsim):
let distinctTypes = Set(Realm().objects(User).valueForKey("type") as! [String])
Obviously the workarounds aren't as efficient as a direct DB query, so use with care (and testing under realistic load).

Dynamic Struct creation in Swift - based on user input

I am trying to create dynamic struct in swift based on user input.
struct Diagnosis {
var diagName = String() // Name of the diagnosis
var diagSymptoms = [String]() // Symptoms of the diagnosis in a ranked array to identify prevelancy
var diagSpecialization = [String]() // the specializations which would mostly encounter this diagnosis
var diagRank = Int() // the overall rank of the diagnosis
var diagSynonoms = [String]() // the other name thru which the same diagnosis is called / referred.
// func init(diagName: String(),diagSymptoms: [String](),diagSpecialization: [String](),diagSynonoms: [String]())
init( let pasdiagName: String,let pasdiagSymptoms:Array<String>) {
self.diagName = pasdiagName
self.diagSymptoms = pasdiagSymptoms
}
}
var maleria = Diagnosis(pasdiagName: "Maleria",pasdiagSymptoms: ["fever","chill","body pain"])
The above creates the structure maleria - But in future I want to have the input from user and create a structure for that inputted string
var abc = "typhoid"
let valueof(abc) = Diagnosis()
The value of function is something I just put here arbitrarily to make my explanation clear.
I know I could do this in python and I am new to swift. Thanks in advance for the help.
As #Wain suggested, you should use a Dictionary.
This is how you create a mutable dictionary where the key is a String and the value can be any type.
var dict = [String:Any]()
This is how you put key/value pairs into the dictionary
dict["year"] = 2016
dict["word"] = "hello"
dict["words"] = ["hello", "world"]
And this is how you extract a value and use it
if let word = dict["word"] as? String {
print(word) // prints "hello"
}

xpages typeahead autocomplete

i couldnt do aautocopmlete edit box. i want to take names from another database. i wrote my code to typeahead's value list. but it dont work. i am using same server but different database.anybody help me ? here is my code:
//Getting the view containing a document for each of the employees
var searchView:NotesView = session.getDatabase("servername","test/application name.nsf")
.getView("viewname");
// Creating a Lotus Notes search query. Notice the reference to lupkey!
var query = "(FIELD Ad Soyad CONTAINS *" + lupkey +"*)";
// Creating an array to store hits in
var searchOutput:Array = ["å","åå"];
// Doing the actual search
var hits = searchView.FTSearch(query);
var entries = searchView.getAllEntries();
var entry = entries.getFirstEntry();
//Sort the array manually, since Notes doesn't want to sort them alphabetically
for (i=0; i<hits; i++) {
searchOutput.push(entry.getColumnValues()[0]);
entry = entries.getNextEntry();
}
searchOutput.sort();
// Build the resulting output HTML code
var result = "<ul><li><span class='informal'>Suggestions:</span></li></ul>";
var limit = Math.min(hits,20);
for (j=0; j<limit; j++) {
var name = searchOutput[j].toString();
var start = name.indexOfIgnoreCase(lupkey)
var stop = start + lupkey.length;
//Make the matching part of the name bold
name = name.insert("</b>",stop).insert("<b>",start);
result += "<li>" + name + "</li>";
}
result += "</ul>";
return result;
There are plenty of issues with your code:
the query can't return any result since your field has a space in it
Do you really need an FTSearch to return values and not a sorted view?
the typeahead -as the name suggest- presents values that match left to right and not somewhere substring. If you need that you need to roll your own typeahead function using Ajax
The typeahead function doesn't take a parameter, so your lupkey doesn't go anywhere. The function needs to return all values and XPages will do the matching
Instead of copying one by one into an array for sorting, copy the returning Vector() into a TreeSet(). This is one line, sorts it and removes duplicates
To get it working check this example based on dojo, previously asked here. You will need the REST control
i do it like that
var directoryTypeahead = function (searchValue:string) {
// update the following line to point to your real directory
//var directory:NotesDatabase = session.getDatabase(database.getServer(), "names.nsf");
var directory:NotesDatabase = session.getDatabase(database.getServer(), "org/test.nsf");
var allUsers:NotesView = directory.getView("SVFHP2");
var matches = {};
var includeForm = {
Person: true,
Group: true
}
searchValue = searchValue.replace("I","i")
var matchingEntries:NotesViewEntryCollection = allUsers.getAllEntriesByKey(searchValue, false);
var entry:NotesViewEntry = matchingEntries.getFirstEntry();
var resultCount:int = 0;
while (entry != null) {
var matchDoc:NotesDocument = entry.getDocument();
var matchType:string = matchDoc.getItemValueString("Form");
//if (includeForm[matchType]) { // ignore if not person or group
var fullName:string = matchDoc.getItemValue("Name").elementAt(0) + " " + matchDoc.getItemValue("Title").elementAt(0);
if (!(matches[fullName])) { // skip if already stored
resultCount++;
var matchName:NotesName = session.createName(fullName);
matches[fullName] = {
cn: matchName.getCommon(),
photo: matchDoc.getItemValueString("Photo"),
job: matchDoc.getItemValueString("sum"),
email: matchDoc.getItemValueString("email"),
}
}
// }
/*if (resultCount > 15) {
entry = null; // limit the results to first 10 found
}
else {*/
entry = matchingEntries.getNextEntry(entry);
//}
};
}