Отримуємо суму чисел у таблиці з JavaScript

Продовжуємо тему таблиць, яку піднімали у статті Вертикальні заголовки в таблицях. Давайте сьогодні зробимо скріпт, який знаходить сумму чисел у стовпчиках чи рядках таблиці за допомогою JavaScript. Причому не просто розв'яжемо завдання знайти суму стовпця, а напишемо універсальний скріпт, що дозволяє находити суми будь-яких стовпців та рядків у різних таблицях.
Підготовка
Будь-яке завдання JavaScript, або будь-який ефект починається з HTML структури сторінки. Від HTML залежить код 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>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.
Додамо для клітинок, суму яких шукаємо, CSS клас, наприклад .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. Не забудьте перевести до числа!
- Виводимо в .sum-result-1 значення із змінної 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('.sum-result-1').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 з потрібними ключами.
Cкладно? Але на практиці все простіше. Головне зрозуміти алгоритм. Беремо клас клітинки і перевіряємо — чи є у 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 та будь-який клас для ідентифікації.