I'm using nodejs with google sheets API and I'm trying to sort data by column with date string that looks like this: 'dd.mm', for example '01.03'. Currently I'm trying to do it by using batchUpdate, but it doesnt work. It sorts by day, 01 is first, 02 is second etc... My request looks like this:
await googleSheets.spreadsheets.batchUpdate({
spreadsheetId,
requestBody: {
requests: [
{
sortRange: {
range: {
sheetId,
startRowIndex,
endRowIndex,
startColumnIndex,
endColumnIndex,
},
sortSpecs: [
{
dimensionIndex,
sortOrder,
},
],
},
},
],
},
});
How can I make google sheets API see the columns as dates, not as strings? Because I assume thats where the problem is, the date string is sorted like a normal string.
Format the range to date format of day.month in your Google Sheets.
Highlight column or range you want to format.
Click Format Tab -> Number -> Custom number format.
In the text box, insert this value: d"."m.
Click Apply.
Step by step example:
Google Sheets can now recognize the data as date, you can sort it now using the API.
Example:
Request:
{
"requests": [
{
"sortRange": {
"range": {
"sheetId": 0,
"startRowIndex": 0,
"startColumnIndex": 0,
"endRowIndex": 13,
"endColumnIndex": 1
},
"sortSpecs": [
{
"sortOrder": "ASCENDING",
"dimensionIndex": 0
}
]
}
}
]
}
Output:
Reference:
Custom date formatting
Related
I want to create a line chart by Google Chart API. I want to get data from AJAX method and set data to chart as javascript JSON array, but I have a problem with datetime format inside. Additional, a AJAX data is a string which generated from PHP. I parse returned string to JSON array which I want to set as chart data.
v1 = '{"Date(2023, 1, 1, 20, 00, 00)", ... }'; # returned string AJAX
v1 = jQuery.parseJSON(v1);
data = new google.visualization.DataTable();
data.addColumn('datetime', 'Time');
data.addColumn({...something else...});
data.addRows(v1);
options = { ... };
chart = new google.visualization.LineChart(document.getElementById('linechart_material'));
chart.draw(data, options);
And I have this error message in console, when I try use Date(year, month, day, hour, minute, second) constructor (Google "Date String Representation" method) as first element of v1 array: Unhandled Promise Rejection: Error: Type mismatch. Value Date(2023, 1, 1, 20, 00, 00) does not match type datetime in column index 0
How to prepare datetime in JSON array and Google Chart API?
google's "Date String Representation" method only works when you are passing the json to the data table's constructor.
see following working snippet.
the json must be in a specific format, which you can see below,
or here: Format of the Constructor's JavaScript Literal data Parameter
however, they use a bad example on their page because they use the new keyword in front of the date value, which isn't required.
point being, you must have the json formatted as below, with keys for rows and columns...
google.charts.load('current', {
packages: ['corechart']
}).then(function () {
var jsonData = {
"cols": [
{"label": "datetime", "type": "date"},
{"label": "value", "type": "number"}
],
"rows": [
{"c":[{"v": "Date(2023, 1, 1, 0, 0, 0)"}, {"v": 1}]}, // = Feb 1, 2023 (month number index is zero-based)
{"c":[{"v": "Date(2023, 1, 2, 0, 0, 0)"}, {"v": 2}]},
{"c":[{"v": "Date(2023, 1, 3, 0, 0, 0)"}, {"v": 3}]},
]
};
var dataTable = new google.visualization.DataTable(jsonData);
console.log('data table rows', dataTable.getNumberOfRows());
console.log('row 1 date', dataTable.getValue(0, 0));
});
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
from here: https://developers.google.com/chart/interactive/docs/datesandtimes#dates-and-times-using-the-date-string-representation
When serializing data using the JavaScript DataTable object literal notation to build your DataTable, the new Date() constructor cannot be used. Instead, Google Charts provides a Date string representation that allows your date or datetime to be serialized and parsed properly when creating a DataTable. This Date string format simply drops the new keyword and wraps the remaining expression in quotation marks:
"Date(Year, Month, Day, Hours, Minutes, Seconds, Milliseconds)"
I am completely new to the topic of APIs and Postman and have the following question:
How can I detect multiple dates in a string and reformat them into a timestamp?
I pulled a JSON format via an API, then converted it to a string via the JSON.stringify function, and then stored it in an environment variable.
It now looks something like this:
[{“date”:“2000-01-01”,“value”:11.8432},{“date”:“2001-01-01”,“value”:112.2348},{“date”:“2002-01-01”,“value”:182.3777},{“date”:“2003-01-01”,“value”:15.0186},{“date”:“2004-01-01”,“value”:131.3781},{“date”:“2005-01-01”,“value”:145.3683}]
Now I’m trying to get this string back into a JSON format but I’d like to add a UNIX time stamp to the date (in milliseconds since January 1, 1970).
So it should look something like this:
[{“date”:946684800000,“value”:11.8432},{“date”:978307200000,“value”:112.2348},{“date”:1009843200000,“value”:182.3777}…
Does anyone know how to solve this within Postman (JavaScript for Postman)?
use moment library and the valueOf() method:
moment = require('moment')
let date = [{ "date": "2000-01-01", "value": 11.8432 }, { "date": "2001-01-01", "value": 112.2348 }, { "date": "2002-01-01", "value": 182.3777 }, { "date": "2003-01-01", "value": 15.0186 }, { "date": "2004-01-01", "value": 131.3781 }, { "date": "2005-01-01", "value": 145.3683 }]
date = date.map((item) => {
item.date = moment(item.date, "YYYY-MM-DD").valueOf()
return item
});
console.log(date)
My mongoDB collection looks like this:
[
{
"id": "myid",
"field": {
"total": 1,
"subfield": [
{
"time": "2020-08-06T08:33:57.977+0530"
},
{
"time": "2020-05-08T04:13:27.977+0530"
}
]
}
},
{
"id": "myid2",
"field": {
"total": 1,
"subfield": [
{
"time": "2020-07-31T10:15:50.184+0530"
}
]
}
}
]
I need to update all the documents and convert date string in the field time available in the subfieldarray to mongoDB ISO date format.
I have thousands of documents and hundreds of objects in subfield array
I'm aware of the aggregate function $todate and $convert.
But I don't want to use aggregation because,
To use $todate or $convert, I need to unwind the field.subfield array which is again an expensive operation.
I want to update my document and save it with the date format.
My MongoDB server version: 4.0.3
I tried the following but it doesn't seem to work and also doesn't return any errors.
db.collection.find().forEach(function(doc) {
doc.field.subfield.time=new ISODate(doc.field.subfield.time);
db.collection.save(doc);
})
You missed a loop for subfield, because its an array,
db.collection.find().forEach(function(doc) {
doc.field.subfield.forEach(function(r) {
r.time = new ISODate(r.time);
})
db.collection.save(doc);
})
If this is for one time then time does not matter, i think both will take same time if you do with aggregation or forEach.
If you are planing to update MongoDb version then form 4.2,
a option you can update with updateMany() using update with aggregation pipeline,
db.collection.updateMany({},
[{
$set: {
"field.subfield": {
$map: {
input: "$field.subfield",
as: "r",
in: {
$mergeObjects: [
"$$r",
{ time: { $toDate: "$$r.time" } }
]
}
}
}
}
}]
)
I'm using Cloudant's map reduce functionality and I want to find how many events (count of events object) the specific user with name (input from user) has attended for a date range (input from user).
I have docs that look like below.
{
user: {
name: 'peter pan'
},
startEventDateTime: <timestamp>,
endDateDateTime: <timestamp>,
events: [
{
name: 'La la land',
text: 'more info'
},
{
name: 'La la land',
text: 'more info'
}
]
}
Above means, user attended 2 events between between that start and end time. There are many documents for the same user for a different date range too with the events attended list.
How can I achieve this in Cloudant map reduce?
My Attempt:
unable to get map correctly. I can filter by name by doing
map:
function (doc) {
emit([doc.user, doc.events, startEventDateTime, endDateDateTime], doc)
}
reduce:
function (keys, values, rereduce) {
if (rereduce) {
return sum(values);
} else {
return values.length;
}
}
I would suggest considering a different format for your documents. Instead of having a user document with a list of events, make a separate document for each event, timestamped for the time at which it happened, such as:
{
"_id": "c48ee0881ce7c5d39243d2243d2e63cb",
"_rev": "1-c2f71fba5f09b129f1db20785f2429b2",
"user": "bob",
"datetime": "Thu 30 Nov 2017 09:46:02 GMT",
"event": {
"name": "lalaland",
"text": "more info"
}
}
Then you can rely on MapReduce to pick out date ranges per user. Here's a map function that does just that:
function (doc) {
if (doc && doc.user && doc.datetime) {
var when = new Date(Date.parse(doc.datetime));
emit([doc.user, when.getFullYear(), when.getMonth(), when.getDay()], 1);
}
}
and using the built-in reduce _sum. You can now use key ranges to slice the data. Say you want the events attended by user bob in Aug, 2017:
curl 'https://ACCT.cloudant.com/DBNAME/_design/DDOC/_view/VIEWNAME?startkey=\["bob", 2017, 7\]&endkey=\["bob", 2017, 8]&group=true&inclusive_end=false&reduce=true'
{
"rows": [
{
"key": [
"bob",
2017,
7,
4
],
"value": 1
}
]
}
I was fighting with HighCharts quite some hours for formatting the data input to the series option.
Finally I saw the link here solved my problem for data formatting and input.
The data format that would be recognized by HighCharts pie chart is like this (format 1) as indicated by the link above:
[["chrome",15],["firefox",20]]
I actually want dynamic data input from external URL and format the data so that HighCharts can recognized it. The data format I got from the URL is like this (format 2):
[
{
"status": "Stopped \/ Idle",
"val": 17.469444444444,
}, {
"status": "Working",
"val": 0,
}, {
"status": "Headland Turning",
"val": 0,
}, {
"status": "Transport",
"val": 0.15333333333333,
}
]
which is already in JSON format.
I just want to know that is that necessary for me to write a parser for the data from format 2 to format 1? Or Am I missing something that HighCharts can recognize the JSON format data and I don't actually need to write a parser?
I am new to HighCharts so feel free to point that out if some of my problem description does not make sense..Thank you!
EDIT: Thanks for all guys answering my question!
When a script expects data in specific format, you often have to map your data to fit format. This can be modified in server code or using javascript
Can use jQuery $.map to reconfigure an object or array to another array.
DEMO: http://jsfiddle.net/qpsSe/1
Note that trailing commas in sample JSON need removing to validate JSON
/* "json" is your response object, modify variable names to match */
var chartData=$.map( json, function( obj,i){
return [[ obj.status, obj.val]];
})
$.map API Docs
Alternate method in native javascript
var chartData=[];
for( i=0; i<json.length; i++){
chartData.push( [ json[i]['status'], json[i]['val'] ])
}
AFAIK that's just how Highcharts wants its data. That being said, the parser is pretty easy:
var data; // this is your received data
var highchartsData = []; // this is data for highcharts
$.each(data, function(i, e) {
highchartsData.push([e.status, e.val]);
});
One thing to note is that if the data you're receiving is in text (say, a response from an AJAX call) then you need to convert it to a javascript object like so:
var data = $.parseJSON(textData);
You need to make a parser when assigning options as stated in HighCharts preprocessing
Basically, you parse the data and include it in the options:
var serie1 = json.map( function(e) {
return [e.status, e.val];
});
options.series.push({data: serie1});
Here is a working example using $.map and options in Fiddle
Since Highcharts 3.0, categories can also be extracted by giving each point a name and setting axis type to "category".
For a column bar chart this would be:
xAxis: {
type: 'category',
},
series: [{
data: [{
name: 'Point 1',
color: '#00FF00',
y: 1
}, {
name: 'Point 2',
color: '#FF00FF',
y: 5
}]
}]
You can bind chart with JSON data, directly.
You just need to set the json property names as highchart standard.
'Y' for value and 'name' for label.
Your JSON should be as like follow:
[
{
name: "Stopped \/ Idle",
y: 17.469444444444
}, {
name: "Working",
y: 0
}, {
name: "Headland Turning",
y: 0
}, {
name: "Transport",
y: 0.15333333333333
}
]