All New Documentation!

clock November 28, 2014 19:19 by author htmltreegrid

We have released a ton of updates to the user guide. In addition, it is no longer a bulky doc file, but a searchable, organized, library of topics arranged in a natural progression. We also have it available for download in various different formats!

 

Although it is still a work in progress, it is much better than what we had before, so please feel free to share feedback, we are continuing to work on it and improve it for you!


Customizing Excel Output

clock November 27, 2014 07:35 by author htmltreegrid

Since each of the built in exporters simply inherits from the base Exporter class and implements its own "customized" way of exporting data, it is quite easy to actually plugin your own exporters. Let's take a look at how this is done.

 

First, we need to write our own custom exporter. This is actually quite simple. In this example, we will use an exporter that writes out OO XML (Open Office Excel Markup Language). This is XML that Microsoft Excel 2007 and up can open. This allows you to write out documents that are excel compatible, and allow you to add formatting, formulas and more. It saves an xml file, but this file can be opened in excel without the dreaded “The file you are trying to open is in a different format than specified by the file extension” message. The big upside of the excel 2007 exporter is that it lets you achieve a combination of no extension message, PLUS the ability to define styles and fonts. Finally, double clicking on this file will automatically open excel on systems that have Office 2007 and above installed

 

/**

 * Flexicious

 * Copyright 2011, Flexicious LLC

 */

(function(window)

{

    "use strict";

    var Excel2007Exporter, uiUtil = flexiciousNmsp.UIUtils, flxConstants = flexiciousNmsp.Constants;

    /**

     * Exports the grid in CSV format

     * @constructor

     * @namespace

     * @extends Exporter

     */

    Excel2007Exporter=function(){

 

        /**

         * Writes the header of the grid (columns) in csv format

         * @param grid

         * @return

            *

         */

 

        this.strTable = "";

 

 

 

 

    };

    flexiciousNmsp.Excel2007Exporter = Excel2007Exporter; //add to name space

    Excel2007Exporter.prototype = new flexiciousNmsp.Exporter(); //setup hierarchy

    Excel2007Exporter.prototype.typeName = Excel2007Exporter.typeName = 'Excel2007Exporter';//for quick inspection

    Excel2007Exporter.prototype.getClassNames=function(){

        return ["Excel2007Exporter","Exporter"];

    };

    Excel2007Exporter.prototype.writeHeader=function(grid){

 

        this.buildHeader(grid);

        return  "";

 

    };

    /**

     * @private

     * @param grid

     * @return

        *

     */

    Excel2007Exporter.prototype.buildHeader=function (grid){

 

        var colIndex=0;

 

        this.strTable += "<Row ss:StyleID='s68'>";

        while(colIndex++<this.nestDepth)

            this.strTable += "<Cell><Data ss:Type='String'></Data></Cell>";

        for(var i=0;i<grid.getExportableColumns().length;i++){

            var col=grid.getExportableColumns()[i];

            if(!this.isIncludedInExport(col))

                continue;

 

            this.strTable += "<Cell><Data ss:Type='String'>" +

                flexiciousNmsp.Exporter.getColumnHeader(col,colIndex) + "</Data></Cell>";

            colIndex++;

        }

        this.strTable += "</Row>";

 

    };

    Excel2007Exporter.prototype.uploadForEcho=function(body, exportOptions){

        var strWorkbook = "<?xml version='1.0' encoding='ISO-8859-1'?><?mso-application progid='Excel.Sheet'?>" +

            "<Workbook xmlns='urn:schemas-microsoft-com:office:spreadsheet' " +

            "xmlns:ss='urn:schemas-microsoft-com:office:spreadsheet' xmlns:x='urn:schemas-microsoft-com:office:excel' " +

            "xmlns:o='urn:schemas-microsoft-com:office:office' xmlns:html='http://www.w3.org/TR/REC-html40'>" +

            "<Styles>" +

            "<Style ss:Name='Normal' ss:ID='Default'>" +

            "<Alignment ss:Vertical='Bottom' />" +

            "<Borders />" +

            "<Font />" +

            "<Interior />" +

            "<NumberFormat />" +

            "<Protection />" +

            "</Style>" +

            "<Style ss:ID='s68'>" +

            "<Borders>" +

            "<Border ss:Position='Bottom' ss:LineStyle='Continuous' ss:Weight='2'/>" +

            "<Border ss:Position='Top' ss:LineStyle='Continuous' ss:Weight='2'/>" +

            "</Borders>" +

            "<Interior ss:Color='#4F81BD' ss:Pattern='Solid'/>" +

            "</Style>" +

            "</Styles>" +

            "<Worksheet ss:Name='Sheet1'>" +

            "<Table>";

        strWorkbook += this.strTable + "</Table></Worksheet></Workbook>";

        flexiciousNmsp.Exporter.prototype.uploadForEcho.apply(this,[strWorkbook, this.exportOptions]);

        this.strTable="";

    };

    /**

     * Writes an individual record in csv format

     * @param grid

     * @param record

     * @return

        *

     */

    Excel2007Exporter.prototype.writeRecord=function(grid, record){

 

        var colIndex=0;

        this.strTable += "<Row>";

        if(!this.reusePreviousLevelColumns){

            while(colIndex++<this.nestDepth)

                this.strTable += "<Cell><Data ss:Type='String'></Data></Cell>";

        }

        for(var i=0;i<grid.getExportableColumns().length;i++){

            var col=grid.getExportableColumns()[i];

            if(!this.isIncludedInExport(col))

                continue;

            var str = col.itemToLabel(record);

            this.strTable += "<Cell><Data ss:Type='String'>" + str + "</Data></Cell>";

        }

        this.strTable += "</Row>";

        return "";

 

    };

    /**

     * Writes the footer in CSV format

     * @param grid

     * @param dataProvider

     */

    Excel2007Exporter.prototype.writeFooter=function(grid, dataProvider){

 

        return "";

 

    };

    /**

     * Extension of the download file.

     * @return

        *

     */

    Excel2007Exporter.prototype.getExtension = function() {

        return "xml";

    };

    /**

     * Returns the content type so MS Excel launches

     * when the exporter is run.

     * @return

        *

     */

    Excel2007Exporter.prototype.getContentType = function() {

        return "text/xml"

    };

    /**

     * Name of the exporter

     * @return

        *

     */

    Excel2007Exporter.prototype.getName = function() {

        return "Excel 2007";

    };

}(window));

 

 

