Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Display comma separated string in HTML as a table / csv format

I have a string that I've built in my Typescript file that's comma separated. This can be exported as a 'file.csv' and everything is displayed correctly once downloaded.

What I would like to achieve is creating a "preview" of this string before it's downloaded. I would like the preview to resemble that of a HTML Table, or how it would appear in a CSV.

Example String

1,Header1, Header2, Header3, Header4,
2,0,1,"Content","More Content","

Naturally, in a CSV this would appear the same as the above but separated within borders / cells.

Is it possible to achieve this in HTML?


2 Answers

Here's an example I created on stackblitz: https://stackblitz.com/edit/angular-k162aa

The main CSV parsing function is described below with inline comments:

// CSV is assumed to have headers as well
csvToJSON(csv: string) {

  const lines: string[] = csv
    // escape everything inside quotes to NOT remove the comma there
    .replace(/"(.*?)"/gm, (item) => encodeURIComponent(item))
    // split by lines
    .split('\n');

  // separate the headers from the other lines and split them
  const headers: string[] = lines.shift().split(',');

  // should contain all CSV lines parsed for the html table
  const data: any[] = lines.map((lineString, index) => {
    const lineObj = {};

    const lineValues = lineString.split(',');

    headers.forEach((valueName, index) => {
      // remove trailing spaces and quotes
      lineObj[valueName] = lineValues[index]
        // handle quotes
        .replace(/%22(.*?)%22/gm, (item) => decodeURIComponent(item))
        // trim trailing spaces
        .trim();
    })

    return lineObj; // return lineValues for array representation.
  }); 

  return { data, headers };
}

csvToJSON(csv: string) {

  const lines: string[] = csv.split('\n');

  // separate the headers from the other lines and split them
  const headers: string[] = lines.shift().split(',');

  // should contain all CSV lines parsed for the html table
  const data: string[][] = lines.map((lineString, index) => {
    const lineObj = {};

    const lineValues = lineString.split(',');

    headers.forEach((valueName, index) => {
      lineObj[valueName] = lineValues[index];
    });

    return lineObj; // return lineValues for an array.
  }); 

  return { data, headers };
}

Notice that the commented code can give you an array of arrays, while the code as is, returns an array of objects.

In the HTML, this format is easier to render since the index of the headers is the same as the index of each item array:

<table class="table">
  <thead>
    <tr>
      <th *ngFor="let header of headers">{{ header }}</th>
    </tr>
  </thead>
  <tbody>
    <tr *ngFor="let row of data">
      <td *ngFor="let header of headers">
        {{ row[header] }}
      </td>
    </tr>
  </tbody>
</table>

To support row headers, you can use the following html snippet for the table body section:

<tr *ngFor="let row of data">
  <ng-container *ngFor="let attribute of row; let i = index">
    <td *ngIf="i">{{ attribute }}</td>
    <th *ngIf="!i">{{ attribute }}</th>
  </ng-container>
</tr>
like image 173
Thatkookooguy Avatar answered Mar 29 '26 04:03

Thatkookooguy


Your question actually mixes two concerns,

  1. parsing the csv and
  2. presenting its data.

Each of the above tasks has its own pitfalls and while it is quite easy to create a simple parser and rendering code it is much easier to avoid future pain by using third party code specialized in these tasks. If you choose well (yes, there are plenty of options) you won't have to worry about covering boundary conditions, size limitations, performance bottlenecks, error handling, XSS vulnerabilities (injected from the data but you should assess library vulnerabilities).

If it was my project I would go with something like Papa Parse and DataTables for parsing and presentation. Check DataTables csv import example page: https://editor.datatables.net/examples/extensions/import

If, on the other hand, you want the challenge to work on all these and you are sure the data will always behave then by all means write you own code!

like image 34
Victor Ortuondo Avatar answered Mar 29 '26 04:03

Victor Ortuondo