I’m trying to read data stored in a csv file and present it in a table, using JavaScript. The csv data (comma delimited) is (I reduced it to be much smaller than the actual one):
Number, PDF1, PDF2, PDF3
0,,,
1,1.pdf,,
2,2a.pdf,2b.pdf,
3,3a.pdf,3b.pdf,3c.pdf
The correspondence between cells in the csv and online is 1 to 1, except 3 last columns (PDF1/2/3). I need them to appear online in the same cell (for each row) as links, separated by space. That is, instead of 3 columns PDF1/2/3 there will be just one, called PDF, containing links to pdfs 1, 2 and 3, if present. The desired output is:
| Number | PDF |
| 0 | |
| 1 | [link>1.pdf] |
| 2 | [link>2a.pdf] [link>2b.pdf] |
| 3 | [link>3a.pdf] [link>3b.pdf] [link>3c.pdf]|
What I have so far:
html:
<span id="output"></span>
JS:
async function fetchCSV(url) {
try {
const response = await fetch(url);
const data = await response.text();
document.getElementById('output').innerText = data;
processData(data);
} catch (error) {
console.error('Error fetching CSV:', error);
}
}
//Link to csv file
fetchCSV('https://blabla/myfile.csv');
//read csv and save contents to variable "lines"
function processData(csv){
var allTextLines = csv.split(/rn|n/);
var lines = [];
var keys = allTextLines.shift().split(','); //first line (headers) of csv
while (allTextLines.length) {
var arr = allTextLines.shift().split(',');
var obj = {};
for(var i = 0; i < keys.length; i++){
obj[keys[i]] = arr[i];
}
lines.push(obj);
}
console.log(lines);
drawOutput(lines);
}
//draw table function drawOutput(lines){
//clear previous data
document.getElementById("output").innerHTML = "";
var table = document.createElement("table");
//first row (cols names) with "th"
var tableHeader = table.insertRow(-1);
Object.keys(lines[0]).forEach(function(key){
if (key == "PDF1") {} //don't show "PDF1" column
else if (key == "PDF2") {} //don't show "PDF2" column
else {
var el = document.createElement("TH");
if (key == "PDF3") {el.innerHTML = "PDF";} //show "PDF3" column as "PDF"
else {el.innerHTML = key;}
tableHeader.appendChild(el);
}
});
//the data (rest of the table)
for (var i = 0; i < lines.length-1; i++) {
var row = table.insertRow(-1);
Object.keys(lines[0]).forEach(function(key){
if (key == "PDF1") {var pdflink1 = lines[i][key];}
else if (key == "PDF2") {var pdflink2 = lines[i][key];}
else if (key == "PDF3") {var pdflink3 = lines[i][key];
var data = row.insertCell(-1);
if (pdflink1 != []) {
var a1 = document.createElement('a');
a1.innerHTML = 'pdf1 ';
a1.href = "dir/" + pdflink1;
data.appendChild(a1);
}
if (pdflink2 != []) {
var a2 = document.createElement('a');
a2.innerHTML = 'pdf2 ';
a2.href = "dir/" + pdflink2;
data.appendChild(a2);
}
if (pdflink3 != []) {
var a3 = document.createElement('a');
a3.innerHTML = 'pdf3';
a3.href = "dir/" + pdflink3;
data.appendChild(a3);}
}
else {
var data = row.insertCell(-1);
data.appendChild(document.createTextNode(lines[i][key]));
}});
}
document.getElementById("output").appendChild(table);
}
Everything seems to work OK, but I’m struggling to “keep” the pdf names in pdflink1 and pdflink2 to put them together with pdflink3 when key == “PDF3” is true. Out of three, only the latter is presented as desired in the output:
| Number | PDF |
| 0 | |
| 1 | [dir/undefined] |
| 2 | [dir/undefined] [dir/undefined] |
| 3 | [dir/undefined] [dir/undefined] [dir/3c.pdf]|
I appreciate any assistance. Thank you.
1
There are a few problems.
Leading spaces in your key names were causing problems. Fixable with .trim()
pdflink1, pdflink2, pdflink3 needed to be moved outside of the forEach()
loop so that their values are available between iterations.
You had two conflicting var data
declarations. I changed the second one to a let
. I would actually recommend you change all of your var
declarations to let
.
Look for EDIT comments in the code snippet for specific changes.
//Link to csv file
// EDIT Changed just for the snippet demo
// fetchCSV('https://blabla/myfile.csv');
async function fetchCSV(url) {
try {
const response = await fetch(url);
const data = await response.text();
document.getElementById('output').innerText = data;
processData(data);
} catch (error) {
console.error('Error fetching CSV:', error);
}
}
//read csv and save contents to variable "lines"
function processData(csv){
var allTextLines = csv.split(/rn|n/);
var lines = [];
var keys = allTextLines.shift().split(','); //first line (headers) of csv
while (allTextLines.length) {
var arr = allTextLines.shift().split(',');
var obj = {};
for(var i = 0; i < keys.length; i++){
// EDIT Leading spaces were causing problems.
// obj key names had a leading space, causing many problems later on with comparisons
obj[keys[i].trim()] = arr[i];
}
lines.push(obj);
}
// console.log(lines);
drawOutput(lines);
}
//draw table
function drawOutput(lines){
//clear previous data
document.getElementById("output").innerHTML = "";
var table = document.createElement("table");
//first row (cols names) with "th"
var tableHeader = table.insertRow(-1);
Object.keys(lines[0]).forEach(function(key){
if (key == "PDF1") {} //don't show "PDF1" column
else if (key == "PDF2") {} //don't show "PDF2" column
else {
var el = document.createElement("TH");
if (key == "PDF3") {el.innerHTML = "PDF";} //show "PDF3" column as "PDF"
else {el.innerHTML = key;}
tableHeader.appendChild(el);
}
});
//the data (rest of the table)
for (var i = 0; i < lines.length-1; i++) {
var row = table.insertRow(-1);
// EDIT Need to move these declaritions outside the for loop
var pdflink1 = ""
var pdflink2 = ""
var pdflink3 = ""
Object.keys(lines[0]).forEach( function(key) {
if (key == "PDF1") {
pdflink1 = lines[i][key];
}
else if (key == "PDF2") {
pdflink2 = lines[i][key];
}
else if (key == "PDF3") {
pdflink3 = lines[i][key];
var data = row.insertCell(-1);
if (pdflink1 != []) {
var a1 = document.createElement('a');
a1.innerHTML = 'pdf1 ';
a1.href = "dir/" + pdflink1;
data.appendChild(a1);
}
if (pdflink2 != []) {
var a2 = document.createElement('a');
a2.innerHTML = 'pdf2 ';
a2.href = "dir/" + pdflink2;
data.appendChild(a2);
}
if (pdflink3 != []) {
var a3 = document.createElement('a');
a3.innerHTML = 'pdf3';
a3.href = "dir/" + pdflink3;
data.appendChild(a3);}
}
else {
// EDIT You had two conflicting var data declarations
let data = row.insertCell(-1);
data.appendChild( document.createTextNode(lines[i][key]) );
}
});
}
document.getElementById("output").appendChild(table);
}
// EDIT Added just for the snippet demo
let csvData = `Number, PDF1, PDF2, PDF3
0,,,
1,1.pdf,,
2,2a.pdf,2b.pdf,
3,3a.pdf,3b.pdf,3c.pdf
`
// EDIT Added these two lines to use instead of fetchCSV(), just for the snippet demo
document.getElementById('output').innerText = csvData;
processData(csvData);
/* EDIT For visualization */
table {
background-color: gray;
border-collapse: collapse;
margin: 10px;
border: solid 2px black;
box-shadow: 4px 4px 10px black;
}
th {
padding: 0.5rem 1rem;
border-bottom: solid 1px black;
}
td {
padding-left: 1rem;
padding-bottom: 0.5rem;
}
th, td {
border-right: solid 1px black;
}
td a {
margin-right: 1rem;
}
<span id="output"></span>
1