<?xml version="1.0" encoding="UTF-8"?>

<sample>

  <name>xlsdatasource</name>
  <title>XLS Data Source Sample</title>
  <description>Shows how the XLS data source implementation could be used to fill reports.</description>

  <mainFeature ref="xlsdatasource"/>
  <secondaryFeature name="datasources" sample="datasource" title="Data Sources"/>
  
  <!-- xlsdatasource -->
  
  <feature name="xlsdatasource" title="XLS Data Source">
    <description>
How to fill a report using data from an XLS file.
    </description>
    <since>3.6.1</since>
    <documentedBy>
      <author>
    	<name>Sanda Zaharia</name>
    	<email>shertage@users.sourceforge.net</email>
      </author>
    </documentedBy>
  	<otherSample ref="datasource"/>
    <content>
<b>XLS Data Sources</b>
<br/>
<br/>
Report filling is one of the basic operations during the report generation. After the report compilation, 
report data are read from the report data source, and/or calculated from report expressions, 
and the generated report sections are filled one by one. 
<br/>
Data sources are very useful when data come as a set of structured records, either extracted from a 
relational database, or loaded from specific files. In order to become more familiar with data source 
objects please consult the <a href="../datasources.html#datasources">Data Sources</a> section.
<br/>
When reporting data is stored in Microsoft Excel files (XLS), the 
<api href="net/sf/jasperreports/engine/data/ExcelDataSource.html">ExcelDataSource</api> data source 
implementation can be used to read it and feed it into the report. 
<br/>
The XLS data source uses the <code>Apache POI</code> library to load the XLS workbook and read 
from it. Instances of this data source can be created by supplying either an in-memory 
workbook object, a file, or an input stream to read the data from. 
<br/>
Report-field mapping for this data source implementation is very similar to the CSV data 
source field-mapping explained in the <a href="../csvdatasource">CSV Data Source</a> sample. It works on the assumption that 
the workbook contains data in a tabular form (rows are records and columns contain 
report-field values). The main difference is that one can specify a given sheet to be used as single sheet data source using the 
<api href="net/sf/jasperreports/engine/query/JRXlsQueryExecuterFactory.html#XLS_SHEET_SELECTION">XLS_SHEET_SELECTION</api> parameter 
or report property.
<br/>
<br/>
<b>XLS Data Source Example</b>
<br/>
<br/>
In our example data records are stored in the /data/XlsDataSource.data.xls file. It contains the same 
records as in the <a href="../csvdatasource">CSV Data Source</a> sample, but the <code>city</code> and 
<code>id</code> columns are separated by an empty column (ie. records contain in fact 6 fields, but 
the second field in each record is always empty).
<br/>
There are no column headers in the .xls file. This means 
that column names are set independently, as shown in the 
<code>getDataSource1()</code> method in the /src/XlsDataSourceApp.java file: 
<pre><![CDATA[
  private static ExcelDataSource getDataSource1() throws JRException
  {
    ExcelDataSource ds;
    try
    {
      String[] columnNames = new String[]{"city", "id", "name", "address", "state"};
      int[] columnIndexes = new int[]{0, 2, 3, 4, 5};
      ds = new ExcelDataSource(JRLoader.getLocationInputStream("data/XlsDataSource.data.xls"));
      ds.setColumnNames(columnNames, columnIndexes);
      
      //uncomment the below line to see how sheet selection works
//    ds.setSheetSelection("xlsdatasource2");
    }
    catch (IOException e)
    {
      throw new JRException(e);
    }

    return ds;
  }
]]></pre>
Column names are the same as in the CSV example: <code>city</code>, <code>id</code>, <code>name</code>, <code>address</code> and <code>state</code>. 
But they are associated with particular column indexes: <code>0, 2, 3, 4, 5</code>. The empty column's index (1) is skipped, and doing so, 
the empty content of the second column will be neglected.
<br/>
The <code>ExcelDataSource</code> object prepared above is passed to the engine at fill time (see again the /src/XlsDataSourceApp.java file):
<pre><![CDATA[
  public void fill1() throws JRException
  {
    long start = System.currentTimeMillis();
    //Preparing parameters
    Map parameters = new HashMap();
    parameters.put("ReportTitle", "Address Report");
    parameters.put("DataFile", "XlsDataSource.data.xls - XLS data source");
    Set states = new HashSet();
    states.add("Active");
    states.add("Trial");
    parameters.put("IncludedStates", states);

    JasperFillManager.fillReportToFile("build/reports/XlsDataSourceReport.jasper", parameters, getDataSource1());
    System.err.println("Filling time : " + (System.currentTimeMillis() - start));
  }
]]></pre>
The <code>IncludedStates</code> parameter defined above is used for data filtering. Only records with <code>Active</code> 
or <code>Trial</code> states will be taken into account:
<br/>
<br/>
<code>
&#160;&#160;&lt;parameter name="IncludedStates" class="java.util.Set"/&gt;
<br/>
<br/>
&#160;&#160;...
<br/>
<br/>
&#160;&#160;&lt;filterExpression&gt;&lt;![CDATA[$P{IncludedStates}.contains($F{state}) ? Boolean.TRUE : Boolean.FALSE]]&gt;&lt;/filterExpression&gt;
</code>
<br/>
<br/>
<b>Running the Sample</b>
<br/>
<br/>
Running the sample requires the <a href="http://ant.apache.org/">Apache Ant</a> library. Make sure that <code>ant</code> is already installed on your system (version 1.5 or later).
<br/>
In a command prompt/terminal window set the current folder to <code>demo/samples/xlsdatasource</code> within the JasperReports source project and run the <code>&gt; ant test view</code> command.
<br/>
It will generate all supported document types containing the sample report in the <code>demo/samples/xlsdatasource/build/reports</code> directory. 
<br/>
Then the report will open in the JasperReports internal viewer.
    </content>
  </feature>

</sample>
