Calculate values inside DataTable populated by CMS

Hello!
So, I have a datatable where wich row is populataded by a CMS collection. I need it to be a datatable because I want the user to be able do download csv, pdf and print it.
My question is because I’m tring to perform some calculations inside 3 cells on each row.
I’ve tried a bunch of sollutions I found here but I can’t make it work.
Right now on the read-only link, I have a function running inside of a HTML Embed on each row, naming each function differently based on the cms… but it doesn’t work.
Also, I need the cells to be populated in a way that datatble interprets it and show it in pdf and xls.


Here is my site Read-Only: LINK
(how to share your site Read-Only link)

A few tips that should help point you in the right direction.

  • If by “datatable” you mean a <table> element, with <tr>, <td> etc, then that’s not actually relevant to any of the goals you’ve stated ( csv, pdf, print, calcs ). It’s also much harder to make responsive.
  • Whether you use table elements or a divs arrangement, your calcs are pretty easy. I’d recommend you do them outside of the table, iterate through your rows and render your calcs, that’s much cleaner than embedding code bits.
  • Printing is a browser function, you can use some custom CSS to make the printable view more specifically print-friendly.
  • PDF can be generated by a 3rd party lib, which will work 100% client-side using a canvas.
  • CSV download can also be done with client side code but it’s something of a hack in my view. You basically have to generate the CSV content, MIME-encode it and then push it into a link element that will trigger the download. I have concerns on whether there are URL length limits here, but otherwise, it’s a workable approach for smaller CSV’s. Larger CSV’s may require a server-side piece here.

Also, I’d dig heavily into the datatables .net library because it has a nice UX on top of everything, and may have some specific hooks for calculation rendering, CSV and PDF export.

https://datatables.net/

1 Like

hi @tizanata as @memetican mentioned you better will be using anything but table. Not big deal with table but there are better options.

Here is some starting point I have done now. I have an easy calculation on each.row than there is a total sum of rows values and finally simple export to CSV.

feel free to customise it to you needs. Only be were that the CSV export doesn’t work in Codepen but works in index.html

Good luck

1 Like

That’s awesome! Thank you for the time @Stan .
So, if I don’t want the fields to be editable (the numbers will be populated via cms) and the hole thing to look like a table (spreadsheet), can I still use the form and just style it like a table with borders, header and stuff?

Thanks @memetican! I’ll use a different approach and mess around with the pdf download.

So it will be very similar approach @tizanata, you can replace inputs with text field like you have in your project. My example was only to show how it can be done and you need only one function process these data if there will be an identical math logic.

Like I have mentioned it is only starting point you develop from this idea.

EDIT

here is simple version with HTML Table to study

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      .row {
        display: flex;
        gap: 1rem;
        margin-bottom: 16px;
      }

      input {
        width: 100px;
        font-size: 2rem;
      }

      p {
        font-size: 2rem;
        width: 100px;
        border: 1px solid #000;
        padding: 5px;
        height: 100%;
        margin: 0;
      }
    </style>
  </head>
  <body>
    <table>
      <thead>
        <th>Input 1</th>
        <th>Input 2</th>
        <th>Result</th>
      </thead>
      <tbody>
        <tr>
          <!-- table row data - Value comes from CMS -->
          <td data-value-1>10</td>
          <!-- table row data - Value comes from CMS -->
          <td data-value-2>0.25</td>
          <td data-result>result</td>
        </tr>
        <tr>
          <!-- table row data - Value comes from CMS -->
          <td data-value-1>24</td>
          <!-- table row data - Value comes from CMS -->
          <td data-value-2>0.8</td>
          <td data-result>result</td>
        </tr>
      </tbody>
    </table>
    <button onclick="exportCsv()">Export</button>
  </body>
</html>

<script>
  // get value from table row td 1 and td 2
  const rows = document.querySelectorAll("tr");

  rows.forEach((row) => {
    // get elements from table row
    const val_1 = row.querySelector("td[data-value-1]")?.textContent;
    const val_2 = row.querySelector("td[data-value-2]")?.textContent;
    let result = row.querySelector("td[data-result]");

    // calculate result and round it to 2 decimals
    let calc = (Number(val_1) * Number(val_2)).toFixed(2);

    // check if result is not null
    if (result) {
      // set result to td
      result.textContent = calc;
    }
  });

// export to CSV
  function exportCsv() {
    rows.forEach((row) => {
      // get elements from table row
      const val_1 = row.querySelector("td[data-value-1]")?.textContent;
      const val_2 = row.querySelector("td[data-value-2]")?.textContent;
      let result = row.querySelector("td[data-result]") ;

      // calculate result and round it to 2 decimals
      let calc = (Number(val_1) * Number(val_2)).toFixed(2);

      // check if result is not null
      if (result) {
        // set result to td
        result.textContent = calc;
      }
    });

    const csv = Array.from(rows)
      .map((row) => {
        // get elements from table row
        const val_1 = row.querySelector("td[data-value-1]")?.textContent;
        const val_2 = row.querySelector("td[data-value-2]")?.textContent;
        let result = row.querySelector("td[data-result]");

        // calculate result and round it to 2 decimals
        let calc = (Number(val_1) * Number(val_2)).toFixed(2);

        // check if result is not null
        if (result) {
          // set result to td
          result.textContent = calc;
        }

        return `
        ${val_1},${val_2},${calc}`;
      })
      .join("\n");

    const blob = new Blob([csv], { type: "text/csv" });
    const url = URL.createObjectURL(blob);
    const a = document.createElement("a");
    a.href = url;
    a.download = "data.csv";
    a.click();
  }



</script>