2012-05-08 17 views
12

Ho solo bisogno di convertire automaticamente questa tabella html in csv usando PHP. Qualcuno può dare qualche idea su come farlo? Grazie.Convertire la tabella HTML in un CSV automaticamente usando PHP?

$table = '<table border="1"> 
<tr> 
<th>Header 1</th> 
<th>Header 2</th> 
</tr> 
<tr> 
<td>row 1, cell 1</td> 
<td>row 1, cell 2</td> 
</tr> 
<tr> 
<td>row 2, cell 1</td> 
<td>row 2, cell 2</td> 
</tr> 
</table>'; 

Ragazzi, ho solo bisogno $ tavolo per convertire in un solo .csv di file, che potrebbe essere generato automaticamente utilizzando qualche funzione PHP. Possiamo definire il percorso per il file csv per /test/home/path_to_csv

+0

ho cercato in Google, ma non ha trovato rilevanti – Thompson

+0

Mi rendo conto che questo non è proprio quello che state cercando, ma si può salvare come un xls. ed Excel lo aprirà come previsto. – dm03514

+0

Hai provato questo? http://davidvielmetter.com/tricks/howto-convert-an-html-table-to-csv-using-php/ –

risposta

15

È possibile utilizzare str_get_htmlhttp://simplehtmldom.sourceforge.net/

include "simple_html_dom.php"; 
$table = '<table border="1"> 
<tr> 
<th>Header 1</th> 
<th>Header 2</th> 
</tr> 
<tr> 
<td>row 1, cell 1</td> 
<td>row 1, cell 2</td> 
</tr> 
<tr> 
<td>row 2, cell 1</td> 
<td>row 2, cell 2</td> 
</tr> 
</table>'; 

$html = str_get_html($table); 



header('Content-type: application/ms-excel'); 
header('Content-Disposition: attachment; filename=sample.csv'); 

$fp = fopen("php://output", "w"); 

foreach($html->find('tr') as $element) 
{ 
    $td = array(); 
    foreach($element->find('th') as $row) 
    { 
     $td [] = $row->plaintext; 
    } 
    fputcsv($fp, $td); 

    $td = array(); 
    foreach($element->find('td') as $row) 
    { 
     $td [] = $row->plaintext; 
    } 
    fputcsv($fp, $td); 
} 


fclose($fp); 
+0

Baba, come possiamo definire un percorso per quel file csv da ottenere automaticamente salvato ad es. **/test/home/path_to_csv ** – Thompson

+1

Sì, puoi ..... tutto quello che devi fare è rimuovere le intestazioni .... e cambiare '" php: // output "' sul tuo percorso – Baba

+0

Grazie per il tuo metodo. Lo proverò sul mio PC (al momento sono su cellulare) e te lo faccio sapere. – Thompson

5

ad ampliare la risposta accettata ho fatto questo, che mi permette di ignora le colonne per nome della classe e si occupa anche di righe/colonne vuote.

È possibile utilizzare str_get_html http://simplehtmldom.sourceforge.net/. Basta includerlo e via vai! :)

$html = str_get_html($html); // give this your HTML string 

header('Content-type: application/ms-excel'); 
header('Content-Disposition: attachment; filename=sample.csv'); 

$fp = fopen("php://output", "w"); 

foreach($html->find('tr') as $element) { 
    $td = array(); 
    foreach($element->find('th') as $row) { 
    if (strpos(trim($row->class), 'actions') === false && strpos(trim($row->class), 'checker') === false) { 
     $td [] = $row->plaintext; 
    } 
    } 
    if (!empty($td)) { 
    fputcsv($fp, $td); 
    } 

    $td = array(); 
    foreach($element->find('td') as $row) { 
    if (strpos(trim($row->class), 'actions') === false && strpos(trim($row->class), 'checker') === false) { 
     $td [] = $row->plaintext; 
    } 
    } 
    if (!empty($td)) { 
    fputcsv($fp, $td); 
    } 
} 

fclose($fp); 
exit; 
4

Si può fare questo con gli array e le espressioni regolari ... Vedi sotto

$csv = array(); 
preg_match('/<table(>| [^>]*>)(.*?)<\/table(|>)/is',$table,$b); 
$table = $b[2]; 
preg_match_all('/<tr(>| [^>]*>)(.*?)<\/tr(|>)/is',$table,$b); 
$rows = $b[2]; 
foreach ($rows as $row) { 
    //cycle through each row 
    if(preg_match('/<th(>| [^>]*>)(.*?)<\/th(|>)/is',$row)) { 
     //match for table headers 
     preg_match_all('/<th(>| [^>]*>)(.*?)<\/th(|>)/is',$row,$b); 
     $csv[] = strip_tags(implode(',',$b[2])); 
    } elseif(preg_match('/<td(>| [^>]*>)(.*?)<\/td(|>)/is',$row)) { 
     //match for table cells 
     preg_match_all('/<td(>| [^>]*>)(.*?)<\/td(|>)/is',$row,$b); 
     $csv[] = strip_tags(implode(',',$b[2])); 
    } 
} 
$csv = implode("\n", $csv); 
var_dump($csv); 

