Dynamically display a CSV file as an HTML table on a web page

68

Solution 1

The previously linked solution is a horrible piece of code; nearly every line contains a bug. Use fgetcsv instead:

<?php
echo "<html><body><table>\n\n";
$f = fopen("so-csv.csv", "r");
while (($line = fgetcsv($f)) !== false) {
        echo "<tr>";
        foreach ($line as $cell) {
                echo "<td>" . htmlspecialchars($cell) . "</td>";
        }
        echo "</tr>\n";
}
fclose($f);
echo "\n</table></body></html>";

Solution 2

Here is a simple function to convert csv to html table using php:

function jj_readcsv($filename, $header=false) {
$handle = fopen($filename, "r");
echo '<table>';
//display header row if true
if ($header) {
    $csvcontents = fgetcsv($handle);
    echo '<tr>';
    foreach ($csvcontents as $headercolumn) {
        echo "<th>$headercolumn</th>";
    }
    echo '</tr>';
}
// displaying contents
while ($csvcontents = fgetcsv($handle)) {
    echo '<tr>';
    foreach ($csvcontents as $column) {
        echo "<td>$column</td>";
    }
    echo '</tr>';
}
echo '</table>';
fclose($handle);
}

One can call this function like jj_readcsv('image_links.csv',true);

if second parameter is true then the first row of csv will be taken as header/title.

Hope this helps somebody. Please comment for any flaws in this code.

Solution 3

phihag's answer puts each row in a single cell, while you are asking for each value to be in a separate cell. This seems to do it:

<?php
// Create a table from a csv file 
echo "<html><body><table>\n\n";
$f = fopen("so-csv.csv", "r");
while (($line = fgetcsv($f)) !== false) {
        $row = $line[0];    // We need to get the actual row (it is the first element in a 1-element array)
        $cells = explode(";",$row);
        echo "<tr>";
        foreach ($cells as $cell) {
            echo "<td>" . htmlspecialchars($cell) . "</td>";
        }
        echo "</tr>\n";
}
fclose($f);
echo "\n</table></body></html>";
?>

Solution 4

Just improved phihag's code because it runs into a infinite loop if file not exists.

<?php

$filename = "so-csv.csv";

echo "<html><body><table>\n\n";

if (file_exists($filename)) {
$f = fopen($filename, "r");
while (($line = fgetcsv($f)) !== false) {
        echo "<tr>";
        foreach ($line as $cell) {
                echo "<td>" . htmlspecialchars($cell) . "</td>";
        }
        echo "</tr>\n";
}
fclose($f);
}

else{ echo "<tr><td>No file exists ! </td></tr>" ;}
echo "\n</table></body></html>";
?>

Solution 5

Here is the working solution updated with a few bootstrap goodies. Table Small, Striped, Bordered, and Hover Highlight

function jj_readcsv($filename, $header = false)
{
    $handle = fopen($filename, "r");
    echo '<div class="table-responsive"><table class="table table-sm table-striped table-bordered table-hover">';
    //display header row if true
    if ($header) {
        $csvcontents = fgetcsv($handle);
        echo '<tr>';
        foreach ($csvcontents as $headercolumn) {
            echo "<th>$headercolumn</th>";
        }
        echo '</tr>';
    }
    // displaying contents
    while ($csvcontents = fgetcsv($handle)) {
        echo '<tr>';
        foreach ($csvcontents as $column) {
            echo "<td style='width:1px; white-space:nowrap;'>$column</td>";
        }
        echo '</tr>';
    }
    echo '</table></div>';
    fclose($handle);
}
Share:
68
Dan H
Author by

Dan H

Updated on March 17, 2021

Comments

  • Dan H
    Dan H about 3 years

    I am creating a view containing a series of test results from well known canned tests as well as custom tests. Buttons on the GUI drive the canned tests, text entry provide the custom tests. Standard % tests:2,5,10,50,75,100; custom: 0-100 as entered %.

    SELECT        
        SerialNumber, ..., DateTimeStampStarted, 
        StartingSetpoint, EndingSetpoint... Status, Notes 
    FROM 
        dbo.PIDTuneResults
    WHERE        
        (DateTimeStampStarted IN (SELECT MAX(DateTimeStampStarted) AS Expr1 
                                  FROM dbo.PIDTuneResults AS PIDTuneResults_1  
                                  WHERE (StartingSetpoint = 0 
                                    AND EndingSetpoint = 2)
                                  GROUP BY SerialNumber))
    

    This query returns one (2%) of the canned tests, I am repeating this query 6 times (UNION), to enumerate the canned setpoints 2,5,10,50,75,100. Each query returns 1 record...the last test performed on that device. Now I need the custom test results. Here is my attempt but I need the last record for any of the custom tests.

    SELECT  
        SerialNumber, ..., DateTimeStampStarted, 
        StartingSetpoint, EndingSetpoint... Status, Notes 
    FROM 
        dbo.PIDTuneResults 
    WHERE 
        StartingSetpoint = 0 
        AND EndingSetpoint NOT IN (2, 5, 10, 50, 75, 100)
    

    How can I get the Last record for any custom test with any ending setpoint value(1-100)? Is there a way to do an aggregated qry like the others?

    Thanks, Dan

    • a_horse_with_no_name
      a_horse_with_no_name almost 6 years
      Which DBMS are you using? "SQL" is just a query language, not the name of a specific database product. Please add the tag for the database product you are using postgresql, oracle, db2, sql-server, ...