And the way you wire this up is :

 

 

 

                          grid.excelOptions.exporters = exporters = [new flexiciousNmsp.CsvExporter(), new flexiciousNmsp.DocExporter(),

                          new flexiciousNmsp.Excel2007Exporter()

                          ];

                         

 

Once you click on the excel export button, you should see:

 

Once you do the export using Excel 2007 exporter, you should see the below:

 

Here are the files required to run this example:

 

Excel2007Exporter.zip (2.76 kb)



XML Configuration vs API configuration

clock November 27, 2014 03:06 by author htmltreegrid

There are two distinct mechanisms you can use to build the grid. XML, and API. The XML is easier, less verbose and can be used to cleanly separate the markup of the grid from the logic associated with it (like event handlers and function callbacks we discuss elsewhere in this guide). 


The key to keep in mind however, is that the XML is ultimately passed into helper functions which then call the API methods and build out the grid. So the API is used in both cases, the XML is just a shorthand preprocessor for the API that makes it easier to configure the grid.


XML configuration 

When you define a grid, you pass in XML configuration for the grid. We have seen many examples of this so far, but lets look at a simple example here:

 

 

        $(document).ready(function () {

            var grid = new flexiciousNmsp.FlexDataGrid(document.getElementById("gridContainer"),

                    {

 

                        configuration: '<grid id="grid" enablePrint="true" enablePreferencePersistence="true" enableExport="true" forcePagerRow="true" pageSize="50" enableFilters="true" enableFooters="true" enablePaging="true">' +

                                    '               <level>' +

                                    '                      <columns>' +

                                    '                   <column type="checkbox"/>'+

                                    '                             <column dataField="id" headerText="ID" filterControl="DynamicFilterControl" footerLabel="Sum: " footerOperation="sum" footerOperationPrecision="2"/>' +

                                    '                             <column dataField="type" headerText="Type" filterControl="TextInput" filterOperation="Contains" />' +

                                    '                      </columns>' +

                                    '               </level>' +

                                    '         ' +

                                    '  </grid>',

                        dataProvider: [

                                              { "id": "5001", "type": "None", "active": true },

                                              { "id": "5002", "type": "Glazed", "active": true },

                                              { "id": "5005", "type": "Sugar", "active": true },

                                              { "id": "5007", "type": "Powdered Sugar", "active": false },

                                              { "id": "5006", "type": "Chocolate with Sprinkles", "active": true },

                                              { "id": "5003", "type": "Chocolate", "active": false },

                                              { "id": "5004", "type": "Maple", "active": true }

                                       ]

                    });

 

        });

 

As you see above, we basically pass in an XML string to the constructor of the FlexDataGrid class. One very frequent question comes up is, "What are the various attributes you can specify in XML"?

 

The answer is simple. All of them. Each and every property mentioned in the documentation can be specified via XML. This includes both properties explicitly exposed as public attributes (e.g. enablePrint, enableExport etc) , and some that are exposed via setters (e.g. setPagerRowHeight, setPagerVisible) . The XML parser is smart enough to figure out if there is a setter with the naming convention setXXXX and use it instead of a direct value set on the property. (This is in red because it often causes confusion among our customers). So pageSize="50" automatically translates to setPageSize(50), even if there is no property called pageSize on FlexDataGrid, but because there is a method named setPageSize. It is also smart enough to figure out that a value is a number passed in as a string, so it will do that conversion as well.

 

In addition to the above, the XML builder does a lot of preprocessing of the string values passed into it. These steps are described below.


1.     Any attribute that matches the name of an event. The XML parser assumes that any string passed in as the value for an event is a function call back and treats it as such. For example creationComplete="myCompanyNameSpace.onCreationComplete". So this needs to evaluate to a name spaced function. A full list of events is available here: http://htmltreegrid.com/docs/classes/flexiciousNmsp.FlexDataGrid.html (events tab)

2.     For any properties with the following suffix, we eval the passed in value. This means the value needs to evaluate to a namepace qualified function. e.g. filterRenderer="flexiciousNmsp.DynamicFilterControl":

1.     Function

2.     Renderer

3.     Editor

4.     Formatter

5.     DateRangeOptions

3.     For the following properties, we wrap the value in a ClassFactory:

1.     filterRenderer

2.     footerRenderer

3.     headerRenderer

4.     pagerRenderer

5.     itemRenderer

6.     nextLevelRenderer

7.     itemEditor

4.     If any value is passed in within curly braces {}, we assume that is a function call. Like {executeFunction(1,2)}. We will execute the executeFunction passing in 1 and 2, and return with the result. This is very rarely used.

5.     For any value you prefix with the word eval__, we evaluate it before it gets applied

6.     For any value you specify within square brackets [], we assume it is an array, and split the string by commas and convert it to an array.

7.     For any value that starts with 0x, we assume its a hex code and use it as such. This is used for colors.

8.     For any value that is composed solely of numbers, we parse it as such.

9.     Finally, after all this preprocessing is done, we check to see if there is a setter method specified for the property name at the target object level (FlexDataGrid, FlexDataGridColumnLevel, or FlexDataGridColumn). If so, we call the setter method with the preprocessed value. Else, we set a property with that name to the preprocessed value.

 

1.     For the grid tag, you can specify any of the properties listed here : http://htmltreegrid.com/docs/classes/flexiciousNmsp.FlexDataGrid.html

2.     For the level tag, you can specify any of the properties listed here : http://htmltreegrid.com/docs/classes/flexiciousNmsp.FlexDataGrid.html

3.     For the column tag, you can specify any of the properties listed here : http://htmltreegrid.com/docs/classes/flexiciousNmsp.FlexDataGridColumn.html

 

API configuration 

  The API method is basically what the XML configuration method uses. Many of our customers store their grid configuration in the backend. They then use it to build out the grid. Some of them choose to build out XML from their backend and then call the buildFromXML method on the grid. Others build out the grid using the API directly. This gives you more flexibility, but makes the code a lot more verbose. Let's take a quick look at the code required to build out a grid with no XML.

 

 

