Skip to content

Instantly share code, notes, and snippets.

@edmorais
Last active May 20, 2025 18:55
Show Gist options
  • Select an option

  • Save edmorais/25413ecb7381d3d96ac8cc75e6ed1218 to your computer and use it in GitHub Desktop.

Select an option

Save edmorais/25413ecb7381d3d96ac8cc75e6ed1218 to your computer and use it in GitHub Desktop.
Browse CSV table rows as pages. Useful to browse tables generated by Google Forms, etc.
<?php
/*
____ __ __ __ ___ _
/ __/__/ /_ _____ ________/ /__ / |/ /__ _______ _(_)__
/ _// _ / // / _ `/ __/ _ / _ \ / /|_/ / _ \/ __/ _ `/ (_-<
/___/\_,_/\_,_/\_,_/_/ \_,_/\___/ /_/ /_/\___/_/ \_,_/_/___/
CSV browser - Eduardo Morais 2024 - www.eduardomorais.pt
Browse CSV table rows as pages. Useful to browse tables generated by Google Forms, etc.
Extracts headings from the CSV first row.
Page title is extracted from the first cell in each row.
Usage: place the CSV files in the same folder as this file. Serve that folder via a (local) webserver.
*/
$csv = false;
if (isset($_GET['csv']) && $_GET['csv'] != null) {
$csv = $_GET['csv'];
if (file_exists($csv)) {
$row = 1;
if (isset($_GET['row']) && $_GET['row'] != null) {
$row = $_GET['row'];
}
showCSV($csv, $row);
} else { $csv = false; }
}
?>
<html>
<head>
<title>CSV browser<?=$csv ? ': '.$csv : ''?></title>
<link href="https://fonts.googleapis.com/css?family=Work+Sans:700,700i,400,400i" rel="stylesheet" type="text/css">
<style type="text/css">
<!--
html, body { margin: auto; padding: 40px; width: 80%; }
body {
color: #a7a9be;
font-family: "Work Sans", Arial, Helvetica, sans-serif;
font-weight: 400;
background: #0f0e17;
}
main { position: absolute; display: block; top: 15%; left: 15%; width: 70%; }
h1, h2 {
color: #fffffe;
font-weight: 700;
}
h1 {
font-size: 2.4rem;
}
h2 {
font-size: 1.8rem;
}
b {
font-weight: normal;
border-bottom: 1px dotted #ff8906;
}
p {
font-size: 1.2rem;
line-height: 1.6rem;
color: #C7C9De;
}
p.smaller {
font-size: 0.9rem;
line-height: 1 rem;
}
a, a:link, a:visited {
text-decoration: none;
color: #fffffe;
}
.sticky {
position: fixed;
top: 4em;
right: 15%;
padding: 0 1em;
background: #0f0e17CC;
border-radius: 16px;
}
a:hover {
color: #fffffe;
border-bottom: 1px solid #e53170;
}
//-->
</style>
</head>
<body>
<?php
if ($csv == false) listCSVs();
function listCSVs() {
$files = glob("*.csv");
echo '<h1>CSV browser</h1>';
foreach($files as $file) {
echo '<p><a href="'.$_SERVER['SCRIPT_NAME'].'?csv='.$file.'&row=1">'.$file.'</a></p>';
}
}
function showCSV($csv, $row) {
$data = array();
$r = 0;
if (($handle = fopen($csv, "r")) !== FALSE) {
while (($d = fgetcsv($handle, 1000, ",")) !== FALSE) {
$data[$r] = $d;
$r++;
}
fclose($handle);
}
$html = "";
foreach($data[$row] as $k=>$item) {
if (!empty($item)) {
if ($k == 0) echo "<h1>$item</h1>";
if ($k > 0) {
if ($data[0][$k] == 'n' || $data[0][$k] == 'N') {
$rowHtml = "<h2># $item</h2>";
} else {
$html .= $data[0][$k]."<br>";
$html .= "<p>".addLinks(nl2br($item))."</p>";
}
}
}
}
if (empty($rowHtml)) $rowHtml = "<h3># $row</h3>";
echo $rowHtml.$html;
echo '<div class="sticky">'
. '<p align="right">';
if ($row > 1) {
echo '<a href="'.$_SERVER['SCRIPT_NAME'].'?csv='.$csv.'&row='.($row-1).'">Previous</a> | ';
}
if ($row < count($data)-1) {
echo '<a href="'.$_SERVER['SCRIPT_NAME'].'?csv='.$csv.'&row='.($row+1).'"><b>Next »</b></a>';
}
echo '</p></div>';
}
function addLinks($string, $rel='nofollow') {
$host = "([a-z\d][-a-z\d]*[a-z\d]\.)+[a-z][-a-z\d]*[a-z]";
$port = "(:\d{1,})?";
$path = "(\/[^?<>\#\"\s]+)?";
$query = "(\?[^<>\#\"\s]+)?";
return preg_replace("#((ht|f)tps?:\/\/{$host}{$port}{$path}{$query})#i", "<a href=\"$1\" rel=\"{$rel}\">$1</a>", $string);
}
?>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment