ERP en LOGICIEL LIBRE dédié aux PME-PMI

           Devenez partenaire Principal ou Majeur de Neogia

VIEWER EXCEL

Contents

Générer des rapports avec Excel

Dans un projet on a eu à générer des rapports en Excel à partir de modèles pré-définis. En fait on devait charger le modèle puis remplir ses cellules avec des données tirées depuis la base de données.

Ceci pourrait être facilement fait avec l'API d'Apache POI, et une servlet. Mais nous avons utilisé Néogia pour notre projet, donc on était contraint de créer un viewer qui devait nous générer des rapports Excel. A la fin on a eu un si beau résultat que la solution avec la servlet devenait à nos yeux trés complexe.

Dans cette page on va vous racontez notre expérience et comment vous pouvez intégrer ce viewer dans votre projet Ofbiz Nogia.

Le renderer de Ofbiz

Dans le module webapp du framework Ofbiz on peut trouver tout genre de rendrer. Ces classes peuvent constitués une base pour créer votre propre rendrer. c'est ce que nous avons fait d'ailleurs. Les rendrers d'Ofbiz doivent implementer une interface ViewHandler qui contient une methode unique render.

Nous avons créer une nouvelle classe POIViewHendler avec une méthode render qui ressemble à) ceci:

public void render(String name, String page, String info, String contentType, String encoding,
        HttpServletRequest request, HttpServletResponse response) throws ViewHandlerException {

   	if (request == null) {
           throw new ViewHandlerException("The HttpServletRequest object was null, how did that happen?");
       }
       if (page == null || page.length() == 0) {
           throw new ViewHandlerException("View page was null or empty, but must be specified");
       }
       if (info == null || info.length() == 0) {
           Debug.logInfo("View info string was null or empty, (optionally used to specify an Entity 
           that is mapped to the Entity Engine datasource that the report will use).", module);
       }
       
   	try {
   		page = request.getRealPath(page);
   		POIFSFileSystem fs =  new POIFSFileSystem(new FileInputStream(page));
   		HSSFWorkbook wb = new HSSFWorkbook(fs);
               HSSFSheet sheet = wb.getSheetAt(0);
               Map fillInfo = (Map) request.getAttribute("poiFillInfo");
               if (fillInfo != null) {
                  Iterator keyIt = fillInfo.keySet().iterator();
                  while (keyIt.hasNext()) {
                      int[] coordinates = (int[]) keyIt.next();
                      HSSFRow row = sheet.getRow(coordinates[1]);
                      if (row == null)
                          row = sheet.createRow(coordinates[1]);
                      HSSFCell cell = row.getCell((short) coordinates[0]);
                      if (cell == null)
                           cell = row.createCell((short)coordinates[0]);
                           cell.setCellValue(fillInfo.get(coordinates).toString());
                      }
               }
                response.setContentType("application/vnd.ms-excel");
                wb.write(response.getOutputStream());
                response.getOutputStream().flush(); 
       } catch (IOException ie) {
           throw new ViewHandlerException("IO Error in report", ie);
       } catch (Exception e) {
           throw new ViewHandlerException("Error in report", e);
           // } catch (ServletException se) {
           // throw new ViewHandlerException("Error in region", se.getRootCause());
       }
   }

En lisant le code on voit que le chemin du modèle Excel est passé à travers le paramètre page. et qu'un objet de type Map est retiré du request. le Map contient des clés de type int[] qui correspondent aux coordonées de la cellule dans la feuille Excel et la valeur est la valeur à mettre dans la cellule concernée.

Le controlleur de l'application

La prochaine étape est de modfiier le fcihier controller.xml de l'application concerné d'une façon à déclarer notre nouveau rendrer de la façon suivante:

<handler name="poi" type="view" class="org.ofbiz.webapp.view.PoiViewHandler"/>

Un exemple

Comme exemple nous allons créer un nouveau request-map et un nouveau view-map dans notre controller.xml

<request-map uri="PrintRentalInvoice">
    	<security https="true" auth="true" />
       <event type="simple" path="widgetActions/manage/developed/carrentalinv.xml"    invoke="makeFillInfo"/>
       <response name="success" type="view" value="RentalInvoice" />
   </request-map>
<view-map name="RentalInvoice" type="poi" page="/xlmodel/company-invoice.xls"/>

Comme il est clair dans notre exemple il y aura un evénement qui sera appelé, et dans cet évenement là on va préparer notre map qui sera sauvegardé dans le request afin d'être utilisé par le rendrer

Le code de l'évenment ressemble à ceci:

<simple-methods xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:noNamespaceSchemaLocation="http://www.ofbiz.org/dtds/simple-methods.xsd">

   <simple-method method-name="makeFillInfo" short-description="Get the invoice data to be injected into the agreement">
     <find-by-primary-key  entity-name="ParkCarRentalContract" value-name="contract" map-name="parameters"/>
     <call-bsh>
     	<![CDATA[ 
               import java.util.*;
               import org.ofbiz.base.util.*;
               import org.ofbiz.base.util.Debug;
               import org.ofbiz.entity.GenericDelegator;
               import org.ofbiz.entity.GenericValue; 
               Map fillInfo = new HashMap();
               delegator = request.getAttribute("delegator");

               fillInfo.put(new int[] {34,2}, contract.contractNumber);
     		fillInfo.put(new int[] {31,8}, contract.fromDate);
               fillInfo.put(new int[] {36,13}, contract.thruDate);
               request.setAttribute("poiFillInfo",  fillInfo);
        ]]>
     	</call-bsh>
    </simple-method>
</simple-methods>

Le code est simplement du minilang mélangé à du beanshel pour avoir en finalité un résultat qui sera mis dans le scope request.


Conclusion

J'espère que cette petite aide vous aidera à simplifier vos rapports surtout si vous êtes entrain de porter une application ou un business qui utilise beacoup des feuilles Excel.