Quindi è possibile utilizzare file_put_contents() a scrivere la stringa CSV in un file ..

0

Se qualcuno sta usando la risposta di Baba ma si gratta la testa per aggiungere spazi bianchi extra, questo funzionerà:

include "simple_html_dom.php"; 
$table = '<table border="1"> 
<tr> 
<th>Header 1</th> 
<th>Header 2</th> 
</tr> 
<tr> 
<td>row 1, cell 1</td> 
<td>row 1, cell 2</td> 
</tr> 
<tr> 
<td>row 2, cell 1</td> 
<td>row 2, cell 2</td> 
</tr> 
</table>'; 

$html = str_get_html($table); 

$fileName="export.csv"; 
header('Content-type: application/ms-excel'); 
header("Content-Disposition: attachment; filename=$fileName"); 

$fp = fopen("php://output", "w"); 
$csvString=""; 

$html = str_get_html(trim($table)); 
foreach($html->find('tr') as $element) 
{ 

    $td = array(); 
    foreach($element->find('th') as $row) 
    { 
     $row->plaintext="\"$row->plaintext\""; 
     $td [] = $row->plaintext; 
    } 
    $td=array_filter($td); 
    $csvString.=implode(",", $td); 

    $td = array(); 
    foreach($element->find('td') as $row) 
    { 
     $row->plaintext="\"$row->plaintext\""; 
     $td [] = $row->plaintext; 
    } 
    $td=array_filter($td); 
    $csvString.=implode(",", $td)."\n"; 
} 
echo $csvString; 
fclose($fp); 
exit; 

}

0

Ho adattato una semplice classe in base al codice trovato su questa discussione, che ora gestisce colspan e rowspan. Non fortemente testato e sono sicuro che potrebbe essere ottimizzato.

Usage:

require_once('table2csv.php'); 

$table = '<table border="1"> 
    <tr> 
    <th colspan=2>Header 1</th> 
    </tr> 
    <tr> 
    <td>row 1, cell 1</td> 
    <td>row 1, cell 2</td> 
    </tr> 
    <tr> 
    <td>row 2, cell 1</td> 
    <td>row 2, cell 2</td> 
    </tr> 
    <tr> 
    <td rowspan=2>top left row</td> 
    <td>top right row</td> 
    </tr> 
    <tr> 
    <td>bottom right</td> 
    </tr> 
    </table>'; 

table2csv($table,"sample.csv",true); 

table2csv.php

<?php 

    //download @ http://simplehtmldom.sourceforge.net/ 
    require_once('simple_html_dom.php'); 
    $repeatContentIntoSpannedCells = false; 


    //-------------------------------------------------------------------------------------------------------------------- 

    function table2csv($rawHTML,$filename,$repeatContent) { 

     //get rid of sups - they mess up the wmus 
     for ($i=1; $i <= 20; $i++) { 
      $rawHTML = str_replace("<sup>".$i."</sup>", "", $rawHTML); 
     } 

     global $repeatContentIntoSpannedCells; 

     $html = str_get_html(trim($rawHTML)); 
     $repeatContentIntoSpannedCells = $repeatContent; 

     //we need to pre-initialize the array based on the size of the table (how many rows vs how many columns) 

     //counting rows is easy 
     $rowCount = count($html->find('tr')); 

     //column counting is a bit trickier, we have to iterate through the rows and basically pull out the max found 
     $colCount = 0; 
     foreach ($html->find('tr') as $element) { 

      $tempColCount = 0; 

      foreach ($element->find('th') as $cell) { 
       $tempColCount++; 
      } 

      if ($tempColCount == 0) { 
       foreach ($element->find('td') as $cell) { 
        $tempColCount++; 
       } 
      } 

      if ($tempColCount > $colCount) $colCount = $tempColCount; 
     } 

     $mdTable = array(); 

     for ($i=0; $i < $rowCount; $i++) { 
      array_push($mdTable, array_fill(0, $colCount, NULL)); 
     } 

     //////////done predefining array 

     $rowPos = 0; 
     $fp = fopen($filename, "w"); 

     foreach ($html->find('tr') as $element) { 

      $colPos = 0; 

      foreach ($element->find('th') as $cell) { 
       if (strpos(trim($cell->class), 'actions') === false && strpos(trim($cell->class), 'checker') === false) { 
        parseCell($cell,$mdTable,$rowPos,$colPos); 
       } 
       $colPos++; 
      } 

      foreach ($element->find('td') as $cell) { 
       if (strpos(trim($cell->class), 'actions') === false && strpos(trim($cell->class), 'checker') === false) { 
        parseCell($cell,$mdTable,$rowPos,$colPos); 
       } 
       $colPos++; 
      } 

      $rowPos++; 
     } 


     foreach ($mdTable as $key => $row) { 

      //clean the data 
      array_walk($row, "cleanCell"); 
      fputcsv($fp, $row); 
     } 
    } 


    function cleanCell(&$contents,$key) { 

     $contents = trim($contents); 

     //get rid of pesky &nbsp's (aka: non-breaking spaces) 
     $contents = trim($contents,chr(0xC2).chr(0xA0)); 
     $contents = str_replace("&nbsp;", "", $contents); 
    } 


    function parseCell(&$cell,&$mdTable,&$rowPos,&$colPos) { 

     global $repeatContentIntoSpannedCells; 

     //if data has already been set into the cell, skip it 
     while (isset($mdTable[$rowPos][$colPos])) { 
      $colPos++; 
     } 

     $mdTable[$rowPos][$colPos] = $cell->plaintext; 

     if (isset($cell->rowspan)) { 

      for ($i=1; $i <= ($cell->rowspan)-1; $i++) { 
       $mdTable[$rowPos+$i][$colPos] = ($repeatContentIntoSpannedCells ? $cell->plaintext : ""); 
      } 
     } 

     if (isset($cell->colspan)) { 

      for ($i=1; $i <= ($cell->colspan)-1; $i++) { 

       $colPos++; 
       $mdTable[$rowPos][$colPos] = ($repeatContentIntoSpannedCells ? $cell->plaintext : ""); 
      } 
     } 
    } 

