Bonjour,

Je vous contacte parce que je suis arrivé au bout de tous les contournements que j'ai pu trouver.

J'utilise PhpSpreadsheet pour générer des fichiers excel d'erreurs : en fonction d'un fichier en entrée, le site effectue des contrôles et génère des résultats de qualité de contrôle de données.
En fonction du nombre d'enregistrements du fichier en entrée et du nombre d'erreurs que celui-ci génère, le fichier peut être très volumineux (plus de 150 000 erreurs, donc lignes dans excel).

Mon traitement génère 13 fichiers excel. Je me rends compte qu'au fur et à mesure que le traitement avance et génère les fichiers Excel, l'utilisation mémoire augmente. Je le mesure avec ce code :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
        $used = round(memory_get_usage(true) / 1024 / 1024, 2);
        $peak = round(memory_get_peak_usage(true) / 1024 / 1024, 2);
        $percentUsed = round(($used / ($memoryLimit / 1024 / 1024)) * 100, 2);
        $percentPeak = round(($peak / ($memoryLimit / 1024 / 1024)) * 100, 2);
        file_put_contents($logFile, "[Chunk] RAM utilisée: {$used}MB ({$percentUsed}%) | Pic: {$peak}MB ({$percentPeak}%)" . PHP_EOL, FILE_APPEND);
Malgré les 48 Go proposés par l'hébergeur, un process PHP est limité à 2 Go.

Voici le code pour générer un des fichiers Excel :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
        $spreadsheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet();
        $sheet = $spreadsheet->getActiveSheet();
 
        $headers = ['Code', 'Message', 'Prêt', 'Tiers', 'Collateral', 'Valeur trouvée', 'Niveau Erreur', 'Type Validation', 'Date'];
        $sheet->fromArray([$headers], NULL, 'A1');
 
        $chunkSize = 500;
        $row = 2;
 
        foreach (array_chunk($erreursDetailleesTransaction, $chunkSize) as $chunk) {
            $sheet->fromArray($chunk, NULL, "A$row");
            $row += count($chunk);
        }
 
        // Log RAM utilisée
        $used = round(memory_get_usage(true) / 1024 / 1024, 2);
        $peak = round(memory_get_peak_usage(true) / 1024 / 1024, 2);
        $percentUsed = round(($used / ($memoryLimit / 1024 / 1024)) * 100, 2);
        $percentPeak = round(($peak / ($memoryLimit / 1024 / 1024)) * 100, 2);
        file_put_contents($logFile, "[Chunk] RAM utilisée: {$used}MB ({$percentUsed}%) | Pic: {$peak}MB ({$percentPeak}%)" . PHP_EOL, FILE_APPEND);
 
        // Styles
        $headerRange = 'A1:I1';
        $dataRange = 'A2:I' . (count($erreursDetailleesTransaction) + 1);
 
        $sheet->getStyle($headerRange)->applyFromArray([
            'font' => ['bold' => true, 'color' => ['rgb' => 'FFFFFF']],
            'fill' => ['fillType' => \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID, 'startColor' => ['rgb' => '4F81BD']],
            'borders' => ['allBorders' => ['borderStyle' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN]],
        ]);
 
        $sheet->getStyle($dataRange)->applyFromArray([
            'borders' => ['allBorders' => ['borderStyle' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN]],
        ]);
 
        foreach (range('A', 'I') as $col) {
            $sheet->getColumnDimension($col)->setAutoSize(false);
        }
 
        $sheet->getColumnDimension('A')->setWidth(15);
        $sheet->getColumnDimension('B')->setWidth(70);
        $sheet->getColumnDimension('C')->setWidth(20);
        $sheet->getColumnDimension('D')->setWidth(20);
        $sheet->getColumnDimension('E')->setWidth(20);
        $sheet->getColumnDimension('F')->setWidth(15);
        $sheet->getColumnDimension('G')->setWidth(20);
        $sheet->getColumnDimension('H')->setWidth(70);
        $sheet->getColumnDimension('I')->setWidth(15);
 
        $sheet->getStyle($headerRange)->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER);
        $sheet->getStyle($headerRange)->getAlignment()->setVertical(\PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER);
        $sheet->getStyle($dataRange)->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER);
        $sheet->getStyle($dataRange)->getAlignment()->setVertical(\PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER);
 
        $sheet->setSelectedCell('A1');
 
        $filePathTransaction .= '.xlsx';
        $writer = new \PhpOffice\PhpSpreadsheet\Writer\Xlsx($spreadsheet);
        $writer->setPreCalculateFormulas(false);
        $writer->save($filePathTransaction);
        $spreadsheet->disconnectWorksheets();
        unset($spreadsheet, $sheet, $writer, $erreursDetailleesTransaction);
        gc_collect_cycles();
Je suis passé par des chunks, par tout plein de contournements et il se trouve que c'est le code ci-dessus qui "résiste" le mieux. J'obtiens une erreur invisible dès que j'approche des 2048 Mo d'utilisation de la RAM, toujours pendant la génération d'un fichier Excel.

Auriez-vous des idées lumineuses pour me sortir de ce pétrin ? Ca fait des semaines que je tourne en rond. J'essaie de libérer la mémoire au maximum mais j'ai l'impression que ça ne change rien.
J'en arrive à me demander si finalement, il est possible de générer un tel fichier Excel via un site web.

J'ai bien conscience que la mise en forme prend beaucoup de ressources mais c'est vraiment un prérequis, sinon je génèrerais un fichier CSV.

La solution est peut-être évidente, je débute, donc n'hésitez pas à me dire si je fais n'importe quoi.

Je vous remercie pour votre aide et reste à votre disposition pour vous apporter un maximum d'éléments supplémentaires.