KoolReport's Forum

Official Support Area, Q&As, Discussions, Suggestions and Bug reports.
Forum's Guidelines

Export Excel not download #2173

Open Epitello opened this topic on on Jun 30, 2021 - 10 comments

Epitello commented on Jun 30, 2021

Hello team, I try to create an excel export, the view is run but the file is not downloading. I am using koolreport with symfony. I share you the code. Thanks by advance

if($params['exportType'] == 'pdf'){

            //L'instruction 'run()' permet de lire et d'éxécuter le contenu de la class MyReport

            $report

                ->run()

                ->export('ExportPDF')

                ->pdf([

                    "format" => $params['document']['format'],

                    "orientation" => $params['document']['orientation'],

                    "zoom" => 1.25,

                    'dpi' => 300

                ])

                ->toBrowser('myreport.pdf', true);

        }else{

            //fait l'export en excel

            $report->run()->exportToExcel('ExportExcel')->toBrowser("myreport.xlsx");

        }
Epitello commented on Jun 30, 2021

and the ExportExcel.view.php

<?php

    use koolreport\excel\PieChart;
    use koolreport\excel\Table;
    use koolreport\excel\BarChart;
    use koolreport\excel\AreaChart;
    use koolreport\excel\LineChart;
    use koolreport\excel\DonutChart;

    //dump($this->page, $this->right, $this->colorScheme, $this->format, $this->currency, $this->elements);exit;
    $page = $this->document;
    $elements = $this->elements;

    foreach ($elements as $key => $value) {
        if($value['type'] == 'VisualQuery'){
            unset($elements[$key]);
        }

        if($value['type'] == 'data_tables'){
            if(array_key_exists('paging', $value['params']['options'])){
                unset($elements[$key]['params']['options']['paging']);
            }
        }
    }

    $styleArray = [
        'font' => [
            'name' => 'Calibri', //'Verdana', 'Arial'
            'size' => 30,
            'bold' => false,
            'italic' => FALSE,
            'underline' => 'none', //'double', 'doubleAccounting', 'single', 'singleAccounting'
            'strikethrough' => FALSE,
            'superscript' => false,
            'subscript' => false,
            'color' => [
                'rgb' => '000000',
                'argb' => 'FF000000',
            ]
        ],
        'alignment' => [
            'horizontal' => 'general',//left, right, center, centerContinuous, justify, fill, distributed
            'vertical' => 'bottom',//top, center, justify, distributed
            'textRotation' => 0,
            'wrapText' => false,
            'shrinkToFit' => false,
            'indent' => 0,
            'readOrder' => 0,
        ],
        'borders' => [
            'top' => [
                'borderStyle' => 'none', //dashDot, dashDotDot, dashed, dotted, double, hair, medium, mediumDashDot, mediumDashDotDot, mediumDashed, slantDashDot, thick, thin
                'color' => [
                    'rgb' => '808080',
                    'argb' => 'FF808080',
                ]
            ],
            //left, right, bottom, diagonal, allBorders, outline, inside, vertical, horizontal
        ],
        'fill' => [
            'fillType' => 'none', //'solid', 'linear', 'path', 'darkDown', 'darkGray', 'darkGrid', 'darkHorizontal', 'darkTrellis', 'darkUp', 'darkVertical', 'gray0625', 'gray125', 'lightDown', 'lightGray', 'lightGrid', 'lightHorizontal', 'lightTrellis', 'lightUp', 'lightVertical', 'mediumGray'
            'rotation' => 90,
            'color' => [
                'rgb' => '000000',
                'argb' => 'FF000000',
            ],
            'startColor' => [
                'rgb' => '000000',
                'argb' => 'FF000000',
            ],
            'endColor' => [
                'argb' => 'FFFFFF',
                'argb' => 'FFFFFFFF',
            ],
        ],
    ];
    
    //Tableau contenant les lettres de l'alphabet pour définir les cellules des éléments
    $letters = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];