myCompanyNameSpace.DynamicColumns_grid_creationCompleteHandler=function(evt)

    {

 

        var grid=this;

        grid.setDataProvider(myCompanyNameSpace.FlexiciousMockGenerator.instance().getFlatOrgList());;

        grid.clearColumns();

 

    var col=myCompanyNameSpace.DynamicColumns_addColumn("id","Company ID");

    col.setColumnLockMode(flexiciousNmsp.FlexDataGridColumn.LOCK_MODE_LEFT)

    grid.addColumn(col);

    col=myCompanyNameSpace.DynamicColumns_addColumn("legalName","Company Name");

    col.setColumnLockMode(flexiciousNmsp.FlexDataGridColumn.LOCK_MODE_RIGHT)

    grid.addColumn(col);

    grid.addColumn(myCompanyNameSpace.DynamicColumns_addColumn("headquarterAddress.line1","Address Line 1"));

    grid.addColumn(myCompanyNameSpace.DynamicColumns_addColumn("headquarterAddress.line2","Address Line2"));

    grid.addColumn(myCompanyNameSpace.DynamicColumns_addCurrencyColumn("earningsPerShare","EPS"));

    grid.addColumn(myCompanyNameSpace.DynamicColumns_addColumn("headquarterAddress.line1","Address Line 1"));

    grid.addColumn(myCompanyNameSpace.DynamicColumns_addColumn("headquarterAddress.line2","Address Line2"));

    grid.addColumn(myCompanyNameSpace.DynamicColumns_addCurrencyColumn("earningsPerShare","EPS"));

    grid.addColumn(myCompanyNameSpace.DynamicColumns_addColumn("headquarterAddress.line1","Address Line 1"));

    grid.addColumn(myCompanyNameSpace.DynamicColumns_addColumn("headquarterAddress.line2","Address Line2"));

    grid.addColumn(myCompanyNameSpace.DynamicColumns_addCurrencyColumn("earningsPerShare","EPS"));

    grid.addColumn(myCompanyNameSpace.DynamicColumns_addColumn("headquarterAddress.line1","Address Line 1"));

    grid.addColumn(myCompanyNameSpace.DynamicColumns_addColumn("headquarterAddress.line2","Address Line2"));

    grid.addColumn(myCompanyNameSpace.DynamicColumns_addCurrencyColumn("earningsPerShare","EPS"));

    //grid.distributeColumnWidthsEqually();

    grid.reDraw();

 };

myCompanyNameSpace.DynamicColumnsCounter=0;

myCompanyNameSpace.DynamicColumns_addCurrencyColumn=function(dataField,headerText){

    var dgCol = myCompanyNameSpace.DynamicColumns_addColumn(dataField,headerText);

    dgCol.setLabelFunction(flexiciousNmsp.UIUtils.dataGridFormatCurrencyLabelFunction);

    dgCol.setStyle("textAlign","right");

    dgCol.setUniqueIdentifier(headerText+myCompanyNameSpace.DynamicColumnsCounter++);

    dgCol.footerOperation="average";

    dgCol.footerLabel="Avg: ";

    dgCol.footerAlign="right";

    dgCol.setStyle("paddingRight",15);

    dgCol.filterOperation="GreaterThan";

    dgCol.filterWaterMark = "Greater Than";

    return dgCol;

};

myCompanyNameSpace.DynamicColumns_counter=0;

myCompanyNameSpace.DynamicColumns_addColumn=function(dataField,headerText){

    var dgCol = new flexiciousNmsp.FlexDataGridColumn();

    dgCol.setDataField(dataField);

    dgCol.setHeaderText(headerText);

    //because columns are having the same header text, we need to provide unique identifiers.

    dgCol.setUniqueIdentifier(headerText+""+myCompanyNameSpace.DynamicColumns_counter++);

    dgCol.filterControl="TextInput";

    dgCol.filterOperation="BeginsWith";

    dgCol.filterWaterMark = "Begins With";

    return dgCol;

};

 

 

 

 

myCompanyNameSpace.SAMPLE_CONFIGS["DynamicColumns"]='<grid horizontalScrollPolicy="on"  id="grid" width="800" height="500" enablePrint="true" ' +

    'enablePreferencePersistence="true" generateColumns="false" '+

    '                                                      enableExport="true" enableCopy="true" enableFilters="true" enableFooters="true" enablePaging="true" ' +

    'preferencePersistenceKey="dynamicColumns"'+

    '                                                      on'+flexiciousNmsp.Constants.EVENT_CREATION_COMPLETE+'="myCompanyNameSpace.DynamicColumns_grid_creationCompleteHandler">'+

    '        '+

    '  </grid>';

 

 

 

So, in this example, we just use the XML to initialize the grid. We use API to generate the actual columns. For a running copy of this example, please refer to http://www.htmltreegrid.com/demo/prod_ext_treegrid.html?example=Dynamic%20Columns

 

We also have a more complicated grid, with column groups and inner levels. The code for this as well as a running example is available here:

http://www.htmltreegrid.com/demo/prod_ext_treegrid.html?example=Large%20Dynamic%20Grid