Exporting to excel with proper cell formatting on ag-grid - javascript

When I export a table to excel using ag-grid's own exportDataAsExcel() the resulting excel contains dates as General data type instead of Date.
[]
I have used this:
exportDataAsExcel({
processCellCallback: ({col, val}) => {( /*date value formatting here*/ )}
})
to format both Date, string with proper date formatting (DD/MM/YYYY) but I can't make excel properly recognize these cells as Date instead of General
This is reproducible with the excel export examples on their website: https://www.ag-grid.com/javascript-grid-excel/?framework=all#gsc.tab=0

I've used this code to apply value formatter in excell as well:
this.gridOptions.api.exportDataAsExcel({
processCellCallback: (params) => {
const colDef = params.column.getColDef()
// try to reuse valueFormatter from the colDef
if (colDef.valueFormatter) {
const valueFormatterParams: ValueFormatterParams = {
...params,
data: params.node.data,
node: params.node!,
colDef: params.column.getColDef()
};
return colDef.valueFormatter(valueFormatterParams);
}
return params.value;
},
});

You need to do three things:
When instantiating the Ag-Grid, you need to add (thanks to another user's answer elsewhere)
let excelStyles = [
{
id: "ExcelDateTime",
dataType: "dateTime",
numberFormat: { format: "yyyy-mm-dd hh:mm:ss;;;" }
},
{
id: "ExcelDate",
dataType: "dateTime",
numberFormat: { format: "yyyy-mm-dd;;;" }
}
];
...
<AgGridReact
... //such as rowData={rowData}
excelStyles={excelStyles}
...
/>;
For columns that are dates:
colDef.cellClass = "ExcelDateTime";
or
colDef.cellClass = "ExcelDate";
as appropriate, and
in your processCellCallback, format the date as an ISO date: "yyyy-mm-ddTHH:MM:ss"

Assuming that you are in control of the server-side application, I have found it easier to do the export from the server-side for any non-trivial exports / formatting.
By doing it on the server, you are in complete control of the data and the production of the Excel file, and not dependent on the limits of Ag-Grid's implementation.

Related

How to change the format of field's value in a feature layer integrated with ArcGIS Esri map?

I have integrated a Parcel Layer in the ArcGIS Esri map inside Angular application. But now I want to change the format of some values coming up in the popup template when user clicks on certain Parcel.
Now my popup values looks like this.
ASSMT_YEAR - 2,017.00
ATTDATE - 20190130
BATHROOMS - 0.00
Requirement
ASSMT_YEAR and YEAR_BUILT value format should not include commas or decimals.
ATTDATE and REC_DATE value format should be in date format.(01/30/2019)
How can I achieve above requirement?
.ts file
const createEsriPopupTemplate = function(layer) {
const config = {
fields: layer.fields.map(field => (
{
name: field.name,
type: field.type,
}
)),
title: formatName(layer.title),
};
return popupUtils.createPopupTemplate(config);
}
for (const layer of esriLayers) {
view.whenLayerView(layer).then(function (layerView) {
const popupTemplate = createEsriPopupTemplate(layer)
if (!popupTemplate) {
console.log("FeatureLayer has no fields.")
} else {
layer.popupTemplate = popupTemplate;
}
});
}
To format the fields for the popup, you can use format property of popup fieldInfos.
ArcGIS JS API - Field Info Format
In your case I think this config should work,
fieldInfos: [
{
fieldName: "ASSMT_YEAR",
label: "ASSMT Year",
format: {
dateFormat: "short-date"
}
},
{
fieldName: "ATTDATE",
label: "Attendance Date",
format: {
dateFormat: "short-date"
}
},
{
fieldName: "BATHROOMS",
label: "Bathrooms"
format: {
digitSeparator: true,
places: 0
}
}
]
Now, you are generating the popup using popupUtils.createPopupTemplate function. So to continue in that path, you will need to change a bit.
First you need to know what fields to change, and in that regard you will have to use something, for example the field type.
Second, the easy change I think it would be instead of popupUtils.createPopupTemplate, use popupUtils.createFieldInfos and follow the doc example.

nodejs unable to parse date with momentjs

I am trying to parse some csv data, however, I am not able to parse date with momentjs library.
var csv = require('csv-parser');
var fs = require('fs');
var moment = require('moment');
const bittrexDateFormat = "MM/DD/YYYY hh:mm:ss a";
var count = 0;
fs.createReadStream('orders.csv')
.pipe(csv({
headers: ['OrderUuid', 'Exchange', 'Type', 'Quantity', 'Limit', 'CommissionPaid', 'Price', 'Opened', 'Closed']
}))
.on('data', function(data) {
var createDate = moment(data.Opened, bittrexDateFormat);
console.log(createDate.toDate());
});
And the csv data looks like;
OrderUuid,Exchange,Type,Quantity,Limit,CommissionPaid,Price,Opened,Closed
24245deb-134c-4da7-990e-8d22d8fd728c,BTC-STRAT,LIMIT_SELL,77.12739479,0.00087503,0.00016874,0.06749952,12/24/2017 12:09:20 AM,12/24/2017 12:09:21 AM
And this the output;
0002-01-02T09:00:02.000Z
On the other hand, if I directly hardcode the date string I am able to get Date object.
var createDate = moment("12/24/2017 12:09:20 AM", bittrexDateFormat);
console.log(createDate.toDate());
Another thing I figured out is if I print data in event .on('data') it prints encoded string version
Row {
OrderUuid: 'O\u0000r\u0000d\u0000e\u0000r\u0000U\u0000u\u0000i\u0000d\u0000',
Exchange: '\u0000E\u0000x\u0000c\u0000h\u0000a\u0000n\u0000g\u0000e\u0000',
Type: '\u0000T\u0000y\u0000p\u0000e\u0000',
Quantity: '\u0000Q\u0000u\u0000a\u0000n\u0000t\u0000i\u0000t\u0000y\u0000',
Limit: '\u0000L\u0000i\u0000m\u0000i\u0000t\u0000',
CommissionPaid: '\u0000C\u0000o\u0000m\u0000m\u0000i\u0000s\u0000s\u0000i\u0000o\u0000n\u0000P\u0000a\u0000i\u0000d\u0000',
Price: '\u0000P\u0000r\u0000i\u0000c\u0000e\u0000',
Opened: '\u0000O\u0000p\u0000e\u0000n\u0000e\u0000d\u0000',
Closed: '\u0000C\u0000l\u0000o\u0000s\u0000e\u0000d\u0000\r\u0000' }
Row {
OrderUuid: '\u00002\u00004\u00002\u00004\u00005\u0000d\u0000e\u0000b\u0000-\u00001\u00003\u00004\u0000c\u0000-\u00004\u0000d\u0000a\u00007\u0000-\u00009\u00009\u00000\u0000e\u0000-\u00008\u0000d\u00002\u00002\u0000d\u00008\u0000f\u0000d\u00007\u00002\u00008\u0000c\u0000',
Exchange: '\u0000B\u0000T\u0000C\u0000-\u0000S\u0000T\u0000R\u0000A\u0000T\u0000',
Type: '\u0000L\u0000I\u0000M\u0000I\u0000T\u0000_\u0000S\u0000E\u0000L\u0000L\u0000',
Quantity: '\u00007\u00007\u0000.\u00001\u00002\u00007\u00003\u00009\u00004\u00007\u00009\u0000',
Limit: '\u00000\u0000.\u00000\u00000\u00000\u00008\u00007\u00005\u00000\u00003\u0000',
CommissionPaid: '\u00000\u0000.\u00000\u00000\u00000\u00001\u00006\u00008\u00007\u00004\u0000',
Price: '\u00000\u0000.\u00000\u00006\u00007\u00004\u00009\u00009\u00005\u00002\u0000',
Opened: '\u00001\u00002\u0000/\u00002\u00004\u0000/\u00002\u00000\u00001\u00007\u0000 \u00001\u00002\u0000:\u00000\u00009\u0000:\u00002\u00000\u0000 \u0000A\u0000M\u0000',
Closed: '\u00001\u00002\u0000/\u00002\u00004\u0000/\u00002\u00000\u00001\u00007\u0000 \u00001\u00002\u0000:\u00000\u00009\u0000:\u00002\u00001\u0000 \u0000A\u0000M\u0000' }
I am pretty new to nodejs but I don't think the problem occurs from either momentjs or csv-parser libraries. Instead it should be string format of stream api nodejs. Thanks a lot.
I just ran your code, and it worked just fine.
Try updating your node version or try invoking the function with
fs.createReadStream('orders.csv', 'utf16le')
the encoding should make the difference...
https://nodejs.org/api/fs.html#fs_fs_createreadstream_path_options

pg-promise ColumnSet use Postgres functions with def property

I am using a ColumnSet and the helper.insert function for a multi row insert.
I have a table column where I want to use the Postgres Date/Time now() function.
const cs = new helpers.ColumnSet([
'lastname',
{
name: 'rental_date',
def: 'now()'
}
], { table: { table: 'book_rental', schema: 'public' } })
let rentals = [
{
lastname: 'Mueller'
},
{
lastname: 'Johnson'
}
]
let insert = helpers.insert(rentals, cs)
db.result(insert)
.then(data => res.json({ message: 'Ok!' }))
.catch(err => res.json({ message: 'Not ok!' }))
It seems to be working by using def: 'now()', but I want to make sure that I am using it the right way.
Edit:
Regarding the answer in the comment. I tried to do the insert manually and it looks like Postgres is converting the 'now()' string into the now() function.
INSERT INTO book_rental (lastname, rental_date) VALUES ('Mueller', 'now()');
To involve your answer, am I right that this should be the correct code then?
const cs = new helpers.ColumnSet([
'lastname',
{
name: 'rental_date',
mod: ':raw',
def: 'now()'
}
], { table: { table: 'book_rental', schema: 'public' } })
Your code doesn't look right, for the following reasons:
You want to use now() without any condition, but the def value is only used when the property doesn't exist in the source object (see Column). The init callback is what should be used instead to guarantee the right value override.
You return now() as an escaped string, while the query needs it as a raw-text string.
First, let's declare a reusable Raw Text string, as per Custom Type Formatting:
const rawText = text => ({toPostgres: () => text, rawType: true});
Then you can define the column like this:
{
name: 'rental_date',
init: () => rawText('now()')
}
And make sure you are using the latest version of pg-promise (v7.2.1 as of this writing).
Or alternatively, you can declare it like this:
{
name: 'rental_date',
mod: ':raw', // same as mode: '^'
init: () => 'now()'
}
This syntax however will work in all versions of the library, and perhaps is even simpler to use ;)

Using a Formatter for the Currencies in SAPUI5

I want to build my own formattor for displaying the amount as it should in the different currencies.
One could guess I use this solution I already know:
<t:template>
<Text text="{
parts: [
{path: 'amount'},
{path: 'currency'}
],
type:'sap.ui.model.type.Currency',
formatOptions: {
currencyCode: false
}
}"
</t:template>
the problem with this solution is I already show the currency in a seperate column and if I go with this solution it looks pretty ugly....
so I tried this one:
<t:template>
<Text text="{parts: [
{path: 'amount'},
{path: 'currency'}
],
formatter : '.formatter.currency'}"
/>
</t:template>
and my formatter function looks like this:
currency: function(amount, currency) {
var change = [];
change.push(amount);
change.push(currency);
var sInternalType = "";
var amount1 = new sap.ui.model.type.Currency();
amount1.formatValue(change, sInternalType);
return amount1;
}
Here I would guess I do something completely wrong, as English is not my first language I would probably assume I didnt understood the API References right, as they is stated this:
formatValue(vValue, sInternalType): any
Format the given array containing amount and currency code to an output value of type string. Other internal types than 'string' are not supported by the Currency type. If an source format is has been defined for this type, the formatValue does also accept a string value as input, which will be parsed into an array using the source format. If aValues is not defined or null, null will be returned.
Parameters:
{array|string} vValue the array of values or string value to be formatted
{string} sInternalType the target type
Returns:
{any} the formatted output value
If it is your intention not to show the currency symbol or code because you already show it elsewhere, you could simply set showMeasure to false, e.g.:
<Text xmlns:core="sap.ui.core"
core:require="{ CurrencyType: 'sap/ui/model/type/Currency' }"
text="{
parts: [
'amount',
'currency'
],
type: 'CurrencyType',
formatOptions: {
showMeasure: false
}
}"
/>
Not showing the currency code/symbol is a feature of the standard Currency type. You don't need to extend it.
Note: In case of OData V4, require the type sap/ui/model/odata/type/Currency instead.
If you want to use an custom formatter, you can define it in this way:
currency: function(amount, currency) {
var oCurrency = new sap.ui.model.type.Currency({
showMeasure: false
});
return oCurrency.formatValue([amount,curreny], "string");
}
But I would recommend to use the solution from jpenninkhof for your use case

