Google Spreadsheet - string value getting converted to date? - javascript

Guys i have a google sheet with column taskName and its type is plain text. If I enter any value like 5 jul under this column it is stored as 5 jul.
I add value in my sheet using a code similar to this:
var name = "5 Jul";
var url = "&taskName=" + encodeURIComponent(name);
var encodedString = encodeReservedCharacters(url);
var htmlVal = "<html><script src='" + url + "?action=addName&groupId=" + groupId + "&prefix=addNameCallback" + "&" + encodedString + "'><'/script><'/html>";
$("#checkscript").html(htmlVal);
function encodeReservedCharacters(queryString) {
var reservedCharWithEquivalentHexCode = {
"(": "%28",
")": "%29",
"/": "%2F",
"*": "%2A",
"'": "%27"
};
queryString = queryString.replace(/[()/*']/g, function(match) {
return reservedCharWithEquivalentHexCode[match];
});
return queryString;
};
groupId is my worksheet id that i get using OAuth token
Sheet is updated but instead of "5 Jul", 7/5/2015 is stored. How to solve this?

I had to prepend a tick (') to the cell contents that were suddenly interpreted as date by the new Google Sheets, such as "2015-06" (now I insert "'2015-06")

Related

How to iterate through a range, get 1st Col data once and continue iterating to form an html table, using Google Apps Script?

This is not duplicated, as the result goes into a string, not an HTML file.
The code below almost gets me there, but it keeps repeating the first column's data, while it should appear in the result only once:
The data:
City
Unit
item
Qty
Oregon
Norman
Item A
10
Oregon
Alex
Item B
50
Seattle
Monica
Item A
10
The result shows Oregon twice and the rest of Oregon related data, while it should appear once and the related data underneath it and then the loop goes on to the next City.
I'm not sure if this should be handled during the loop, or if this should be trated in the result itself.
This will be an html string to be pasted into a cell.
Here's the code, as it is now:
function dataToHTML() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const allSheets = ss.getSheets();
for (let s in allSheets){
let sheet = allSheets[s]
if (sheet.getName() == "State1"){
let html = '';
let location = sheet.getRange(1,1).getValue();
let state = sheet.getRange(1,2).getValue();
let locationHTML = '<h1>' + location + ' Businesses' + '</h1>' + '\n';
html += locationHTML
let dataValues = sheet.getRange(4, 1, sheet.getLastRow(), 6).getValues();
for (let a = 0; a < dataValues.length; a++){
if (dataValues[a][0] != ''){
let city = '<h2>' + dataValues[a][0] + '</h2>' + "\n";
let unit = '<h3>' + dataValues[a][1] + '</h3>' + "\n";
let item= '<a href="tel: ' + dataValues[a][5] + '</a>' + '\n';
let qty= dataValues[a][3] + ', ' + state + ' ' + dataValues[a][4] + "\n";
html += city + unit + item + qty
}
}
ss.getSheetByName('Sheet5').getRange(1,1).setValue(html);
}
}
}
Expected output:
"<h1>Georgia Businesses</h1>
<h2>Oregon</h2>
<h3>Norman</h3>
<a href=""tel: </a>
10, GA
<h3>Alex</h3>
<a href=""tel: </a>
50, GA
<h2>Seattle</h2>
<h3>Monica</h3>
<a href=""tel: </a>
10, GA "
Oregon should show once.
As usual, appreciate your help.
I believe your goal is as follows.
You want to convert your sample data in your question to the value of "Expected output:" in your question.
When I saw your sample data and script, I noticed the following points.
It seems that location and state are the cells "A1" and "B1". In your sample data, the cells "A1" and "B1" are "City" and "Unit", respectively. But in your expected result, Georgia and GA are used as location and state, respectively.
In your sample data, there are 4 columns (A - D). But in your script, it seems that the column "F" is used like dataValues[a][5].
In this answer, I would like to propose a modified script by supposing that your sample data has the columns "A" to "F" and the values of cells "A1" and "B1" is the header values of your actual sheet.
When your script is modified for achieving the goal, how about the following modification?
Modified script:
function dataToHTML() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sheet = ss.getSheetByName("State1");
if (!sheet) return;
const [[location, state], ...values] = sheet.getDataRange().getValues();
const obj = values.reduce((m, [a, ...b]) => m.set(a, m.has(a) ? [...m.get(a), b] : [b]), new Map());
let html = `<h1>${location} Businesses</h1>\n`;
obj.forEach((v, k) => {
html += `<h2>${k}</h2>\n`;
v.forEach(e => {
html += `<h3>${e[0]}</h3>\n`;
html += `${e[4]}\n`;
html += `${e[2]}, ${state} ${e[3]}\n`;
});
});
ss.getSheetByName('Sheet5').getRange(1, 1).setValue(html);
}
In your script,
When you want to use only the sheet "State1", you can directly retrieve it using getSheetByName.
getValue() is used in the loop. In this case, the process cost will become high.
About let item= '<a href="tel: ' + dataValues[a][5] + '</a>' + '\n';, the value of tel: is not enclosed by the double quotes.
In this modification,
Values are retrieved from the sheet "State1".
Create an object for putting to HTML.
Create the HTML data.
Note:
I thought that the provided sample data in your question might not be for your expected result. So I proposed the above-modified script by supposing your sample data. So, when the above script was not the result you expect, can you provide the sample input and output data you expect? By this, I would like to modify the script.
References:
getSheetByName(name)
Map

How do I pass multiple variables as query string parameter

I am working with the below Javascript function. It only works when the value is a number. I mean it only returns the value if it is a a number. For example:
var ldInstID = getParameterByName("ID")
If ID is a number then it works and assigns the value to the variable but if the ID is a string it is not working. Please help to make this work for a string too.
I am using this on SharePoint list edit page where ID is a list column value. I want to capture another column city and pass it as href query string along with ID.
In the attached images you can see that ldInstID is blank
<!--
Name: dispParent.js
-->
<script type="text/javascript" src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.7.2.min.js"></script>
<script type="text/javascript">
jQuery(document).ready(function($) {
//get the ID for the Issue from the Query String
// var issueID = getParameterByName("ID");
var ldInstID = getParameterByName("LeadInsitution");
//find the element with the "Add new item" link.
//note that if you have more than one list on your page, this just finds the first one
var anchorElement = $("a[title='Add a new item to this list or library.']");
//modify the "Add new item" link to call the "NewItem2" function and pass in the Issue ID.
//Be sure to put the path to your site below. You can use relative URL to the web application or the FQDN
// $(anchorElement).attr("href","javascript:NewItem2(event,'URL/Lists/Time/NewForm.aspx?IssueID=" + issueID + "');");
// $(anchorElement).attr("href","javascript:NewItem2(event,'URL/NewForm.aspx?IssueID=" + issueID + "&LdInst" + LdInst + "');");
$(anchorElement).attr("href","javascript:NewItem2(event,'URL/NewForm.aspx?LdInstID=" + ldInstID + "');");
//remove the "onclick" attribute from the anchor element as we aren't using it anymore
$(anchorElement).removeAttr("onclick");
});
// no, I didn't write this function from scratch, I found it at
// http://stackoverflow.com/questions/901115/get-query-string-values-in-javascript
// http://www.sharepointhillbilly.com/Lists/Posts/Post.aspx?ID=26
function getParameterByName(name)
{
name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
var regexS = "[\\?&]" + name + "=([^&#]*)";
var regex = new RegExp(regexS);
var results = regex.exec(window.location.href);
if(results == null)
return "";
else
return decodeURIComponent(results[1].replace(/\+/g, " "));
}
</script>
variable passed-ID
Variable passed- ldInstID
Get parameter by id from URL:
function getURLParameter(parameterName) {
let result = null, temp = [];
location.search
.substr(1)
.split('&')
.forEach(function (item) {
temp = item.split('=');
if (temp[0] === parameterName)
result = decodeURIComponent(temp[1]);
});
return result;
}
if my url is http://example.com?id1=100&text=my%20text
console.log(getURLParameter('id1')); // 100
console.log(getURLParameter('text')); // "my text"

Google Sheets Script / Dynamically Add Formula

I'm trying append some daily values to a sheet but can't quite figure out how to capture the current cell in a variable and then reuse it to generate the formula.
This is the code that I'm using
var emptyA = sheet.getRange(sheet.getLastRow()+1,1,1)
var emptyB = sheet.getRange(sheet.getLastRow()+1,2,1)
var emptyC = sheet.getRange(sheet.getLastRow()+1,3,1)
I'd like multiply the daily value in the A column with the value in cell F5 which also updates daily, because this changes it should be a formula so I figure it's something along the lines of
var dailyValue = sheet.getRange('F5')
var lastA = sheet.getRange(sheet.getLastRow(),2,1)
var formula = "=" + lastA + "*" + dailyValue
emptyB.setFormula([formula])
The problem that I'm having is lastA gives me "RANGE" rather than the cell ID
Does anyone have any thoughts?
Cheers, Rich
I guess you need to change
var formula = "=" + lastA + "*" + dailyValue
to
var formula = "=" + "F5" + "*" + dailyValue.getA1Notation();
Use getA1Notation() to return cell address like A500.
Use getValue() if you need the value to be hardcoded instead of a link to cell.
Change the following lines:
var dailyValue = sheet.getRange('F5').getValue
var lastA = sheet.getRange(sheet.getLastRow(),2).getValue
emptyB.setFormula(formula)

Read multiple JSON API Pages and parse data

Objective: To collect JSON data from forecast API and then read the JSON precipIntensity property over the number of days specified, this code starts at three. Since this take a number of steps to coherently follow please try to make sense of all the code.
My main issue is trying to name the JSON code pages that return then put them into another context to read the precipIntensity
property.
To outline: The back date gets the UNIX time, then requests an API for each forecast day. Then the APIs are put in an array. The array is put in a for() loop to request each JSON script... (now what to do? I would like to be able to read each or calculate something but I do not know how to ask for the formatted code. I can do the remaining bit).
A sample of JSON can be found at my other related post...
https://stackoverflow.com/questions/29949454/store-json-api-object-data-and-reuse-it (I found that the API server stores the data for me...solved)
EDITED since 5/1/15:
//Get the back dated times and current in UNIX,
//later make a lookup that gives datediff from current date and user's date and adjust index i condition to equal exact days.
var totalPrecipSinceDate;
var threeDayAPITimes = [];
for (var i = 0; i <= 2; i++) //place user userData-1 where i <= input
{
var myDate = new Date(); //https://stackoverflow.com/questions/7693170/javascript-convert-from-epoch-string-to-date-object
var epoch = myDate.getTime(); //1318023197289 number of ms since epoch
var unixEpoch = Math.round(epoch/1000)
threeDayAPITimes[i] = Math.round(unixEpoch - (86400 * i));
/*
var epoch = (DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds;
threeDayAPITimes[i] = Math.round(epoch - (86400 * i));
*/
}
//Plan to convert UNIX dates to display
//List of locations: LATITUDE,LONGITUDE
var locations = ["46.3494,-85.5083"]
var currentAPIKey ="privateAPIKey"; //gets an APIkey from user from forecaster input.
var listAPIs = "";
$.each(threeDayAPITimes, function(i, time) {
var darkForecastAPI= "https://api.forecast.io/forecast/" + currentAPIKey + "/" + locations + "," + time;
$.getJSON(darkForecastAPI, {
tags: "WxAPI[" + i + "]", //Is this tag the name of each JSON page? I tried to index it incase this is how to refer to the JSON formatted code from the APIs.
tagmode: "any",
format: "json"
}, function(result) {
// Process the result object
});
});
//Process result in foreach loop
var eachPrecipSum = 0;
if(result.currently.precipIntensity >=0 && result.currently.precipType == "rain")
{
$.each(result, function() {
eachPrecipSum += (this.currently.precipIntensity);
totalPrecipSinceDate += eachPrecipSum ;
});
}
alert(eachPrecipSum );
Your loop should be something like this:
$.each(threeDayAPITimes, function(i, time) {
var darkForecastAPI= "https://api.forecast.io/forecast/" + currentAPIKey + "/" + locations + "," + time;
$.getJSON(darkForecastAPI, {
tags: "WxAPI[" + i + "]", //Is this tag the name of each JSON page? I tried to index it incase this is how to refer to the JSON formatted code from the APIs.
tagmode: "any",
format: "json"
}, function(result) {
// Process the result object
});
}

Compare timestamp in two different formats - GAS

I am using the enhanced workflow script that was posted by Mogsdad here.
I have managed to work out a few issues but one that I am stuck on at the moment is the error that comes up from this section -
// Record approval or rejection in spreadsheet
var row = ArrayLib.indexOf(data, 0, timestamp);
if (row < 0) throw new Error ("Request not available."); // Throw error if request was not found
sheet.getRange(row+1, approvalCol).setValue(e.parameter.approval);
I get the "Request not available" error because the ArrayLib.indexOf object is comparing the time stamp that is being presented from the same source but via two different 'routes'.
The timestamp from the 'timestamp' variable looks like this - "17/03/2015 18:00:11"
...and the timestamp contained in the 'data' variable (that should match the timestamp variable) looks like this - "Tue Mar 17 2015 00:30:10 GMT-0700 (PDT)".
I am assuming that the two different formats is what is resulting in the ArrayLib.indexOf object returning a '-1' result and hence the error message.
Any thoughts on what I need to do to get the matching working successfully ?
Create a new Date object for the timestamp value, so that you can ensure they can be compared. The code should look like:
var dateFromTimestamp = new Date(timestamp);
After looking around at a few other posts I came up with a solution that seems to work pretty well and overcomes the issues with using the timestamp.
I put an array formula in the first column of the response sheet that created a ticket number -
=ArrayFormula(if(B2:B,"AFR"&text(row(A2:A)-1,"00000"),iferror(1/0)))
Then I retrieved the ticket number (var cellVal) and sent it with the email. The response email brings the approval value to the correct line every time....so far.
function sendEmail(e) {
// Response columns: Timestamp Requester Email Item Cost
var email = e.namedValues["Requester Email"];
var item = e.namedValues["Item"];
var cost = e.namedValues["Cost"];
//var timestamp = e.namedValues["Timestamp"];
var row = e.range.getRow();
var seq = e.values[1];
var url = ScriptApp.getService().getUrl();
var sheet = SpreadsheetApp.openById('1pFL0CEW5foe8nAtk0ZwwTleYrBn2YulMu_eKPDEFQaw').getSheetByName("Form Responses 1");
var range = sheet.getDataRange();
var cellval = range.getCell(row,1).getValue();
//var origMail = range.getCell(row,3).getValue();
Logger.log(cellval);
//Logger.log(origMail);
var options = '?approval=%APPROVE%&reply=%EMAIL%'
.replace("%EMAIL%",e.namedValues["Requester Email"])
var approve = url+options.replace("%APPROVE%","Approved")+'&row='+row+'&cellval='+cellval;
var reject = url+options.replace("%APPROVE%","Rejected")+'&row='+row+'&cellval='+cellval;
var html = "<body>"+
"<h2>Please review</h2><br />"+
"Request from: " + email + "<br />"+
"Ticket No: " + cellval + "<br />"+
"For: "+item +", at a cost of: $" + cost + "<br /><br />"+
"Approve<br />"+
"Reject<br />"+
"</body>";
MailApp.sendEmail(Session.getEffectiveUser().getEmail(),
"Approval Request",
"Requires html",
{htmlBody: html});
}

Categories