2012-05-08 2 views
12

Мне просто нужно преобразовать эту таблицу html автоматически в csv, используя PHP. Может кто-нибудь представить, как это сделать? Спасибо.Преобразование таблицы HTML в CSV автоматически с использованием 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>'; 

Ребята, мне просто нужно $ таблицу конвертировать только .csv файл, который может быть автоматически сгенерированного с помощью некоторых функций PHP. Мы можем определить путь для этого файла CSV для /тест/дома/path_to_csv

+0

Я искал Google, но не нашел соответствующий – Thompson

+0

Я понимаю, что это не совсем то, что вы ищете, но вы можете сохранить его как xls. и excel откроет его, как ожидалось. – dm03514

+0

Вы пробовали это? http://davidvielmetter.com/tricks/howto-convert-an-html-table-to-csv-using-php/ –

ответ

15

Вы можете использовать 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

Баба, как мы можем определить некоторый путь для этого файла csv, чтобы автоматически сохранить его, например. **/test/home/path_to_csv ** – Thompson

+1

Да, вы можете ..... все, что вам нужно сделать, это удалить заголовки .... и изменить '' php: // output "' на ваш путь – Baba

+0

Спасибо за ваш метод. Я попробую его на своем ПК (сейчас я нахожусь на мобильном телефоне) и дам вам знать. – Thompson

5

для расширения принятого ответа я сделал это, что позволяет мне игнорировать столбцы по имени класса, а также обрабатывать пустые строки/столбцы.

Вы можете использовать str_get_html http://simplehtmldom.sourceforge.net/. Просто включите его и прочь! :)

$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

Вы можете сделать это с помощью массивов и регулярных выражений ... Ниже

$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); 

Затем вы можете использовать file_put_contents() писать строки CSV в файл ..

0

Если кто-либо использует ответ Бабы, но почесывает голову над добавлением лишних белых пространств, это будет работать:

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

Я приспособил простой класс, основанный на коде, найденную на эту тему, что теперь обрабатывает colspan и rowspan. Не тестировалось сильно, и я уверен, что он может быть оптимизирован.

Использование:

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

Вы можете использовать эту функцию в отдельный файл JS:

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' 
     }); 
    } 

Теперь, чтобы инициировать эту функцию, вы можете использовать:

$('.getfile').click(
      function() { 
    exportTableToCSV.apply(this, [$('#thetable'), 'filename.csv']); 
      }); 

где 'getfile' должен быть классом, назначенным кнопке, где вы хотите добавить призыв к действию. (При нажатии этой кнопки появится всплывающее окно загрузки) , а «таблица» должна быть идентификатором, присвоенным таблице, которую вы хотите загрузить.

Вы также можете перейти на произвольное имя файла для загрузки в код.

+0

Эта работа блестяще. Я пожертвую 100 быков в вашу честь. – OllyBarca

0

Ответы Бабы содержат дополнительное пространство. Итак, я обновил код для этого:

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);