?>
<!-- Boucle sur l'objet page pour créer et positionner les objets-->
<?php foreach($page['pages'] as $pageId => $pageContent): ?>
    <!-- Défini un sheet et son nom -->
    <div sheet-name="Page <?= $pageId + 1?>">
        <!-- Défini les élément composant les cellules de début et de fin (lettre + nombre)-->
        <?php $startRangeLetter = 'A'; $startRangeIndex = 1; $endRangeLetter = ''; $endRangeIndex = 1?>
        <!-- Boucle sur les lignes de la page-->
        <?php foreach($pageContent['body']['element'] as $rowId => $rowContent): ?>
            <!-- Boucle sur les colonnes d'une ligne -->
            <?php foreach($rowContent['element'] as $colId => $colContent): ?>
                <?php foreach($colContent['element'] as $subRowId => $subRowContent): ?>
                    <?php
                        //défini les variables de dimension pour calculer la plage de chaque élément
                        // 80 et 20 son les dimensions par défaut d'une céllule excel
                        $tempWidth = (int) round($colContent['style']['width'] / 80);
                        $tempHeight = (int) round($subRowContent['style']['height'] / 21);

                        //on assigne $letters à $tempLetters car dans le cas ou il y a plusieurs élément sur une même ligne il faut modifier le tableau
                        $tempLetters = $letters;

                        //$count correspond à l'index de la lettre à utiliser en cas de cellule à plus d'une lettre
                        //exemple : AA
                        $count = 0;

                        $firstLoop = true;

                        foreach($elements as $key => $elementParams){
                            if($elementParams['id'] == $subRowContent['element']){
                                $element = $elementParams;                               
                            }
                        }
                        
                        //Si l'élément est un tableau, on récupère le nombre de lignes du tableau plutot que ça dimension
                        if($element['type'] == 'data_tables'){
                            //on ajoute deux au nombre de ligne pour faire commencer l'élément suivant à la fin du tableau
                            //car la première ligne de la feuille excel est occuppé par les labels et il faut faire commencer une ligne après la fin
                            $endRangeIndex = $this->dataStore(strval($element['datastore']['id']))->count() + 2;
                        }else{
                            //récupère l'index pour la cellule de fin en fonction de la taille de l'élément
                            $endRangeIndex = ($startRangeIndex - 1) + $tempHeight;
                        }

                        //si il y a plusieurs éléments sur une ligne
                        if($colId != 0){
                            //si la cellule est composé de plus d'une lettre (AA)
                            if(strlen($startRangeLetter) > 1){
                                //récupère le dernier charactère de la string
                                $lastChar = substr($startRangeLetter, -1);
                                //on "coupe" $tempLetters pour le faire commencer à la lettre de la cellule de fin de l'élément précédent
                                $tempLetters = array_slice($tempLetters, array_search($lastChar, $tempLetters));
                                //récupère l'index de la première lettre de la cellule
                                $count = array_search(substr($startRangeLetter, 0, 1), $letters);
                                //permet de ne pas passer dans la condition du premier tour de boucle
                                $firstLoop = false;
                            }else{
                                //on "coupe" $tempLetters pour le faire commencer à la lettre de la cellule de fin de l'élément précédent
                                $tempLetters = array_slice($tempLetters, array_search($startRangeLetter, $tempLetters));
                            }
                        }

                        //donne à $endRangeLetter la valeur de la lettre de la céllule de fin en fonction de la largeur calculé de l'élément
                        for($i = 0; $i <= $tempWidth; $i++){
                            //si $i - le nombre total de lettre vaut 0
                            if($i - (count($tempLetters)) == 0){
                                //si c'est le premier tour de boucle
                                if($firstLoop == true){ 
                                    $firstLoop = false;
                                }else{
                                    $count += 1;
                                }
                            }

                            //si i = un index présent dans le tableau (de 0 à 25)
                            if($i <= count($tempLetters) - 1){
                                //si une première lettre est déja présente
                                if($firstLoop == false){
                                    $endRangeLetter = $letters[$count].$letters[$i];
                                }else{
                                    //$endRangeLetter prend la valeur de la lettre correspondante
                                    $endRangeLetter = $tempLetters[$i];
                                }
                            }else{
                                //$endRangeLetter prend la valeur de la lettre correspondant à l'index de count + la lettre correspondant à l'index de $i
                                $endRangeLetter = $letters[$count].$letters[abs($i - count($tempLetters))];
                            }

                        }
                    ?>

                    <!-- Si l'élément à rendre est un tableau alors on lui indique seulement ça cellule de départ -->
                    <?php if($element['type'] == 'data_tables'):?>
                        <div cell='<?=$startRangeLetter.$startRangeIndex?>'>
                    <?php else:?>
                    <!-- Sinon on indique une plage (cellule du haut à gauche : cellule du bas à droite) -->
                        <div range='<?=$startRangeLetter.$startRangeIndex?>:<?=$endRangeLetter.$endRangeIndex?>'>
                    <?php endif?>
                        <?php
                            //correspond à lélement à rendre pour la colonne
                            // $element = $elements[$colContent['id_element']];

                            //tableau au bon format pour être interprété par la fonction create
                            $params = [
                                "dataSource"=>$this->dataStore(strval($element['datastore']['id'])),
                                // "colorScheme"=>$this->colorScheme['colorScheme'],
                                "excelStyle" => $styleArray
                            ];

                            //récupère les params de l'élement et les places dans le tableau $params
                            foreach ($element['params'] as $key => $value) {
                                $params[$key] = $value;
                            }

                            //appel la bonne class en fonction du type de l'élément à rendre
                            switch($element['type']){
                                case 'data_tables':
                                    Table::create($params);
                                    break;
                                case 'pie_chart':
                                    PieChart::create($params);
                                    break;
                                case 'column_chart':
                                    BarChart::create($params);
                                    break;
                                case 'donut_chart':
                                    DonutChart::create($parms);
                                    break;
                                case 'area_chart':
                                    AreaChart::create($parms);
                                    break;
                                case 'line_chart':
                                    LineChart::create($parms);
                                    break;
                            }
                        ?>
                    </div>
                    <?php
                        //Si la ligne possède plusieurs colonnes alors $startRangeLetter prend la velaur de $endRangeLetter pour pouvoir rendre les 
                        //éléments les un à coté des autres
                        // dump($rowContent);exit;
                        if(count($rowContent['element']) > 1){
                            $startRangeLetter = $endRangeLetter;
                        }
                    ?>
                <?php endforeach ?>
            <?php endforeach ?>
            <!-- On assigne les valeurs de $startRangeLetter et $startRangeIndex pour faire commencer la nouvelle ligne à la suite de la précédante -->
            <?php $startRangeIndex = $endRangeIndex; $startRangeLetter = 'A';?>
        <?php endforeach ?>
    </div> 
