1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213
|
---
title: Tabulate CSV Data
author: MichaelCurrin
date: 2020-04-01 20:30:00 +0200
---
This tutorial shows how to use Jekyll to read a CSV and render the data as an HTML table.
This approach will:
- use the CSV's first row as the HTML table header.
- use remaining rows for the body of the table.
- preserve the order of the columns from the original CSV.
- be flexible enough to work with _any_ valid CSV that is referenced.
There is no need to specify what the names of the columns are, or how many columns there are.
The trick to this tutorial is that, when we iterate over the row data, we pick up the _first row_
and unpack that so we can get the header names.
Follow the steps below to convert a sample CSV of authors into an HTML table.
## 1. Create a CSV
Create a CSV file in your [Data files]({{ '/docs/datafiles/' | relative_url }}) directory so
that Jekyll will pick it up. A sample path and CSV data are shown below:
`_data/authors.csv`
```
First name,Last name,Age,Location
John,Doe,35,United States
Jane,Doe,29,France
Jack,Hill,25,Australia
```
That data file will now be available in Jekyll like this:
{% raw %}
```liquid
{{ site.data.authors }}
```
{% endraw %}
## 2. Add a table
Choose an HTML or markdown file where you want your table to be shown.
For example: `table_test.md`
```yaml
---
title: Table test
---
```
### Inspect a row
Grab the first row and see what it looks like using the `inspect` filter.
{% raw %}
```liquid
{% assign row = site.data.authors[0] %}
{{ row | inspect }}
```
{% endraw %}
The result will be a _hash_ (an object consisting of key-value pairs) which looks like this:
```ruby
{
"First name"=>"John",
"Last name"=>"Doe",
"Age"=>"35",
"Location"=>"United States"
}
```
Note that Jekyll _does_ in fact preserve the order here, based on the original CSV.
### Unpack a row
A simple solution would be to hardcode the field names when looking up the row values by key.
{% raw %}
```liquid
{{ row["First name"] }}
{{ row["Last name"] }}
```
{% endraw %}
But we prefer a solution that will work for _any_ CSV, without specifying the column names upfront.
So we iterate over the `row` object using a `for` loop:
{% raw %}
```liquid
{% assign row = site.data.authors[0] %}
{% for pair in row %}
{{ pair | inspect }}
{% endfor %}
```
{% endraw %}
This produces the following. Note the first item in each pair is the _key_ and the second will be
the _value_.
```
["First name", "John"]
["Last name", "Doe"]
["Age", "35"]
["Location", "United States"]
```
### Create a table header row
Here we make a table with a single table row (`tr`), made up of table header (`th`) tags. We find
the header name by getting the first element (at index `0`) from `pair`. We ignore the second
element as we don't need the value yet.
{% raw %}
```liquid
<table>
{% for row in site.data.authors %}
{% if forloop.first %}
<tr>
{% for pair in row %}
<th>{{ pair[0] }}</th>
{% endfor %}
</tr>
{% endif %}
{% endfor %}
</table>
{% endraw %}
```
For now, we do not display any content from the second row onwards. We achieve this by using
`forloop.first`, since this will return true for the _first_ row and false otherwise.
### Add table data rows
In this section we add the data rows to the table. Now, we use the second element of `pair`
to find the value.
For convenience, we render using the `tablerow` tag - this works like a `for` loop, but the inner
data will be rendered with `tr` and `td` HTML tags for us. Unfortunately, there is no equivalent for
the header row, so we must write that out in full, as in the previous section.
{% raw %}
```liquid
---
title: Table test
---
<table>
{% for row in site.data.authors %}
{% if forloop.first %}
<tr>
{% for pair in row %}
<th>{{ pair[0] }}</th>
{% endfor %}
</tr>
{% endif %}
{% tablerow pair in row %}
{{ pair[1] }}
{% endtablerow %}
{% endfor %}
</table>
```
{% endraw %}
With the code above, the complete table would look like this:
<table>
<tr>
<th>First name</th>
<th>Last name</th>
<th>Age</th>
<th>Location</th>
</tr>
<tr>
<td>John</td>
<td>Doe</td>
<td>35</td>
<td>United States</td>
</tr>
<tr>
<td>Jane</td>
<td>Doe</td>
<td>29</td>
<td>France</td>
</tr>
<tr>
<td>Jack</td>
<td>Hill</td>
<td>25</td>
<td>Australia</td>
</tr>
</table>
That's it - you can now turn a CSV into an HTML table using Jekyll.
## Next steps
- Change the field names in the CSV.
- Choose a different CSV.
- Add CSS styling to your table.
- Render the table using a JSON or YAML input file.
|