2017-09-05 1 views
0

Je me connecte via IMAP pour obtenir les pièces jointes XLSX à partir d'une boîte aux lettres afin de convertir ces feuilles de calcul en données PHP avec PHPExcel, mais lorsque je charge le fichier et le convertit en tableau, le tableau est vide.Comment lire un fichier de pièce jointe XLSX avec PHPExcel?

C'est la fonction qui obtient les pièces jointes des mails correspondant aux critères:

public function getEmailAttachments($criteria){ 
    $emails = imap_search($this->inbox, $criteria); 
    $email_attachments = []; 
    if($emails) { 
    rsort($emails); 
    foreach ($emails as $email_number) { 
     $attachments = []; 
     //get Email structure 
     $structure = imap_fetchstructure($this->inbox, $email_number); 
     /* if any attachments found... */ 
     if(isset($structure->parts) && count($structure->parts)) 
     { 
      for($i = 0; $i < count($structure->parts); $i++) 
      { 
       $attachments[$i] = array(
        'is_attachment' => false, 
        'filename' => '', 
        'name' => '', 
        'attachment' => '' 
      ); 

       if($structure->parts[$i]->ifdparameters) 
       { 
        foreach($structure->parts[$i]->dparameters as $object) 
        { 
         if(strtolower($object->attribute) == 'filename') 
         { 
          $attachments[$i]['is_attachment'] = true; 
          $attachments[$i]['filename'] = $object->value; 
         } 
        } 
       } 

       if($structure->parts[$i]->ifparameters) 
       { 
        foreach($structure->parts[$i]->parameters as $object) 
        { 
         if(strtolower($object->attribute) == 'name') 
         { 
          $attachments[$i]['is_attachment'] = true; 
          $attachments[$i]['name'] = $object->value; 
         } 
        } 
       } 

       if($attachments[$i]['is_attachment']) 
       { 
        $attachments[$i]['attachment'] = imap_fetchbody($this->inbox, $email_number, $i+1); 
        /* 3 = BASE64 encoding */ 
        if($structure->parts[$i]->encoding == 3) 
        { 
         $attachments[$i]['attachment'] = base64_decode($attachments[$i]['attachment']); 
        } 
        /* 4 = QUOTED-PRINTABLE encoding */ 
        elseif($structure->parts[$i]->encoding == 4) 
        { 
         $attachments[$i]['attachment'] = quoted_printable_decode($attachments[$i]['attachment']); 
        } 
       } 
      } 
     } 
     $email_attachments = array_merge($email_attachments, array_filter($attachments, function($attachment){return $attachment['is_attachment'] == 1;})); 
    } 
    } 
    imap_close($this->inbox); 
    return $email_attachments; 
} 

Alors ceci est la fonction qui écrit les fichiers XLSX au serveur et les charges avec PHPExcel pour les convertir en données Array :

public function getEmailReports(){ 
    $this->loadPhpExcel(); 
    $attachments = parent::getEmailAttachments('FROM "[email protected]"'); 
    //iterate through each attachment and save it 
    foreach($attachments as $attachment){ 
    $filename = $attachment['name']; 
    if(empty($filename)) $filename = $attachment['filename']; 
    $folder = "data/excel"; 
    $file_path = "./". $folder ."/". time() . "-" . $filename; 
    $fp = fopen($file_path, "w"); 
    fwrite($fp, $attachment['attachment']); 
    $excelReader = PHPExcel_IOFactory::createReaderForFile($file_path); 
    $excelObj = $excelReader->load($file_path); 
    foreach ($excelObj->getWorksheetIterator() as $worksheet) { 
     $worksheets[$worksheet->getTitle()] = $worksheet->toArray(); 
    } 
    fclose($fp); 
    print_r($worksheets); //ARRAY IS EMPTY HERE 
    //unlink($file_path); 
    } 
} 
+0

combien de ceci avez-vous testé cela fonctionne? – rtfm

+0

@rtfm Le fichier XLSX est en cours d'écriture sur le serveur, la partie qui ne fonctionne pas est lors du chargement du fichier XLSX à partir du serveur et de la conversion en tableau –

+0

Aucune erreur n'est affichée? Rien écrit dans les journaux? –

Répondre

1

J'ai ouvert le fichier XLSX avec WinRAR et découvert que le fichier xl/worbooks.xml a un espace de noms "S":

<?xml version="1.0"?> 
<s:workbook 
xmlns:s="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"> 
<s:workbookPr/> 
<s:bookViews> 
<s:workbookView activeTab="0"/> 
</s:bookViews> 
<s:sheets> 
<s:sheet r:id="rId1" sheetId="1" name="Sheet1"/> 
<s:sheet r:id="rId2" sheetId="2" name="Sheet2"/> 
<s:sheet r:id="rId3" sheetId="3" name="Sheet3"/> 
<s:sheet r:id="rId4" sheetId="4" name="Sheet4"/> 
</s:sheets> 
<s:definedNames/> 
<s:calcPr fullCalcOnLoad="1" calcId="124519"/> 
</s:workbook> 

Je trouve cette question sur PHPExcel GitHub repo https://github.com/PHPOffice/PHPExcel/issues/571

Donc je ne ai fait créer une classe allant de PHPExcel_Reader_Excel2007 pour enlever l'espace de noms « s »

<?php 
class PHPExcel_Reader_Excel2007_XNamespace extends 
PHPExcel_Reader_Excel2007 
{ 

public function securityScan($xml) 
{ 
    $xml = parent::securityScan($xml); 
    return str_replace(['<s:', '</s:'], ['<', '</'], $xml); 
} 

} 

et finalement remplacé ceci:

$excelReader = PHPExcel_IOFactory::createReaderForFile($file_path); 

pour cela:

$excelReader = new PHPExcel_Reader_Excel2007_XNamespace();