<?php endforeach ?>

Sebastian Morales commented on Jul 1, 2021

If you replace the excel view file with a simple view with one text/table/chart widget only, does excel export work? Rgds,

Epitello commented on Jul 1, 2021

No, it doesn't download excel even if i create a simple view

Sebastian Morales commented on Jul 1, 2021

Pls use this content for your excel view:

<div>
    <div>Hello world</div>
</div>

together with this export command:

error_reporting(E_ALL);
$report->run()->exportToExcel('ExportExcel')->toBrowser("myreport.xlsx");

Then let us know what happens exactly (with screenshot if it's possible). Tks,

Epitello commented on Jul 1, 2021

I can't send you a screenshot beacause nothing append, if i put a dump in ExportExcel.view.php i see my dump but i i remove it i see nothing, just the main page

Sebastian Morales commented on Jul 2, 2021

Would you pls run our standard excel template example in our examples:

https://cdn.koolreport.com/assets/download/koolreport_and_examples_5.0.1.zip

and let us know if it works. Tks,

Epitello commented on Jul 5, 2021

it doesn't work

Sebastian Morales commented on Jul 5, 2021

Pls let us know your PHP version and your Excel package version? Tks,

Epitello commented on Jul 5, 2021

I changed the $ tmpFilePath in ExportHandler.php at line 289, and now I can see the excel file is created but the toBrowser function seems to keep not working, maybe it is an access right to the folder or the creation of the "tmp" folder which causes problem a problem or something like that. (I am using koolreport with symfony). php version : 7.4.20 koolreport/pro: 5.0.4

Sebastian Morales commented on Jul 6, 2021

Pls turn on your PHP error reporting in your php.ini or in your project somewhere. We can't debug with empty error reporting. Regarding the temp file path, pls try this export command:

$report->run()->exportToExcel('ExportExcel', [ 'useLocalTempFolder' => true ])->toBrowser("myreport.xlsx");

It would use a local temp directory instead of the system one. In any case pls allow write permission to the system temp directory for your PHP user. Rgds,

Build Your Excellent Data Report

Let KoolReport help you to make great reports. It's free & open-source released under MIT license.

Download KoolReport View demo
help needed

Excel