?> 
9

È possibile utilizzare questa funzione in un file js separato:

function exportTableToCSV($table, filename) { 

     var $rows = $table.find('tr:has(td)'), 

      // Temporary delimiter characters unlikely to be typed by keyboard 
      // This is to avoid accidentally splitting the actual contents 
      tmpColDelim = String.fromCharCode(11), // vertical tab character 
      tmpRowDelim = String.fromCharCode(0), // null character 

      // actual delimiter characters for CSV format 
      colDelim = '","', 
      rowDelim = '"\r\n"', 

      // Grab text from table into CSV formatted string 
      csv = '"' + $rows.map(function (i, row) { 
       var $row = $(row), 
        $cols = $row.find('td'); 

       return $cols.map(function (j, col) { 
        var $col = $(col), 
         text = $col.text(); 

        return text.replace('"', '""'); // escape double quotes 

       }).get().join(tmpColDelim); 

      }).get().join(tmpRowDelim) 
       .split(tmpRowDelim).join(rowDelim) 
       .split(tmpColDelim).join(colDelim) + '"', 

      // Data URI 
      csvData = 'data:application/csv;charset=utf-8,' + encodeURIComponent(csv); 

     $(this) 
      .attr({ 
      'download': filename, 
       'href': csvData, 
       'target': '_blank' 
     }); 
    } 

Ora, per avviare questa funzione, puoi usare:

dove 'getfile' deve essere la classe assegnata al pulsante, dove si desidera aggiungere call to action. (Facendo clic su questo pulsante, verrà visualizzato il popup di download) e "thetable" dovrebbe essere l'ID assegnato alla tabella che si desidera scaricare.

È inoltre possibile modificare il nome del file personalizzato da scaricare nel codice.

+0

Questo lavoro è brillante. Sacrificherò 100 tori in tuo onore. – OllyBarca

0

La risposta di Baba contiene spazio extra. Così, ho aggiornato il codice a questo:

include "simple_html_dom.php"; 
 
$table = '<table border="1"> 
 
<tr> 
 
<th>Header 1</th> 
 
<th>Header 2</th> 
 
</tr> 
 
<tr> 
 
<td>row 1, cell 1</td> 
 
<td>row 1, cell 2</td> 
 
</tr> 
 
<tr> 
 
<td>row 2, cell 1</td> 
 
<td>row 2, cell 2</td> 
 
</tr> 
 
</table>'; 
 

 
$html = str_get_html($table); 
 

 

 

 
header('Content-type: application/ms-excel'); 
 
header('Content-Disposition: attachment; filename=sample.csv'); 
 

 
$fp = fopen("php://output", "w"); 
 

 
foreach($html->find('tr') as $element) 
 
{ 
 
    $td = array(); 
 
foreach($element->find('th') as $row) 
 
{ 
 
    $td [] = $row->plaintext; 
 
} 
 

 
foreach($element->find('td') as $row) 
 
{ 
 
    $td [] = $row->plaintext; 
 
} 
 
fputcsv($fp, $td); 
 
} 
 

 

 
fclose($fp);