set data type when exporting to excel - grails

I'm using Grails 1.3.4 with the export 0.9.5 plug in.
I have a formatter that I use that sets the date format to 'YYYY-MM-DD' when exporting to excel. But this doesn't change the data type. The date is exported to Excel as a string/general data type.
def dateFormat = { domain, value ->
if(value instanceof Date){
return new java.text.SimpleDateFormat("yyyy-MM-dd").format(value)
}
return value
}
Map formatters = [ecd:dateFormat, completed:dateFormat, dateCreated:dateFormat, approvedDate:dateFormat, dpaECD:dateFormat]
exportService.export(params.format, response.outputStream,exportList, jobService.parseColNames(columns), labels, formatters, null)
Is there a way to export data and set the datatype of a column in excel so the user doesn't have to manually set the cell/column formatting to 'Date' every time after exporting?

Are you sure you want to use that plugin? It didn't work so well to me.
I've been using the JXL plugin for Grails for a while and it works perfectly.
It even has an option to write the Excel file to the response, so that the user can directly download the file using my REST service.
The link is: http://grails.org/plugin/jxl
Here is an example of how simple it is to create workbooks:
new ExcelBuilder().workbook('/path/to/test.xls') {
sheet('SheetName') {
cell(0,0,'Current Date')
cell(0,1,new Date())
}
}
Note that the cell() method has 3 parameters: column, row and value. This third parameter can be a number, string or date, and it formats it perfectly.
You can find more information here.

Related

Illegal sap.ui.model.odata.type.DateTimeOffset

Posting for prosperity. I had zero hits from google.
I'm writing a SAP Business One Web Client extension. I'm using the worklist template and have the b1s/v2/ Service Layer metadata (auto generated while setting up the template)
Running the sandbox version ("npm run start-local") it automatically generates fake data based on the metadata. My data included an edm.DateTimeOffset which is resolved by Fiori using the sap.ui.model.odata.type.DateTimeOffset model.
Here is an example response object from the test data proxy (all autogenerated)
{
DocEntry: 1,
U_CardCode: "U_CardCode_0",
U_CardName: "U_CardName_0",
U_DocCurrency: "U_DocCurrency_0",
U_DocTotal: "",
U_DueDate: "2017-04-13T14:50:39.000Z",
U_Status: "U_Status_0",
U_SupplierInvNo: "U_SupplierInvNo_0",
}
A perfectly normal U_DueDate value that, according to all the documentation I could find is an accepted format, doublely confirmed by the fact that it's a sap generated value.
This produces an error on screen
Illegal sap.ui.model.odata.type.DateTimeOffset
Adding a formatter doesn't work. If it's unable to parse the value then it won't pass it on to a formatter.
Turns out there is a way to override the expected type in the metadata. I couldn't find much documentation on it, but I changed the element from
text="{'U_DueDate'}" />
to
text="{
path: 'U_DueDate',
targetType: 'any',
formatter: '.formatter.date'
}" />
The date is now accepted as a string so I can use a custom formatter.
Here is the date function in the formetter:
date : function (sValue) {
if (!sValue) {
return "";
}
var date = new Date(sValue)
var asString = date.toLocaleDateString("en-GB")
return asString;
}
You don't have to hard code the localization, but my use case is that niche

Different text used of sorting and filtering

in a app, I use jQueryTablesorter, and the widget https://mottie.github.io/tablesorter/docs/example-widget-filter.html
I have two main features :
- filtering (the widget)
- sorting (default feature)
Both of these feature use textExtraction() function,
https://mottie.github.io/tablesorter/docs/#textextraction
My problem is the following :
for sorting, I would like to use computer form of a date, that is "2020-04-01"
for filtering, I would like to use human form (in French "1er avril 2020").
How can I deal with it ?
You might need to use a date library like sugar or date.js - check out this demo: https://mottie.github.io/tablesorter/docs/example-parsers-dates.html. What that library does is use the parser to convert the filter into a normalized date that will match with the date in the column. You would also need to add a filter-parsed class name to the column (ref).
I have found. I need to use a hook which modify the value parsed for filtering.
$.tablesorter.filter.types.start = function(config, data) {
data.exact = data.$cells[data.index];
data.exact = data.exact.innerText;
data.iExact = data.exact.toLowerCase();
return null;
}

Deserialize joda time from string in grails?

I had a LocalTime field (using Joda Time) in Grails domain class.
Class WorkDone{
LocalTime duration
}
Now I have altered this field to String (with Text constraint) so that it can support duration larger than 24 hrs.
String duration
The problem is there is already some data in database. And I want to sanitize that data through database migrations in Grails. I am using Postgres which saves LocalTime as Bytea (binary data).
When I call WorkDone.duration it returns me a String of the form:
\xaced0005737200176f72672e6a6f64612e74696d652e4c6f63616c54696d65fffff44abbf29def0200024a000c694c6f63616c4d696c6c69734c000b694368726f6e6f6c6f677974001a4c6f72672f6a6f64612f74696d652f4368726f6e6f6c6f67793b78700000000000000000737200276f72672e6a6f64612e74696d652e6368726f6e6f2e49534f4368726f6e6f6c6f67792453747562a9c811667137502703000078707372001f6f72672e6a6f64612e74696d652e4461746554696d655a6f6e652453747562a62f019a7c321ae30300007870770500035554437878
How can I extract time from this string?
Your data is scaped in bytea Hex format, (starts with \x) take a look at PostgreSQL docs
http://www.postgresql.org/docs/current/static/datatype-binary.html
You have to unescape it before read as ObjectInputStream ang get the LocalTime object, unescape it and then try again as Raphael suggest.
You should have done a data-migration before changing your Data-type to String.
Here is what you should do.
1. Change the Data-type of the field back to LocalTime.
2. Create a new field with String Date.
3. Write a script that would get all date in LocalTime and convert it to String and save it in new field.
4. Once you have your data migrated, delete the old field and then rename your new field to duration.
I ended up doing the following -
grailsChange{
change{
sql.eachRow("Select id,duration from work_done"){
def wdId = it.id
def durationObj = (LocalTime)(new ObjectInputStream(new ByteArrayInputStream(it.duration))).readObject()
durationObj = durationObj.toString().substring(0,8)
WorkDone.executeUpdate("update WorkDone wd set wd.duration=:newDuration" +
"where wd.id=:wdId",
[newDuration:durationObj ,wdId:wdId ])
}
}

Override Grails Error Messages to format Dates and Numbers

I have created a domain with a Double field. When the validation occurs it throws the error message with size value showing the number with commas. Following are the detials
Groovy Class
class Quote {
String content;
Double size;
static constraints = {
content(maxSize:1000, blank:false)
size(min: 0.00D, max:999.99D)
}
}
Value entered "11111", error obtained "Size 11,111 is exceeded the limit". I have added the property key/value pair in messages.properties.
Here, I would like to get the message back without the commas. My main aim is to take the key and format the message returned based on my requirements. I require this as I have other fields that need conversion. For example, a date is validated but when showing the error the Gregorian date needs to be converted to an Islamic date and shown to user.
Does anyone know if I can do something to make this work.
I have tried the solution provided in http://ishanf.tumblr.com/post/434379583/custom-property-editor-for-grails but this did not work.
I have also tried modifying the messages values, but this is not flexible in case of my date issue. Example, for a key value pair, instead of using {2} as a place holder I could use {2, date, mm/dd/yyyy}, but for Islamic dates I want to format and show things differently.
Also, please note I have created a separate key for default date formatting for my application.
Would appreciate the help.
In grails, the return of a constrain is an already translated string.
You can create a taglib to format that, or enhance the
Another option would be custom validators. A custom validator can return false or a key when failing.
For example in your domain class, to vaildate a field:
myDateField validator: {val, obj -> obj.myShinyDateValidatorMethod(val) }
private myShinyDateValidatorMethod() {
if (isNotValidDate(val) {
return [the_message_key, val.formatedAsYouWand]
}
}
and, in your properties file you have to have defined the key:
the_message_key=This date: {3} is not valid
The trick here is that in the return from the validator, first string is the key and the rest are parameters for that key, but grails already uses {0}, {1}, {2} placeholders for className, fieldName and value, and the first parameter that you pass will be used as {3} placeholder.
Hope this helps

Grails intercept form submit to modify params

Why do I need this:
I am working in a project which allows user to choose date in Nepali Bikram Sambat Date format (which is incompatible with Java and SQL's "DATE"). I did it by modifying org.codehaus.groovy.grails.plugins.web.taglib.FormTagLib class's datePicker tagLibrary. And modifying the scaffolding template list.gsp.
My problem :
When user chooses Nepali date from browser and submits the form, I want to read the [day, month, year] and convert it into Java Date object and save into database. (The date will be converted back to Nepali Bikram Sambat when it will be displayed into view).
I tried to print the params in the controller but all the params are already mapped/wrapped into corresponding objects - along with my Nepali Date. So I get sysout of Java's Date from code below :
println params.date
I am wondering how can I intercept the form submit request and modify the date params into English date. I see one solution - using JavaScript ( and rewrite my conversion code into JavaScript) before form submit to convert the params. And just wanted to confirm is there a easy way - like interceptor/filter etc.
Well, assuming you are using input fields with the standard grails datepicker, you should have in your params map the fields being passed, just with a different name. Write a "println params" in your action receiving the request and look for the names of the fields of the datepicker. It was supposed to bring you something like (name of the datepicker field, say * + _year, for year, * + _month for month and so on).
You can create a CustomEditorRegistrar that changes the format from your date before it's wrapped into objects. Like this:
public class CustomDateEditorRegister implements PropertyEditorRegistrar {
public void registerCustomEditors(PropertyEditorRegistry registry) {
String dateFormat = 'dd/MM/yyyy'
registry.registerCustomEditor(Date, new CustomDateEditor(new SimpleDateFormat(dateFormat), true))
}
}
And your Date editor could be something like:
class CustomSimpleDateEditor extends CustomDateEditor {
public CustomSimpleDateEditor(SimpleDateFormat formatter, boolean allowEmpty) {
super(formatter, allowEmpty);
}
public String getAsText() {
Date date = (Date)getValue();
try {
String dateText = new SimpleDateFormat("dd/MM/yyyy").parse(date);
return dateText;
}
catch(Exception e) {
e.printStackTrace();
return "";
}
}
}
Your params.date will be converted before it's passed to objects and saved to the db. Anyway, here's a good link explaining it.
Hope it helps!

Resources