Hi,
I am using a custom fetch operation for a ListGrid where the "select" and "group" clause are customized by passing them with parameters. The way data are grouped and summed are configured by the user, that's why select/group clause are dynamically formed.
This work great for populating the grid, however when exporting data to Excel, a non customized query is generated, not the same as the one that populated the grid (not seeing the group clause), which produces a Excel file content not corresponding to the data showed. Any idea on how to have the (server side) export function using the SQL that was used to produce the grid ?
Many thanks, Ben.
Datasource with custom fetch:
DMI to provide the parameters to the fetch query (only dynamicSelectClause and dynamicGroupClause are used):
The ListGrid with the export method (export to excel) :
External code that prepares the info for the dynamic grid and builds it and launches the fetch
I am using a custom fetch operation for a ListGrid where the "select" and "group" clause are customized by passing them with parameters. The way data are grouped and summed are configured by the user, that's why select/group clause are dynamically formed.
This work great for populating the grid, however when exporting data to Excel, a non customized query is generated, not the same as the one that populated the grid (not seeing the group clause), which produces a Excel file content not corresponding to the data showed. Any idea on how to have the (server side) export function using the SQL that was used to produce the grid ?
Many thanks, Ben.
Datasource with custom fetch:
Code:
<DataSource
ID="ui_grid_times"
serverType="sql"
tableName="ui_grid_times"
>
<fields>
<field name="id" title="Id" type="sequence" primaryKey="true" hidden="true"/>
<field name="workCode" title="Work code" type="text" />
<field name="id_workphase_type" title="Category Id" type="integer" hidden="true"/>
<field name="id_record" title="Record Id" type="integer" hidden="true"/>
<field name="id_workphase" title="Phase Id" type="integer" hidden="true"/>
<field name="id_workpackage" title="Phackage Id" type="integer" hidden="true"/>
<field name="id_worktask" title="Task Id" type="integer" hidden="true"/>
<field name="id_team" title="Team Id" type="integer" hidden="true"/>
<field name="id_person" title="Person Id" type="integer" hidden="true"/>
<field name="id_workrate" title="Rate Id" type="integer" hidden="true"/>
<field name="date_from_day" title="Date" type="date" />
<field name="date_from_week" title="Week" type="date" />
<field name="date_from_month" title="Month" type="date" />
<field name="date_from_year" title="Year" type="date" />
<field name="_hours" title="Worked hours" type="double" />
<field name="_hours_billable" title="Billable hours" type="double" />
<field name="_mandays" title="Worked MDs" type="double" />
<field name="_mandays_billable" title="Billable MDs" type="double" />
<field name="_amount_billable" title="Amount" type="double" />
<field name="is_billable" title="B" type="boolean" sqlStorageStrategy="integer"/>
<field name="is_validated" title="V" type="boolean" sqlStorageStrategy="integer"/>
<field name="comment" title="Comment" type="text" />
<field name="personCode" title="Person" type="text" />
<field name="personName_full" title="Person name" type="text" />
<field name="personSortkey" title="Sortkey" type="text" />
<field name="teamName" title="Team" type="text" />
<field name="teamSortkey" title="Team sortkey" type="integer" />
<field name="workrateName" title="Rate" type="text" />
<field name="workrateRate" title="Hourly" type="double"/>
<field name="currencySymbolInput" title="¤" type="text"/>
<field name="currencySymbolOutput" title="¤" type="text"/>
<field name="worktaskName" title="Task" type="text"/>
<field name="worktaskSortkey" title="Task sortkey" type="integer" />
<field name="workpackageName" title="Package" type="text"/>
<field name="workpackageSortkey" title="Package sortkey" type="integer" />
<field name="workphaseName" title="Phase" type="text"/>
<field name="workphaseSortkey" title="Phase sortkey" type="integer" />
<field name="workphaseType" title="Category" type="text"/>
<field name="workphaseTypeSortkey" title="Category sortkey" type="text"/>
<field name="recordName" title="Record name" type="text" />
</fields>
<operationBindings>
<operationBinding operationType="fetch" operationId="dynamicFetch">
<serverObject lookupStyle="new" className="com.nside.moon.server.dmi.DynamicSQLDMI" />
<selectClause>
$rawValue.dynamicSelectClause
</selectClause>
<tableClause>
$defaultTableClause
</tableClause>
<whereClause>
$defaultWhereClause
</whereClause>
<groupClause>
$rawValue.dynamicGroupClause
</groupClause>
<orderClause>
$defaultOrderClause
</orderClause>
</operationBinding>
</operationBindings>
</DataSource>Code:
package com.nside.moon.server.dmi;
import javax.servlet.http.HttpServletRequest;
import com.isomorphic.datasource.DSRequest;
import com.isomorphic.datasource.DSResponse;
public class DynamicSQLDMI {
public DSResponse fetch(DSRequest dsRequest) {
DSResponse dsResponse = new DSResponse();
HttpServletRequest request = dsRequest.getHttpServletRequest();
String dynamicSelectClause = (String)request.getParameter("dynamicSelectClause");
if (dynamicSelectClause!=null) dsRequest.addToTemplateContext("dynamicSelectClause",dynamicSelectClause);
String dynamicTableClause = (String)request.getParameter("dynamicTableClause");
if (dynamicTableClause!=null) dsRequest.addToTemplateContext("dynamicTableClause",dynamicTableClause);
String dynamicWhereClause = (String)request.getParameter("dynamicWhereClause");
if (dynamicWhereClause!=null) dsRequest.addToTemplateContext("dynamicWhereClause",dynamicWhereClause);
String dynamicOrderClause = (String)request.getParameter("dynamicOrderClause");
if (dynamicOrderClause!=null) dsRequest.addToTemplateContext("dynamicOrderClause",dynamicOrderClause);
String dynamicGroupClause = (String)request.getParameter("dynamicGroupClause");
if (dynamicGroupClause!=null) dsRequest.addToTemplateContext("dynamicGroupClause",dynamicGroupClause);
try {
dsResponse = dsRequest.execute();
} catch (Exception e) {
e.printStackTrace();
}
return dsResponse;
}
}The ListGrid with the export method (export to excel) :
Code:
package com.nside.moon.client_desktop.grids;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashSet;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.i18n.client.NumberFormat;
import com.nside.moon.client_desktop.views.ViewTimesQuery;
import com.smartgwt.client.data.DSRequest;
import com.smartgwt.client.data.Record;
import com.smartgwt.client.data.SortSpecifier;
import com.smartgwt.client.types.ExportDisplay;
import com.smartgwt.client.types.ExportFormat;
import com.smartgwt.client.types.FetchMode;
import com.smartgwt.client.types.GroupStartOpen;
import com.smartgwt.client.types.SortDirection;
import com.smartgwt.client.widgets.grid.GroupValueFunction;
import com.smartgwt.client.widgets.grid.ListGrid;
import com.smartgwt.client.widgets.grid.ListGridField;
import com.smartgwt.client.widgets.grid.ListGridRecord;
import com.smartgwt.client.widgets.grid.SummaryFunction;
public class GridTimes extends Grid {
private LinkedHashSet<String> allFields;
private LinkedHashSet<String> visibleFieldNames;
private LinkedHashSet<String> groupFieldNames;
private LinkedHashSet<String> sortkeyFieldNames;
private ArrayList<ListGridField> fields;
private HashMap<String,String> requestParameters;
public GridTimes(ViewTimesQuery view,LinkedHashSet<String> allFields,LinkedHashSet<String> visibleFieldNames,LinkedHashSet<String> groupFieldNames,LinkedHashSet<String> sortkeyFieldNames,HashMap<String,String> requestParameters) {
super(view,"ui_grid_times",null,0,"*");
this.allFields = allFields;
this.visibleFieldNames = visibleFieldNames;
this.groupFieldNames = groupFieldNames;
this.sortkeyFieldNames = sortkeyFieldNames;
this.requestParameters = requestParameters;
setFetchOperation("dynamicFetch");
setDataFetchMode(FetchMode.PAGED);
setShowAllRecords(false);
fields = new ArrayList<ListGridField>();
build();
}
private void build(){
addField("id","80",true);
addField("id_workphase_type","80",true);
addField("id_record","80",true);
addField("id_workphase","80",true);
addField("id_workpackage","80",true);
addField("id_worktask","80",true);
addField("id_team","80",true);
addField("id_person","80",true);
addField("id_workrate","80",true);
addFieldNumber("workphaseTypeSortkey","80",true,Factory.FORMAT_DOUBLE0);
addFieldNumber("workphaseSortkey","80",true,Factory.FORMAT_DOUBLE0);
addFieldNumber("worktaskSortkey","80",true,Factory.FORMAT_DOUBLE0);
addFieldNumber("teamSortkey","80",true,Factory.FORMAT_DOUBLE0);
addFieldDate("date_from_year","60",false,Factory.FORMAT_DATE_yyyy);
addFieldDate("date_from_month","60",false,Factory.FORMAT_DATE_MMMyy);
addFieldDate("date_from_week","60",false,Factory.FORMAT_DATE_ddMMyy);
addFieldDate("date_from_day","60",false,Factory.FORMAT_DATE_ddMMyy);
addField("personCode","65",false);
addField("personName_full","150",false);
addField("teamName","120",false);
addField("recordName","300",false);
addField("workphaseType","120",false);
addField("workphaseName","150",false);
addField("workpackageName","250",false);
addFieldNumber("workpackageSortkey","80",true,Factory.FORMAT_DOUBLE0);
addField("worktaskName","250",false);
addCoreFieldNumber("_hours","80",Factory.FORMAT_DOUBLE2);
addCoreFieldNumber("_hours_billable","80",Factory.FORMAT_DOUBLE2);
addCoreFieldNumber("_mandays","80",Factory.FORMAT_DOUBLE2);
addCoreFieldNumber("_mandays_billable","80",Factory.FORMAT_DOUBLE2);
addCoreFieldNumber("_amount_billable","80",Factory.FORMAT_DOUBLE2);
addCoreField("currencySymbolOutput","25");
addField("is_billable","30",false);
addField("is_validated","30",false);
addField("workrateName","70",false);
addFieldNumber("workrateRate","50",false,Factory.FORMAT_DOUBLE2);
addField("currencySymbolInput","25",false);
addField("comment","400",false);
ListGridField field = Factory.makeField("filler","*",false,false);
field.setTitle(" ");
fields.add(field);
setAutoFitExpandField("filler");
setFields(fields.toArray(new ListGridField[fields.size()]));
setShowGroupSummary(true);
setShowGroupSummaryInHeader(false);
setShowGridSummary(true);
setGroupStartOpen(GroupStartOpen.ALL);
setGroupByField(groupFieldNames.toArray(new String[groupFieldNames.size()]));
SortSpecifier[] sortSpecifiers = new SortSpecifier[sortkeyFieldNames.size()];
int i = 0;
for (String sortkeyFieldName:sortkeyFieldNames){
sortSpecifiers[i++] = new SortSpecifier(sortkeyFieldName,SortDirection.ASCENDING);
}
setSort(sortSpecifiers);
}
private void addCoreField(final String name,String width){
ListGridField field = Factory.makeField(name,width,false,false);
field.setShowGroupSummary(true);
field.setShowGridSummary(true);
setSummaryCustom(field,new SummaryFunction(){
public Object getSummaryValue(Record[] records, ListGridField field) {
String value = "";
if (records.length>0){
value = records[0].getAttribute(field.getName());
}
return value;
}
});
fields.add(field);
}
private void addCoreFieldNumber(String name,String width,NumberFormat format){
ListGridField field = Factory.makeFieldNumber(name,width,false,false,format);
field.setShowGroupSummary(true);
field.setShowGridSummary(true);
fields.add(field);
}
private void addField(String name,String width,boolean hidden){
if (allFields.contains(name)){
ListGridField field = Factory.makeField(name,width,hidden||!visibleFieldNames.contains(name),false);
field.setShowGroupSummary(false);
field.setShowGridSummary(false);
fields.add(field);
}
}
private void addFieldNumber(String name,String width,boolean hidden,NumberFormat format){
if (allFields.contains(name)){
ListGridField field = Factory.makeFieldNumber(name,width,hidden||!visibleFieldNames.contains(name),false,format);
field.setShowGroupSummary(false);
field.setShowGridSummary(false);
fields.add(field);
}
}
private void addFieldDate(String name,String width,boolean hidden,final DateTimeFormat format){
if (allFields.contains(name)){
ListGridField field = Factory.makeFieldDate(name,width,hidden||!visibleFieldNames.contains(name),false,format);
field.setShowGroupSummary(false);
field.setShowGridSummary(false);
field.setGroupValueFunction(new GroupValueFunction(){
public Object getGroupValue(Object value, ListGridRecord record, ListGridField field, String fieldName, ListGrid grid) {
Date date = (Date) value;
return format.format(date);
}
});
fields.add(field);
}
}
public void autoFetch(){
}
protected String getCellCSSText(ListGridRecord record, int rowNum, int colNum) {
String name = getFieldName(colNum);
if (name.equals("personCode")||name.equals("date_from_day")||name.equals("date_from_week")||name.equals("date_from_month")||name.equals("date_from_year")) {
return "font-family:courier;";
} else
return super.getCellCSSText(record, rowNum, colNum);
}
public void export(){
// exportAs is either XML or CSV, which we can do with requestProperties
DSRequest dsRequestProperties = new DSRequest();
dsRequestProperties.setExportAs(ExportFormat.OOXML);
dsRequestProperties.setExportDisplay(ExportDisplay.DOWNLOAD);
dsRequestProperties.setExportFilename("MoonTimeQueryExport.xlsx");
dsRequestProperties.setParams(requestParameters);
exportData(dsRequestProperties);
}External code that prepares the info for the dynamic grid and builds it and launches the fetch
Code:
public void refresh() {
int currencyId = getScreen().getSelectedId(true);
if (!(currencyId>0)){
SC.warn("You must select a currency");
} else {
DBLogger.log(DBLogger.OPERATION_TIME_QUERY_LOAD,null,null,null);
if (gridTimes!=null) {
layoutGrid.removeMember(gridTimes);
gridTimes.destroy();
}
String timeField = selectTime.getValueAsString();
LinkedHashSet<String> allFields = new LinkedHashSet<String>();
LinkedHashSet<String> visibleFields = new LinkedHashSet<String>();
LinkedHashSet<String> groupFields = new LinkedHashSet<String>();
LinkedHashSet<String> sortkeyFields = new LinkedHashSet<String>();
String groupField = selectGroup.getValueAsString();
String subgroupField = selectSubgroup.getValueAsString();
if (groupField!=null) {
if (groupField.equals("time")) groupField = timeField;
groupFields.add(groupField);
}
if (subgroupField!=null) {
if (subgroupField.equals("time")) subgroupField = timeField;
groupFields.add(subgroupField);
}
String groupSortkey = null;
String subgroupSortkey = null;
ArrayList<String> otherSortkeys = new ArrayList<String>();
for (Record r:fieldList.toArray()){
String fieldName = r.getAttribute("name");
String keyFieldName = r.getAttribute("keyFieldName");
String sortkeyFieldName = r.getAttribute("sortkeyFieldName");
if (fieldName.equals("time")) fieldName = timeField;
if (sortkeyFieldName!=null&&sortkeyFieldName.equals("time")) sortkeyFieldName = timeField;
boolean addField = false;
boolean isSelected = gridSelectFields.isSelected((ListGridRecord)r);
if (groupField!=null&&fieldName.equals(groupField)) {
addField = true;
groupSortkey = sortkeyFieldName;
}
if (subgroupField!=null&&fieldName.equals(subgroupField)) {
addField = true;
subgroupSortkey = r.getAttribute("sortkeyFieldName");
}
if (!addField&&isSelected) {
addField = true;
if (otherSortkeys.size()<3) otherSortkeys.add(sortkeyFieldName);
}
if (addField){
allFields.add(fieldName);
if (isSelected) visibleFields.add(fieldName);
if (keyFieldName!=null) allFields.add(keyFieldName);
if (sortkeyFieldName!=null) allFields.add(sortkeyFieldName);
}
}
if (!checkboxAggregate.getValueAsBoolean()) allFields.add("id");
if (groupSortkey!=null) sortkeyFields.add(groupSortkey);
if (subgroupSortkey!=null) sortkeyFields.add(subgroupSortkey);
for (String sortkey:otherSortkeys){
sortkeyFields.add(sortkey);
}
final AdvancedCriteria c = new AdvancedCriteria();
c.addCriteria(new AdvancedCriteria("date_from_day",OperatorId.GREATER_OR_EQUAL,dateFrom.getValueAsDate()));
c.addCriteria(new AdvancedCriteria("date_from_day",OperatorId.LESS_OR_EQUAL,dateTo.getValueAsDate()));
if (checkboxValidated.getValueAsBoolean()){
c.addCriteria(new AdvancedCriteria("is_validated",OperatorId.EQUALS,true));
}
String ids;
if (gridSelectRecords!=null){
ids = gridSelectRecords.getSelectedIds();
String workCode = gridSelectRecords.getWorkCode();
if (ids!=null&&ids.length()>0) {
c.addCriteria(new AdvancedCriteria("workCode",OperatorId.EQUALS,workCode));
c.addCriteria(new AdvancedCriteria("id_record",OperatorId.IN_SET,ids.split(",")));
}
}
ids = gridSelectPersons.getSelectedIds();
if (ids!=null&&ids.length()>0) c.addCriteria(new AdvancedCriteria("id_person",OperatorId.IN_SET,ids.split(",")));
ids = gridSelectCategories.getSelectedIds();
if (ids!=null&&ids.length()>0) c.addCriteria(new AdvancedCriteria("id_workphase_type",OperatorId.IN_SET,ids.split(",")));
String fieldList = "";
boolean first = true;
for (String s:allFields){
fieldList += (first?"":",") + s;
first = false;
}
final HashMap<String,String> requestParameters = new HashMap<String,String>();
requestParameters.put("dynamicSelectClause",fieldList + ",SUM(_hours) AS _hours,SUM(_hours_billable) AS _hours_billable,SUM(_mandays) AS _mandays,SUM(_mandays_billable) AS _mandays_billable,SUM(_amount_billable) AS _amount_billable,MAX(currencySymbolOutput) AS currencySymbolOutput");
requestParameters.put("dynamicGroupClause",fieldList);
gridTimes = new GridTimes(this,allFields,visibleFields,groupFields,sortkeyFields,requestParameters);
layoutGrid.addMember(gridTimes);
updateCurrencyParameter(currencyId,new DSCallback(){
public void execute(DSResponse response, Object rawData, DSRequest request) {
DSRequest r = new DSRequest();
r.setParams(requestParameters);
gridTimes.fetchData(c,null,r);
}
});
}
}