I am trying to push mixpanel data into a single Google Sheet using code from here:
https://github.com/melissaguyre/mixpanel-segmentation-google-spreadsheets
I am having issues with the API_PARAMETERS not looping through as expected. (Formula, Formula1, & Formula2) The first two parameters loop through fine, but when the final is added, I get the error:
TypeError: Cannot read property "2016-07-11" from undefined. (line 143, file "Code")
Here is the code:
* Step 1) Fill in your account's Mixpanel Information here
`enter code here`*/
var API_KEY = '******';
var API_SECRET = '****';
/**
* Step 2) Define the tab # at which to create new sheets in the spreadsheet.
* 0 creates a new sheet as the first sheet.
* 1 creates a new sheet at the second sheet and so forth.
*/
var CREATE_NEW_SHEETS_AT = 0;
/**
* Step 3) Define date range as a string in format of 'yyyy-mm-dd' or '2013-09-13'
*
* Today's Date: set equal to getMixpanelDateToday()
* Yesterday's Date: set equal to getMixpanelDateYesterday()
*/
var FROM_DATE = getMixpanelDate(7);
var TO_DATE = getMixpanelDate(1);
/**
* Step 4) Define Segmentation Queries - Get data for an event, segmented and filtered by properties.
var API_PARAMETERS = {
'Formula' : [ 'QuestionAsked', '(properties["InputMethod"]) == "Voice" or (properties["InputMethod"]) == "Text" ', 'general', 'day', 'B7'],
'Formula1' : [ 'QuestionAsked', '(properties["InputMethod"]) == "Voice" or (properties["InputMethod"]) == "Text" ', 'unique', 'day', 'B2'],
//'Formula2' : [ 'QuestionAnswered', '(properties["InputMethod"]) == "Voice" or (properties["InputMethod"]) == "Text" ', 'unique', 'day', 'B3' ],
};
// Iterates through the hash map of queries, gets the data, writes it to spreadsheet
function getMixpanelData() {
for (var i in API_PARAMETERS)
{
var cell = API_PARAMETERS[i][4];
fetchMixpanelData(i, cell);
}
}
// Creates a menu in spreadsheet for easy user access to above function
function onOpen() {
var activeSpreadsheet = SpreadsheetApp.getActiveSpreadsheet();
activeSpreadsheet.addMenu(
"Mixpanel", [{
name: "Get Mixpanel Data", functionName: "getMixpanelData"
}]);
}
/**
* Gets data from mixpanel api and inserts to spreadsheet
*
*/
function fetchMixpanelData(sheetName, cell) {
var c = cell;
var expires = getApiExpirationTime();
var urlParams = getApiParameters(expires, sheetName).join('&')
+ "&sig=" + getApiSignature(expires, sheetName);
// Add URL Encoding for special characters which might generate 'Invalid argument' errors.
// Modulus should always be encoded first due to the % sign.
urlParams = urlParams.replace(/\%/g, '%25');
urlParams = urlParams.replace(/\s/g, '%20');
urlParams = urlParams.replace(/\[/g, '%5B');
urlParams = urlParams.replace(/\]/g, '%5D');
urlParams = urlParams.replace(/\"/g, '%22');
urlParams = urlParams.replace(/\(/g, '%28');
urlParams = urlParams.replace(/\)/g, '%29');
urlParams = urlParams.replace(/\>/g, '%3E');
urlParams = urlParams.replace(/\</g, '%3C');
urlParams = urlParams.replace(/\-/g, '%2D');
urlParams = urlParams.replace(/\+/g, '%2B');
urlParams = urlParams.replace(/\//g, '%2F');
var url = "http://mixpanel.com/api/2.0/segmentation?" + urlParams;
Logger.log("THE URL " + url);
var response = UrlFetchApp.fetch(url);
var json = response.getContentText();
var dataAll = JSON.parse(json);
var dates = dataAll.data.series;
Logger.log(API_PARAMETERS);
for (i in API_PARAMETERS){
var parametersEntry = API_PARAMETERS[i];
for (i in dates){
data = dataAll.data.values[parametersEntry[0]][dates[i]];
}
insertSheet(data, c);
};
}
function insertSheet(value, cell) {
var sheetName = 'Formula';
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName(sheetName);
var c = sheet.getRange(cell).setValue(value);
};
/**
* Returns an array of query parameters
*/
function getApiParameters(expires, sheetName) {
var parametersEntry = API_PARAMETERS[sheetName];
return [
'api_key=' + API_KEY,
'expire=' + expires,
'event=' + parametersEntry[0],
'where=' + parametersEntry[1],
'type=' + parametersEntry[2],
'unit=' + parametersEntry[3],
'from_date=' + FROM_DATE,
'to_date=' + TO_DATE
];
}
/**
* Sorts provided array of parameters
*
function sortApiParameters(parameters) {
var sortedParameters = parameters.sort();
// Logger.log("sortApiParameters() " + sortedParameters);
return sortedParameters;
}
/**
function getApiExpirationTime() {
var expiration = Date.now() + 10 * 60 * 1000;
// Logger.log("getApiExpirationTime() " + expiration);
return expiration;
}
/**
* Returns API Signature calculated using api_secret.
*/
function getApiSignature(expires, sheetName) {
var parameters = getApiParameters(expires, sheetName);
var sortedParameters = sortApiParameters(parameters).join('') + API_SECRET;
// Logger.log("Sorted Parameters " + sortedParameters);
var digest = Utilities.computeDigest(Utilities.DigestAlgorithm.MD5, sortedParameters);
var signature = '';
for (j = 0; j < digest.length; j++) {
var hashVal = digest[j];
if (hashVal < 0) hashVal += 256;
if (hashVal.toString(16).length == 1) signature += "0";
signature += hashVal.toString(16);
}
return signature;
}
/**
*********************************************************************************
* Date helpers
*********************************************************************************
*/
// Returns today's date string in Mixpanel date format '2013-09-11'
function getMixpanelDateToday() {
var today = new Date();
var dd = today.getDate();
var mm = today.getMonth() + 1;
var yyyy = today.getFullYear();
if (dd < 10) {
dd = '0' + dd;
}
if ( mm < 10 ) {
mm = '0' + mm;
}
today = yyyy + '-' + mm + '-' + dd;
return today;
}
// Returns yesterday's's date string in Mixpanel date format '2013-09-11'
function getMixpanelDate(days){
var today = new Date();
var d = new Date(today);
d.setDate(today.getDate() - days);
//Logger.log(yesterday);
var dd = d.getDate();
//Logger.log(yesterday);
var mm = d.getMonth() + 1;
var yyyy = d.getFullYear();
if (dd < 10) {
dd = '0' + dd;
}
if (mm < 10) {
mm = '0' + mm;
}
d = yyyy + '-' + mm + '-' + dd;
//Logger.log(yesterday);
return d;
}
Related
I am trying to use textFinder to return the data from recordsSheet; I expect cslData[0] to return the employee ID number; however, it is returning the character in the 0 position of the string value.
function textFinder(findID){
var recordData;
var findRecord = recordsSheet.createTextFinder(findID);
var foundRange = findRecord.findNext();
var fRng = recordsSheet.getRange(foundRange.getRow(),1,1,9)
while(null != foundRange){
recordData.push(fRng.getValues());
foundRange = findRecord.findNext();
}
return(recordData);
}
var ss = SpreadsheetApp.getActiveSpreadsheet();
var recordsSheet = ss.getSheetByName("Active Records");
function onFormSubmit(e) {
var eRng = e.range;
var eRow = eRng.getRow();
var colA = ss.getRange('A' + eRow).getValue()
//The second value of the form response (e) is in Column A
Logger.log("Call txt finder")
var cslData = textFinder(colA).toString().split(",").join();
Logger.log("cslData: " + cslData)
Logger.log("cslData[0]: " + cslData[0])
Logger.log("cslData[1]: " + cslData[1])
Logger.log("cslData[2]: " + cslData[2])
Logger.log("cslData[0][0]: " + cslData[0][0])
}
I was expecting cslData[0] to return "100###5"
Modification points:
In your script, eRow is not declared. And, e is not used. Please be careful about this. In this modification, it supposes that eRow is declared elsewhere.
In your script, var recordData; is not an array. So, I think that an error occurs at recordData.push(fRng.getValues());. So, I'm worried that your showing script might be different from your tested script.
If var recordData; is var recordData; = [], about your current issue, in your script, the array of recordData is converted to the string by var cslData = textFinder(colA).toString().split(",").join();. By this, cslData[0] returns the top character. I thought that this is the reason for your issue.
And, if var recordData; is var recordData; = [], recordData is 3 dimensional array.
In your situation, I thought that findAll might be useful.
When these points are reflected in your script, how about the following modification?
Modified script:
var ss = SpreadsheetApp.getActiveSpreadsheet();
var recordsSheet = ss.getSheetByName("Active Records");
function textFinder(findID) {
return recordsSheet
.createTextFinder(findID)
.findAll()
.map(r => recordsSheet.getRange(r.getRow(), 1, 1, 9).getValues()[0]);
}
function onFormSubmit(e) {
var colA = ss.getRange('A' + eRow).getValue();
var cslData = textFinder(colA);
Logger.log("cslData: " + cslData);
if (cslData.length > 0) Logger.log("cslData[0]: " + cslData[0][0]);
}
or, I think that you can also the following script.
function onFormSubmit() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var recordsSheet = ss.getSheetByName("Active Records");
var eRow = ###; // Please set this.
var findID = ss.getRange('A' + eRow).getValue();
var cslData = recordsSheet.createTextFinder(findID).findAll().map(r => recordsSheet.getRange(r.getRow(), 1, 1, 9).getValues()[0]);
Logger.log("cslData: " + cslData)
if (cslData.length > 0) Logger.log("cslData[0]: " + cslData[0][0])
}
Reference:
findAll()
Could anyone point me in the correct direction?
I searched plenty... I had no luck with mapping... or "find" nor extracting the data I need.
My code:
function checkMeetCode(meetCode, index, searchDate) {
var ss=SpreadsheetApp.getActive().getSheetByName('AsistenciaMeet');
var colB = ss.getRange("D3:D").getValues();
var filasLlenasLengthB = colB.filter(String).length; //
var userKey = 'all';
var applicationName = 'meet';
var emailAddress = colB[index];
Logger.log("Index / Alumno: "+index+" / " + emailAddress);
var optionalArgs = {
event_name: "call_ended",
endTime: searchDate,
startTime: fechaRestada(searchDate),
filters: "identifier==" + emailAddress + ",meeting_code==" + meetCode
};
var response = AdminReports.Activities.list(userKey, applicationName, optionalArgs)
Logger.log("RESPONSE: "+response);
var actividad = response.items;
if (actividad == null) {
// do nothing
}
else {
**// HERE IS WHERE I AM TRYING TO FIND / EXTRACT INFORMATION FROM "response"
// READ BELOW PLEASE.**
}
}
NEED HELP WITH:
I want to FIND/EXTRACT the intValue of "duration_seconds":
The results from:
Logger.log("RESPONSE: "+response);
RESPONSE: {"kind":"admin#reports#activities","etag":"\"JDMC8884sebSctZ17CIssbQ/IhilrSKVziEhoZ7URUpQ-NrztHY\"","items":[{"events":[{"parameters":[{"name":"video_send_seconds","intValue":"1829"},{"name":"screencast_recv_packet_loss_mean","intValue":"0"},{"name":"identifier_type","value":"email_address"},{"name":"video_send_packet_loss_max","intValue":"0"},{"name":"endpoint_id","value":"meet_android_4154513448557872"},{"name":"video_recv_long_side_median_pixels","intValue":"320"},{"name":"calendar_event_id","value":"44jr4vu3qo75q6bvkknq_20200421T213000Z"},{"name":"video_send_fps_mean","intValue":"29"},{"name":"video_recv_short_side_median_pixels","intValue":"180"},{"name":"network_estimated_download_kbps_mean","intValue":"351"},{"name":"duration_seconds","intValue":"1830"},{"name":"video_send_bitrate_kbps_mean","intValue":"762"},{"name":"network_recv_jitter_msec_max","intValue":"130"},{"name":"ip_address","value":"186.59.21.55"},{"name":"audio_send_seconds","intValue":"1829"},{"name":"screencast_recv_packet_loss_max","intValue":"0"},{"name":"video_recv_seconds","intValue":"1818"},{"name":"network_rtt_msec_mean","intValue":"36"},{"name":"video_send_long_side_median_pixels","intValue":"640"},{"name":"screencast_recv_seconds","intValue":"1829"},{"name":"product_type","value":"meet"},{"name":"video_recv_packet_loss_max","intValue":"0"},{"name":"is_external","boolValue":false}],"name":"call_ended","type":"call"}] ...
OK, after roughly 8 hours... I was able to make it work.
var insideParameters = response["items"][0]["events"][0]["parameters"];
Logger.log(insideParameters.length);
for (var i = 30; i<insideParameters.length;i++){ // its always located above i = 30...
if(insideParameters[i].name === "duration_seconds"){
var duration = insideParameters[i].intValue;
Logger.log(duration);
}
}
I'm trying to create an array to localstorage containing some gear box values, witch I then need again to do some more calculations with specific array[?].value.
The problem I'm encountering is that the created entry returns only 2 array entries, although all entries are there but the " is at the beginning and then at the second last entry and then before and after the last entry.
These are the values generated.
spd_Dev = ["202.391,172.876,120.451,102.601,85.173,72.664,61.701,52.706,45.116,38.510,32.326,27.407,22.910,19.536,16.585,14.195,12.228","10.401"]
When I used to use a fixed array I've entered it as:
var spd_Dev = [202.391, 172.876, 120.451, 102.601, 85.173, 72.664, 61.701, 52.706, 45.116, 38.510, 32.326, 27.407, 22.910, 19.536, 16.585, 14.195, 12.228, 10.401];
So my question is how to write this values to localstorage and read again from localstorage so that I can use this values as an array.
This is what I'm trying to work.
var D_RatioId = data.truck.make + data.truck.model + "D_Ratio"
var G_RatioId = data.truck.make + data.truck.model + "G_Ratio"
var fGr = data.truck.forwardGears;
var gr = data.truck.displayedGear;
var Rpm = data.truck.engineRpm * 100;
var spd = data.truck.speed;
var T_Dia = 1008.3;
if (localStorage.getItem(G_RatioID) == undefined) {
localStorage.setItem(G_RatioID, '');
var fG_Rat = [localStorage.getItem(G_RatioID)];
} else {
var fG_Rat = [localStorage.getItem(G_RatioID)];
}
var spd_Dev = localStorage.getItem(Spd_DevId);
spd_Dev = spd_Dev ? spd_Dev.split(', ') : [];
if (localStorage.getItem("i") == undefined) {
localStorage.setItem("i", 1);
var i = localStorage.getItem("i");
} else {
var i = localStorage.getItem("i");
}
if (i <= fGr && spd > 0.5) {
if (i <= fGr + 1) {
if (i == gr) {
if (RPM > 1450) {
var G_Ratio = Math.abs(Rpm / D_Ratio * (Math.PI * T_Dia / 1000) * 60 / spd / 1000, 2).toFixed(2);
var spd_D = Math.abs(RPM / (RPM / G_Ratio / D_Ratio * (Math.PI * T_Dia / 1000) * 60 / 1000) * 0.821932).toFixed(3);
fG_Rat.push(G_Ratio);
spd_Dev.push(spd_D);
i++;
localStorage.setItem("i", i);
var G_RatioValue = fG_Rat;
var Spd_DevValue = spd_Dev;
SetG_Ratio(G_RatioID, G_RatioValue);
SetSpd_Dev(Spd_DevId, Spd_DevValue);
localStorage.setItem("spd_Dev", JSON.stringify(Spd_DevValue));
}
}
}
}
function SetG_Ratio(G_RatioID, G_RatioValue) {
localStorage.setItem(G_RatioID, G_RatioValue);
console.log(G_RatioID, G_RatioValue);
}
function SetSpd_Dev(Spd_DevId, Spd_DevValue) {
localStorage.setItem(Spd_DevId, Spd_DevValue.toString());
console.log(Spd_DevId, Spd_DevValue, Spd_DevValue.length);
}
if (spd >= 0) {
var spd_Dev = [localStorage.getItem(Spd_DevId)];
var spD_D = JSON.parse(spd_Dev);
for (i = 1; i < (fGr + 1); i++) { // Some more code dependant on the above results //
why don't you use LSM.js? it will make everything simpler. you can put the array as an array so that it will return the full array only, you will not need to use split(),
https://github.com/kevinj045/LSM_js
var lsm = new LSM("G_RatioID");
var G_RatioValue ["202.391,172.876,120.451,102.601,85.173,72.664,61.701,52.706,45.116,38.510,32.326,27.407,22.910,19.536,16.585,14.195,12.228","10.401"];
lsm.set("G_RatioID",G_RatioValue);
console.log(lsm.get("G_RatioID")); // it will return the full array
I am new in Javascript and bit by bit I have used resources here on StackOverflow to build on a project that uses external API to get time entries for users from the 10k ft project management system. I have finally have different functions together as follows:
Calls for user details which includes user_id
Get the time entries and sums up for every user who's approval has a value (pending or approval) in a specific date range. Those without approval will be ignored in the summation and their total entries left at 0.
My challenge now is to have only those with 0 as total hours of time entries receive emails to update their time entries. This code doesn't seem to select only those with 0 and send emails specifically to them. I will appreciate any pointers and/or assistance. after sending the email, this should be recorded on Google sheet
var TKF_URL = 'https://api.10000ft.com/api/v1/';
var TKF_AUTH = 'auth'
var TKF_PGSZ = 2500
var from = '2020-01-20'
var to = '2020-01-26'
var options = {
method: 'get',
headers: {
Authorization: 'Bearer ' + TKF_AUTH
}
};
function getUsers() {
var userarray = [];
var lastpage = false;
var page = 1;
do {
// gets 10kft data
var users = read10k_users(page);
// writes data from current page to array
for (var i in users.data) {
var rec = {};
// pushing of mandatory data
rec.id = users.data[i].id;
rec.display_name = users.data[i].display_name;
rec.email = users.data[i].email;
userarray.push(rec);
}
// checks if this is the last page (indicated by paging next page link beeing null
if (users.paging.next != null) {
lastpage = false;
var page = page + 1;
} else {
lastpage = true;
}
}
while (lastpage == false);
return (userarray);
return (userarray);
}
function read10k_users(page) {
var endpoint = 'users?';
var url = TKF_URL + endpoint + 'per_page=' + TKF_PGSZ + '&auth=' + TKF_AUTH + '&page=' + page;
var response = UrlFetchApp.fetch(url, options);
var json = JSON.parse(response);
//Logger.log(json.data)
return (json);
}
function showTimeData() {
var users = getUsers()
var time_array = [];
for (var i = 0; i < users.length; i++) {
// Logger.log(users[i].id)
var url = 'https://api.10000ft.com/api/v1/users/' + users[i].id + '/time_entries?fields=approvals' + '&from=' + from + '&to=' + to + '&auth=' + TKF_AUTH + '&per_page=' + TKF_PGSZ;
var response = UrlFetchApp.fetch(url, options);
var info = JSON.parse(response.getContentText());
var content = info.data;
var total_hours = 0;
for (var j = 0; j < content.length; j++) {
if (content[j].approvals.data.length > 0) {
total_hours += content[j].hours;
}
}
Logger.log('User name: ' + users[i].display_name + ' ' + 'User id: ' + users[i].id + ' ' + 'total hours: ' + total_hours+ ' ' + 'Email: ' + users[i].email)
}
}
function sendMail(showTimeData){
var emailAddress = user.email;
var message = 'Dear ' + user.display_name + 'Please update your details in the system'
var subject = ' Reminder';
MailApp.sendEmail(emailAddress, subject, message);
}
I was able to get a solution for this as follows:
for (var j = 0; j < content.length; j++) {
if (content[j].approvals.data.length > 0) {
total_hours += content[j].hours;
}
}
Logger.log('User name: ' + users[i].display_name + ' ' + 'User id: ' + users[i].id + ' ' + 'total hours: ' + total_hours + ' ' + 'Email: ' + users[i].email)
if (total_hours == 0) {
sendMail(users[i])
}
}
}
function sendMail(user) {
var emailAddress = user.email;
var message = 'Dear ' + user.display_name + 'Please update your details in the system'
var subject = ' Reminder';
MailApp.sendEmail(emailAddress, subject, message);
}
I have a JSON file with list of employes. I imported this data to table. Next step is add sorting by <th>. My script doesn't work and nothing happens. I don't know the reason. I'm just a JS beginner. Can You help me why sorting is not working?
Here is my repository:
https://github.com/rrajca/Employee-table
My js is:
$(document).ready(function() {
$.getJSON("dane.json", function(data) {
/* var sortedList = data.sort(function(a, b) {
return a.id - b.id;
}) */
var employeeList = "";
$.each(data, function(key, value) {
employeeList += "<tr>";
employeeList += "<td>"+value.id+"</td>";
employeeList += "<td>"+value.firstName+"</td>";
employeeList += "<td>"+value.lastName+"</td>";
employeeList += "<td>"+value.dateOfBirth+"</td>";
employeeList += "<td>"+value.company+"</td>";
employeeList += "<td>"+value.note+"</td>";
employeeList += "</tr>";
})
$("tbody").append(employeeList);
})
var compare = {
name: function(a, b) {
a = a.replace(/^the /i, '');
b = b.replace(/^the /i, '');
if (a < b) {
return -1;
} else {
return a > b ? 1 : 0;
}
},
duration: function(a, b) {
a = a.split(':');
b = b.split(':');
a = Number(a[0]) * 60 + Number(a[1]);
b = Number(b[0]) * 60 + Number(b[1]);
return a - b;
},
date: function(a, b) {
a = new Date(a);
b = new Date(b);
return a - b;
}
};
$('.sortable').each(function() {
var $table = $(this);
var $tbody = $table.find('tbody');
var $controls = $table.find('th');
var rows = $tbody.find('tr').toArray();
$controls.on('click', function() {
var $header = $(this);
var order = $header.data('sort');
var column;
if ($header.is('.ascending') || $header.is('.descending')) {
$header.toggleClass('ascending descending');
$tbody.append(rows.reverse());
} else {
$header.addClass('ascending');
$header.siblings().removeClass('ascending descending');
if (compare.hasOwnProperty(order)) {
column = $controls.index(this);
rows.sort(function(a, b) {
a = $(a).find('td').eq(column).text();
b = $(b).find('td').eq(column).text();
return compare[order](a, b);
});
$tbody.append(rows);
}
}
});
});
});
Change your comparison function to:
name: function(a, b) { // Add a method called name
a = a.replace(/^the /i, ''); // Remove The from start of parameter
b = b.replace(/^the /i, ''); // Remove The from start of parameter
if(parseInt(a) == +a) {
a = +a;
b = +b;
}
return a > b
}
The problem was that you were doing string comparisons on everything. So I added in a check to see if it was a number, and casted appropriately.
https://jsfiddle.net/gj2vonsL/7/
The other comparison functions that you wrote have other issues like invalid date formats, etc. But your general idea is correct