3 décembre 2012

Magento : dans l'admin, ajouter une colonne dans un export mais pas dans la grille

Dans le back office de Magento, il est possible très simplement d'autoriser l'utilisateur à effectuer un export de données. Ce mécanisme est géré par Magento et le développeur n'a qu'à spécifier qu'il souhaite l'utiliser. Deux formats sont supportés de base : CSV et XML pour Excel.

Il suffit d'ajouter le code suivant dans la méthode _prepareColumns() de votre block Grid, avant l'appel au parent :
$this->addExportType('*/*/exportCsv', Mage::helper('customer')->__('CSV'));
$this->addExportType('*/*/exportXml', Mage::helper('customer')->__('Excel XML'));
Puis ajouter les actions correspondantes dans votre contrôleur admin :
public function exportCsvAction()
{
    $fileName = 'votre_export.csv';
    $content = $this->getLayout()->createBlock('votre_module/votre_grid')->getCsvFile();
    $this->_prepareDownloadResponse($fileName, $content);
}

public function exportXmlAction()
{
    $fileName = 'votre_export.xml';
    $content = $this->getLayout()->createBlock('votre_module/votre_grid')->getExcelFile();
    $this->_prepareDownloadResponse($fileName, $content);
}
Ces actions utilisent les mêmes données que la grille, via l'appel à _prepareGrid(). Elles gèrent donc les mêmes colonnes. Donc pour ajouter une colonne à l'export, il faut l'ajouter à la grille. Et si on veut n'afficher cette colonne que dans l'export et pas dans la grille, il suffit de masquer la colonne à l'affichage :
protected function _prepareColumns()
{
    $this->addColumn('test', array(
        'index' => 'test',
        'header' => 'Test',
        'header_css_class' => 'no-display',
        'column_css_class' => 'no-display',
    ));

    return parent::_prepareColumns();
}
En faisant cela, la colonne "Test" sera ajoutée en 1ère position dans l'export. Pour la placer ailleurs, vous pouvez utiliser la méthode addColmunAfter() au lieu de addColumn(). Elle prend un 3ème paramètre qui est l'id de la colonne après laquelle vous souhaitez placer la colonne que vous ajoutez. Vous pouvez utiliser l'id d'une colonne qui sera créée par le parent et qui n'existe pas encore puisque l'ordre des colonnes n'est déterminé que plus tard.

L'inconvénient de cette façon de faire est que si la colonne que vous ajoutez uniquement pour l'export a un contenu lourd à calculer, les performances de l'affichage de la grille sont également impactées. Si vous souhaitez ajouter une colonne uniquement pour l'export et ne pas du tout l'avoir dans la grille, vous devez modifier les méthodes suivantes dans votre block Grid : _getExportHeaders(), _exportCsvItem() et _exportExcelItem(). Comme vous pouvez le constater, il faut impacter la méthode qui gère l'export d'un enregistrement pour chaque mode d'export. Cela peut être source d'erreurs et d'oublis.

2 commentaires:

  1. Salut,

    Je suis tombé sur ton article en voulant faire la même chose mais j'ai trouvé une autre solution moins "sale" :

    Dans la fonction exportCsvAction tu pouvais faire:

    public function exportCsvAction()
    {
    $fileName = 'votre_export.csv';
    $grid = $this->getLayout()->createBlock('votre_module/votre_grid');

    $grid->addColumn('test', array(
    'index' => 'test',
    'header' => 'Test'
    ));
    $this->_prepareDownloadResponse($fileName, $grid->getCsvFile());
    }

    Anyway, Thanks for your support !

    RépondreSupprimer
  2. salut
    merci pour ton commentaire, je n'avais pas pensé à cette façon de faire
    et je suis d'accord avec toi sauf que ta solution impose de dupliquer le code autant de fois qu'on a de formats d'export (et donc de méthodes correspondantes), sachant que de base il y a CSV et XML. De manière générale j'essaie de faire du DRY autant que possible.

    RépondreSupprimer