Cуммируем данныe в таблицах с помощью JavaScript

2022-Nov-19

Продолжаем тему таблиц, которую поднимали в статье “Вертикальные заголовки в таблицах”. Давайте сегодня сделаем суммирование в столбцах таблиц на JavaScript. Причем не просто решим задачу суммирования столбца, а напишем универсальный скрипт, позволяющий суммировать любые столбцы вместе и раздельно в разных таблицах.

Подготовка

Любая задача по JavaScript или любой эффект начинается с верстки. От верстки зависит код JS, поэтому уделите максимальное внимание тому, что вы пишите в HTML. В первую очередь решим простую задачу — пусть будет таблица и нужно просуммировать столбец и внизу вывести сумму. Сделаем простую таблицу.

<table class="table table-striped text-center">
<tr>
    <th>Name</th>
    <th>Subject</th>
    <th>Marks</th>
</tr>
<tr>
    <td>Hillary</td>
    <td>Advanced Web</td>
    <td>100</td>
</tr>
<tr>
    <td>Teddy</td>
    <td>Operating Syatem (ttt)</td>
    <td>200</td>
</tr>
<tr>
    <td>Lary</td>
    <td>Advanced Web</td>
    <td>600</td>
</tr>
<tr>
    <td>Bronko</td>
    <td>Operating Syatem (ttt)</td>
    <td>400</td>
</tr>
<tr>
    <td colspan="2" class="text-end">Total:</td>
    <td class="sum-result-1"></td>
</tr>
</table> 
  

В таблице есть столбец Marks сумму которого нужно найти и вывести в Total. Сейчас в Total выводится число 0.

Добавим для ячеек, которые нужно суммировать класс, например .cell-sum, а в результирующий столбец класс .cell-total. Напомню, мы создаем упрощенный вариант суммирования данных в таблице с помощью JavaScript, ниже будет и сложный вариант. Теперь таблица в HTML выглядит так:

<table class="table table-striped text-center">
<tr>
    <th>Name</th>
    <th>Subject</th>
    <th>Marks</th>
</tr>
<tr>
    <td>Hillary</td>
    <td>Advanced Web</td>
    <td class="sum-cell">100</td>
</tr>
<tr>
    <td>Teddy</td>
    <td>Operating Syatem (ttt)</td>
    <td class="sum-cell">200</td>
</tr>
<tr>
    <td>Lary</td>
    <td>Advanced Web</td>
    <td class="sum-cell">600</td>
</tr>
<tr>
    <td>Bronko</td>
    <td>Operating Syatem (ttt)</td>
    <td class="sum-cell">400</td>
</tr>
<tr>
    <td colspan="2" class="text-end">Total:</td>
    <td class="sum-result-1"></td>
</tr>
</table>  

Алгоритм

Алгоритм программы следующий:

  • Получаем все ячейки с классом .cell-sum
  • Создаем переменную total равную нулю
  • С помощью цикла перебираем .cell-sum, извлекаем текст между тегами <td></td> и добавляем в total. Не забудьте перевести в число!!!
  • Выводим в .cell-total значение из переменной total.

Обратите внимание — здесь вместо цикла можно применить reduce.

Реализация

Создайте JavaScript файл и подключите в HTML. Получим все ячейки, значение которых нужно суммировать.

const cellSum = document.querySelectorAll('.cell-sum');

Теперь создадим переменную total и циклом перебираем cellSum:

let total = 0;

for (let i = 0; i < cellSum.length; i++){
    total += +cellSum[i].textContent;
}

console.log(total);

На данном этапе в консоли будет выведена сумма. Если нет — проверьте шаги, описанные выше. Обратите внимание на запись:

total += +cellSum[i].textContent;

Возможно, она вас смущает, распишу подробно (для начинающих разработчиков):

total = total + (+cellSum[i].textContent);

Плюс перед cellSum нужен для перевода в число. И осталось вывести в таблицу результат:

document.querySelector('.cell-total').textContent = total;

Давайте напишем тот же код с reduce:

let total = Array.from(cellSum).reduce((accum, item) => accum += +item.textContent, 0);

Пару строк кода — и теперь суммировать вручную не нужно.

Суммируем любое количество столбцов

Предыдущий код работает если нужно суммировать один столбец, при этом на странице одна таблица. Давайте сделаем решение сумма столбцов таблицы JavaScript более универсальным. Напишем скрипт позволяющий суммировать любое количество ячеек в любых таблицах. Начнем с усложнения таблицы.

<table class="table table-striped text-center">
    <tr>
        <th>Name</th>
        <th>Subject</th>
        <th>Marks</th>
        <th>Bonus</th>
    </tr>
    <tr>
        <td>Hillary</td>
        <td>Advanced Web</td>
        <td class="sum-cell aaa">100</td>
        <td class="sum-cell bbb">30</td>
    </tr>
    <tr>
    <td>Teddy</td>
        <td>Operating Syatem (ttt)</td>
        <td class="sum-cell aaa">200</td>
        <td class="sum-cell bbb">30</td>
    </tr>
    <tr>
    <td>Lary</td>
        <td>Advanced Web</td>
        <td class="sum-cell aaa">600</td>
        <td class="sum-cell bbb">30</td>
    </tr>
    <tr>
    <td>Bronko</td>
        <td>Operating Syatem (ttt)</td>
        <td class="sum-cell aaa">400</td>
        <td class="sum-cell bbb">30</td>
    </tr>
    <tr>
        <td colspan="2" class="text-end">Total:</td>
        <td class="sum-result-1"></td>
        <td class="sum-result-2"></td>
    </tr>
</table>

В те ячейки что необходимо суммировать прописали класс .cell-sum, однако у нас два столбца и их нужно различать. Для различия пропишем еще классы в нужные ячейки. Обратите внимание, классы могут называться как вам угодно. Решение будет реализовывать сумму по прописанным классам. Для ячейки куда будем выводить сумму пропишем классы .total-sum-a, .total-sum-b, однако в названии классов никаких ограничений нет. Главное — чтобы вы могли привязаться к выводу.

Алгоритм решения

Давайте решать задачу.

  • Получаем все ячейки с классом .cell-sum
  • Создаем переменную total, которая теперь будет равна пустому объекту {} ведь сумм будет несколько.
  • С помощью цикла перебираем .cell-sum и получаем первую ячейку. Затем с помощью еще одного цикла перебираем все классы данной ячейки. Проверяем, если в объекте result уже есть запись с таким классом — то суммируем к ней значение из ячейки. Если нет — создаем со значением из ячейки.
  • Выводим в .cell-total значение из переменной total с нужными ключами.

Звучит сложно, но на практике все проще. Главное понять алгоритм. Берем класс ячейки и проверяем — есть ли в result запись с таким ключом? Если есть — добавляем к ней число из текущей ячейки. Если нет — создаем запись со значением из текущей ячейки. По факту получаем объект с кучей сумм. Реализуем:

let result = {};

for (let i = 0; i < sumCell.length; i++) {
    let classes = sumCell[i].classList;
    for (let k = 0; k < classes.length; k++) {
        let currentClass = classes[k];
        if (currentClass in result) {
            result[currentClass] += +sumCell[i].textContent;
        }
        else {
            result[currentClass] = +sumCell[i].textContent;
        }
    }
}

И теперь в консоли видно, что result это объект, где под указанными ключами лежит сумма из ячеек.

result = {
    cell-sum: 4960,
    sum-a: 480,
    sum-b: 4000
}

Осталось только вывести нужную сумму в нужную ячейку.

Решение универсальное, не зависит от количества таблиц, работает с любым количеством столбцов. Требование — на ячейке должен быть класс .cell-sum и любой класс для идентификации.

Загрузить файл с кодом: Download

Статьи

Кнопка "Показать пароль" на JavaScript + анимация
Задача собеседования: получаем email из строки
Вертикальный текст в заголовках таблиц HTML + CSS