Как создать трекер расходов с SheetJS

Знакомство с SheetJS 

Представьте, что вы работаете бухгалтером в крупном супермаркете. По роду своей деятельности вы создаете электронные таблицы, чтобы отслеживать финансовые операции магазина и обрабатывать большие объемы числовых данных. В ваши обязанности входит: 

  • открыть редактор электронных таблиц и внести список продаж за каждый день;  
  • построить график и подсчитать общую прибыль и объем продаж; 
  • применить формулы к данным для аналитических целей; 
  • и наконец, отправить составленный документ руководителю отдела или другим инстанциям. 

Все действия вполне осуществимы. А что если за один день происходят сотни продаж? Тогда вы потратите много сил и времени, поскольку будете снова и снова делать одно и то же. Это проблема, и ее надо как-то решать. 

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

В данной статье на основе терминала мы создадим трекер расходов, который будет добавлять их в файл Excel и подсчитывать общую сумму. Итогом работы станет следующий результат: 

Цель ясна, приступаем к ее реализации! 

Начальный этап

Инициализируем репозиторий проекта с помощью указанной команды терминала: 

mkdir sheet-tutorial #создаем каталог проекта 
cd sheet-tutorial
npm init -y #инициализируем проект
Installation of modules

Установка модулей 

В проекте задействованы модули: 

  • yargs  —  для проектирования интерфейса терминала; 
  • xlsx  —  для взаимодействия с электронными таблицами посредством кода.

Устанавливаем эти зависимости, выполняя данную bash-инструкцию:

npm i yargs xlsx

Создание проекта 

Написание временных данных 

В этом разделе создадим файл Excel, который послужит базой данных для приложения. 

Переходим в корневой каталог проекта, где создаем файл Expenses.xlsx. В нем будут храниться данные о расходах клиента. 

В Expenses.xlsx вводим следующие данные: 

В таблице два заголовка: Category (категория) и Amount (количество)!

Как видно, мы создали два заголовка, а именно Category и Amount, и указали под ними различные пункты расходов и соответствующие им суммы. 

Написание вспомогательных функций 

В проекте создаем файл sheetUtils.js. В этот модуль войдут вспомогательные методы для управления базой данных. 

В sheetUtils.js сначала прописываем данный код: 

const xlsx = require("xlsx");
const path = require("path");

const fileLocation = path.join(__dirname, "Expenses.xlsx");

const fileContents = xlsx.readFile(fileLocation);
const firstSheet = fileContents.SheetNames[0];
const sheetValues = fileContents.Sheets[firstSheet];
const parsedJSON = xlsx.utils.sheet_to_json(sheetValues);

function getParsedJSON() {
return parsedJSON;
}

console.log(getParsedJSON());
  • Строка 4. С помощью модуля path создаем путь к документу Expenses.xlsx.
  • Строки 6–8. Читаем содержимое документа и сохраняем его значение в переменной sheetValues.
  • Строка 9. Преобразуем сохраненные данные в sheetValues в формат JSON, что позволяет легко выполнять арифметические операции. 
  • Строка 15. Выводим значение метода getParsedJSON для целей отладки. 

Проверяем, что получилось! Запускаем программу командой: 

node sheetUtils

Результат:

Как видно, SheetJS вернула массив ранее введенных записей. Кроме того, обратите внимание, что заголовки Category и Amount теперь используются как ключи в объектах JSON. 

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

Для этого дополняем файл sheetUtils.js указанным кодом:

function addEntry(text) {
xlsx.utils.sheet_add_aoa(sheetValues, [text], { origin: -1 }); //свойство 'origin' указывает Node добавить запись в следующую доступную строку
xlsx.writeFile(fileContents, fileLocation);
}
addEntry(["Cake for girlfriend's birthday", 30]);
  • Строка 2. Вспомогательный метод вставляет значение text в виде новой записи на рабочем листе. 
  • Строка 3. Сохраняем измененный документ Expenses.xlsx.
  • Строка 5. Выполняем метод addEntry для внесения нового пункта расходов в файл. 

Получаем вот такой результат в таблице: 

Как видно, SheetJS добавила выбранные данные в электронную таблицу. Это значит, что программа в полном порядке!

Осталось лишь создать функцию, которая будет отображать общую сумму расходов. Для этого добавляем фрагмент кода в sheetUtils.js :

function getTotal() {
const allData = getParsedJSON();
const totalResult = allData
.map((item) => item.Amount)
.reduce((acc, a) => acc + a, 0);
return totalResult;
}
console.log("Current total ", getTotal());
module.exports = { getParsedJSON, addEntry, getTotal };
  • Строка 2. Получаем содержимое электронной таблицы в формате JSON.
  • Строки 3–5. С помощью функции map и reduce извлекаем значения Amount из массива JSON и суммируем их. Сохраняем результат сложения в переменной totalResult
  • Строка 8. Выводим итоговую сумму в консоль. 
  • Строка 9. Экспортируем пользовательские функции для применения в проекте. 

Ниже представлен результат кода:

Программа отлично работает!

Окончательный вариант файла sheetUtils.js выглядит так: 

const xlsx = require("xlsx");
const path = require("path");

const fileLocation = path.join(__dirname, "Expenses.xlsx");

const fileContents = xlsx.readFile(fileLocation);
const firstSheet = fileContents.SheetNames[0];
const sheetValues = fileContents.Sheets[firstSheet];
const parsedJSON = xlsx.utils.sheet_to_json(sheetValues);

function getParsedJSON() {
return parsedJSON;
}

function addEntry(text) {
xlsx.utils.sheet_add_aoa(sheetValues, [text], { origin: -1 });
xlsx.writeFile(fileContents, fileLocation);
}

function getTotal() {
const allData = getParsedJSON();
const totalResult = allData
.map((item) => item.Amount)
.reduce((acc, a) => acc + a, 0);
return totalResult;
}

module.exports = { getParsedJSON, addEntry, getTotal };

Создание CLI

После создания вспомогательных методов переходим к проектированию интерфейса командной строки, тем самым обеспечивая пользователю взаимодействие с программой. 

Сначала создаем файл index.js, в котором прописываем код: 

const yargs = require("yargs/yargs");
const { addEntry, getTotal, getParsedJSON } = require("./sheetUtils");

const argv = yargs(process.argv.slice(2))
.alias("a", "add-amount")
.describe("a", "Add new expense to the table")
.alias("-c", "-category")
.describe("c", "Type of expense")
.command("overview", "Get list of expenses:", () => {
console.log(getParsedJSON());
})
.command("total", "Get total amount", () => {
console.log("Your total is: " + getTotal());
}).argv;
console.log(argv);
  • Строки 4–8. Используем модуль yargs для определения опций add-amount и category. Они позволяют пользователю добавлять новые записи в базу данных. 
  • Строки 9 и 10. Даем описание команды overview. При ее выполнении программа реализует метод getParsedJSON
  • Строки 12 и 13. Определяем команду total, при выполнении которой приложение отображает общую сумму расходов пользователя. 

Время тестировать! Запускаем программу: 

node index --help

Получаем результат:

Теперь необходимо написать дополнительный код для поддержки опций category и add-amount. С этой целью добавляем данные строки в index.js:

//file: index.js
if (argv.a && argv.c) {
addEntry([argv.c, argv.a]);
console.log("Added expense: ", argv.c, argv.a);
}
  • Строка 3. Выполняем метод addEntry и передаем входные данные пользователя в качестве параметров функции. 
  • Строка 4. Сообщаем пользователю о добавлении записей в файл. 

Результат:

Посмотрим, что происходит в файле Expenses.xlsx:

Обратите внимание, что последняя запись успешно добавлена в файл. Это значит, что программа прекрасно работает. 

Цель достигнута! 

Заключение 

Теперь вы знаете, как создать простой трекер расходов с помощью SheetJS. Используя эту удобную библиотеку, вы можете без особого труда работать с электронными таблицами. 

Читайте также:

Читайте нас в TelegramVK и Яндекс.Дзен


Перевод статьи Hussain Arif: Build an Expense Tracker with SheetJS

Предыдущая статьяPHP: типы переменных
Следующая статьяЖизненный цикл разработки на примере сайта