Gridx in XPages – 27: Exporting to Excel

No application would be complete without the ability to export all of the data to Excel. </sarcasm> In reality, this request still comes up a lot, so it’s a very handy feature that Gridx provides the ability to export the grid data. In this post, I’ll show what the exporter module provides, the easy way to send the data in CSV format, and how to tie the process together.

Gridx Series

Gridx in XPages — Entire Series

High Level Steps to Export

The Export module doesn’t really do the whole job for you; what it really does is provide you the data in CSV format and then you have to finish the job.

Here are the high-level steps that are required:

  1. Include the Export module in the require statement
  2. Write two functions to get the data to export, then open the page to write it out
  3. Use a JSON RPC method to put that data into a scope variable
  4. Open an XAgent page to actually write out the data
  5. Add a button to call the JavaScript function to run the whole process

1. Including the Export Module

This module doesn’t get added to the grid, but it needs to be available in order to call from JavaScript.

Here’s the require statement from my sample page:

require([ 
  &quot;gridx/Grid&quot;, 
  &quot;dojo/store/Memory&quot;,
  &quot;gridx/core/model/cache/Sync&quot;, 
  &quot;gridx/modules/ColumnResizer&quot;,
  &quot;gridx/modules/NestedSort&quot;, 
  &quot;gridx/modules/Filter&quot;,
  &quot;gridx/modules/filter/FilterBar&quot;,
  &quot;gridx/modules/filter/QuickFilter&quot;,
  &quot;gridx/modules/HiddenColumns&quot;, 
  &quot;gridx/modules/Persist&quot;,
  &quot;gridx/modules/HeaderMenu&quot;,
  &quot;gridx/support/exporter/toCSV&quot;,
  &quot;gridx/modules/VirtualVScroller&quot;,
  &quot;gridx/modules/extendedSelect/Column&quot;,
  &quot;gridx/modules/move/Column&quot;,
  &quot;gridx/modules/dnd/Column&quot;,
  &quot;dojo/date/locale&quot;,
  &quot;dojo/currency&quot;,
  &quot;gridx/modules/Bar&quot;,
  &quot;dijit/Toolbar&quot;,
  &quot;dijit/form/Button&quot;, 
  &quot;dojo/domReady!&quot; 
  ], 
  function(Grid, MemoryStore, Cache, ColumnResizer, NestedSort, Filter, FilterBar, QuickFilter, HiddenColumns, Persist, HeaderMenu, CSV_Export, VirtualVScroller, colSelect, colMove, colDnD, locale, currency, Bar, Toolbar, Button) {    

2. Functions to Retrieve Data and Write it Out

The first function uses the export module to prepare the data for export.

Note: it needs to be within the require() statement so the CSV_Export is within scope.

getGridData = function() { 
  var args = {
    selectedOnly: false,
    omitHeader: false,
    useStoreData: false,
    separator: ','
  };

  CSV_Export(grid, args).then(exportData);
};	

exportData() is a callback to run once the data is ready. (You can also pass in callbacks to run on error and as the export progresses, if you want to update a progress meter).

This function calls a JSON RPC method to put the data into a scope variable. When done, it opens a new window with an XAgent page to actually write out the data.

function exportData(data) {
    rpcExport.exportData(data).addCallback(function() {
    // Open the XAgent page to write out the data	
    window.open('ExportGridx.xsp');	
  })

3.JSON RPC method to put that data into a scope variable

JSON RPC ties everything together and coordinates the timing. When I first worked on exporting with the dojo EnhancedGrid, this was a sticking point, because there was sometimes a timing issue — the data wasn’t ready before the XAgent was opened, so I tried a few workarounds that weren’t always reliable.

With this method, the client-side JavaScript function passes in the data to export and the RPC method puts it into a scope variable so it can be picked up by the XAgent page. (Note: This control is available in the extension library, 8.5.3 Upgrade Pack 1, or Notes 9.)

&lt;xe:jsonRpcService id=&quot;jsonRpcService1&quot; serviceName=&quot;rpcExport&quot;&gt;
  &lt;xe:this.methods&gt;
    &lt;xe:remoteMethod name=&quot;exportData&quot;
      script=&quot;sessionScope.gridxExport = csvData;&quot;&gt;
      &lt;xe:this.arguments&gt;
        &lt;xe:remoteMethodArg name=&quot;csvData&quot; type=&quot;string&quot;&gt;&lt;/xe:remoteMethodArg&gt;
      &lt;/xe:this.arguments&gt;
    &lt;/xe:remoteMethod&gt;
  &lt;/xe:this.methods&gt;
&lt;/xe:jsonRpcService&gt;

On a callback that runs when the RPC method is done, the exportData() function opens the XAgent page. This makes the timing of the whole process flow smoothly.

(Note: if you’re not familiar with JSON RPC and you’ll be at ConnectED, check out my session with Paul Calhoun [BP105], where we’ll dig into the benfits of it.)

4. XAgent to Export Data

Once the data is ready, the code opens a separate window for an XAgent page. The page has rendered set to false and it runs code on afterRenderResponse to write out the data from the scope variable.

If you have Excel installed, you will have the opportunity to open the file directly in Excel. (You can also save it to the machine.)
Gridx 27 - B

Here is the entire source of my XAgent page:

&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;xp:view xmlns:xp=&quot;http://www.ibm.com/xsp/core&quot; rendered=&quot;false&quot;&gt;

	&lt;xp:this.afterRenderResponse&gt;&lt;![CDATA[#{javascript:
// This XAgent just writes out the CSV data from the grid that is stored in a scope variable.
var exCon = facesContext.getExternalContext();
var writer = facesContext.getResponseWriter();
var response = exCon.getResponse();
response.setContentType(&quot;text/csv;charset=utf-8&quot;);
 
response.setHeader(&quot;Cache-Control&quot;, &quot;no-cache&quot;);
response.setHeader(&quot;Content-Disposition&quot;, &quot;attachment; filename=GridExport.csv&quot;);
writer.write(sessionScope.gridxExport);
writer.endDocument();}
]]&gt;
	&lt;/xp:this.afterRenderResponse&gt;
&lt;/xp:view&gt;

5. Button to Run the Export

Finally, we just need a button to call the exportGridData() function.

&lt;xp:button value=&quot;Export&quot; id=&quot;button1&quot;&gt;
  &lt;xp:eventHandler event=&quot;onclick&quot; submit=&quot;false&quot;&gt;
    &lt;xp:this.script&gt;&lt;![CDATA[getGridData();]]&gt;&lt;/xp:this.script&gt;
  &lt;/xp:eventHandler&gt;
&lt;/xp:button&gt;

Here’s an example of grid data:

Gridx 27 - A

Here’s the default layout in Excel after exporting:
Gridx 27 - C

Enhancements

In its current form, it will export everything visible in the grid. (If the grid is filtered, it will export the results of the filter.)

There are several things you can do to enhance the process:

  • Export selected rows only
  • Put the button to export the data into a toolbar
  • Add formatters to modify the data as it’s exported
  • Use Apache POI to write a proper Excel spreadsheet
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: