Skip to content

Get HTML Table Data into Bar Chart

I’ve been messing around with some database data that I’ve imported into an HTML table. Then I decided that I needed to get that data into a bar chart.

Is there a way I can do this? If so can you show me how to do so?

HTML (warning code snippet doesn’t actually work here, but it does in my application):

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
         pageEncoding="ISO-8859-1"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
    <div>
        <a href="http://localhost:8088">Go Back</a>
    </div>
</head>
<body>
<table id = "tableContent">
    <thead>
    <tr>
        <th>Region</th>
        <th>Total Cases</th>
    </tr>
    </thead>
    <tbody>
    <c:forEach var = "covid_table" items ="${covidapi}">
        <tr>
            <td>${covid_table.getName()}</td>
            <td>${covid_table.getTotal_cases()}</td>
        </tr>
    </c:forEach>
    </tbody>
</table>
</body>
</html>

Here’s the HTML code I used in the working version

New HTML CODE:

<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
    <div>
        <a href="http://localhost:8088">Go Back</a>
    </div>
    <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
    <script src="https://code.highcharts.com/highcharts.js"></script>
    <script src="https://code.highcharts.com/modules/data.js"></script>
    <script src="https://code.highcharts.com/modules/exporting.js"></script>
    <script src="https://code.highcharts.com/modules/export-data.js"></script>
    <script type="text/javascript">
        $(function() {
            Highcharts.chart('container', {
                data: {
                    table: 'tableContent'
                },
                chart: {
                    type: 'column'
                },
                title: {
                    text: 'Data extracted from a HTML table in the page'
                },
                yAxis: {
                    allowDecimals: false,
                    title: {
                        text: 'Units'
                    }
                },
                tooltip: {
                    formatter: function() {
                        return '<b>' + this.series.name + '</b><br/>' +
                            this.point.y + ' ' + this.point.name.toLowerCase();
                    }
                }
            });
        });
    </script>
</head>
<body>
<div id="container" style="width: 100%; height: 400px;"> </div>
<table id = "tableContent">
    <thead>
    <tr>
        <th>Region</th>
        <th>Total Cases</th>
    </tr>
    </thead>
    <tbody>
    <c:forEach var = "covid_table" items ="${covidapi}">
        <tr>
            <td>${covid_table.getName()}</td>
            <td>${covid_table.getTotal_cases()}</td>
        </tr>
    </c:forEach>
    </tbody>
</table>
</body>
</html>

Answer

If you have the data from the API, then what you need to change is the presentational layer.

Here’s a small snippet that works with a set of data (it’s a fully JavaScript solution):

const fetchData = async() => {
  const response = await fetch('https://jsonplaceholder.typicode.com/todos')
  const json = await response.json()
  return json
}
const thead1 = document.querySelector('#table > thead')
const tbody1 = document.querySelector('#table > tbody')
const headerHtml = (items) => {
  let html = ''
  html += '<tr><th></th>'
  Object.keys(items[0]).forEach(header => {
    html += `<th>${ header }</th>`
  })
  html += '</tr>'
  return html
}
const bodyHtml = (items) => {
  let html = ''
  items.forEach(item => {
    html += '<tr>'
    html += '<td></td>'
    for (let key in item) {
      html += `<td>${ item[key] }</td>`
    }
    html += '</tr>'
  })
  return html
}
(async function() {
  // get data from the API
  const response = await fetchData()
  // transform data for our requirements
  let transformed = response.reduce((a, c) => {
    if (typeof a[c.userId] === "undefined") a[c.userId] = 0
    a[c.userId] += 1
    return a
  }, {})
  let data = Object.entries(transformed).map(([id, val]) => ({
    id,
    val
  }))
  thead1.innerHTML = headerHtml(data)
  tbody1.innerHTML = bodyHtml(data)
  // create chart:
  Highcharts.chart('container', {
    data: {
      table: 'table'
    },
    chart: {
      type: 'column'
    },
    title: {
      text: 'Data extracted from a HTML table in the page'
    },
    yAxis: {
      allowDecimals: false,
      title: {
        text: 'Units'
      }
    },
    tooltip: {
      formatter: function() {
        return `
          <b>${ this.series.name }</b>
        `
      }
    }
  });
})();
#table {
  border-collapse: collapse;
  border: 1px solid #cacaca;
  width: 200px;
}
#table tr,
#table th,
#table td {
  border: 1px solid #6f6f6f;
}
#table th {
  background: #cacaca;
}
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/data.js"></script>
<script src="https://code.highcharts.com/modules/exporting.js"></script>
<script src="https://code.highcharts.com/modules/export-data.js"></script>
<table id="table">
  <thead>
  </thead>
  <tbody>
  </tbody>
</table>
<hr />
<div id="container"></div>