formatting bound property in javascript before it is displayed

I'm trying to format a JSON date to a JavaScript date to display it in a nice way. The original date comes from a JSON-object, which looks like this:
{
"name": "foo",
"num": "1",
"date": "\/Date(1367539200000)\/"
}
The place where the JSON elements should be displayed later is a SAPUI5 object header:
objectHeader = new sap.m.ObjectHeader({
title: "{/name}",
number: "{/num}",
attributes: [
new sap.m.ObjectAttribute({
text: "{/date}"
})
]
});
Since the JSON object is bound to the object header via
dataModel.setData(json)
objectHeader.setModel(dataModel)
the values are correctly substituted. But i want to have the date correctly formatted to a more readable format instead of seeing /Date(1367539200000)/ on my website. I tried with
new sap.m.ObjectAttribute({
text: new Date(parseInt("{/date}".substr(6))).toLocaleString('de');
})
But that failed with an 'Invalid Date'. What would be the right syntax to format the JSON date to a Javascript data object in a model binding?
You can use a formatter to do that for you. The advantage is that you can properly use databinding, so your controls will be updated automatically in case the model changes.
new sap.m.ObjectAttribute({
text: {
parts: [
{path: "/date"}
],
formatter: function(date){
//do whatever you want
return /* the value you want to have as result */;
}
}
})

Categories