Это пятая статья в серии, в которой мы научимся использовать мощную логику такого языка программирования, как JavaScript, для управления данными электронных таблиц.
В этой статье мы поговорим о том, как читать и анализировать файлы XSLX с помощью JavaScript в Node.js.
Теперь, когда вы понимаете, как Node.js можно использовать для чтения файлов на жестком диске и как вы можете создавать команды для интерфейса командной строки (CLI), давайте узнаем, как читать файлы, сохраненные Microsoft Excel.
Вы, безусловно, можете использовать fs.readFile()
для чтения файла XLSX и написания кода для анализа данных, найденных в нем. Однако это еще один случай, когда очень умные люди уже проделали эту сложную работу и создали на ее основе пакет npm.
Пакет, который мы будем использовать, называется ExcelJS. Установите его сейчас.
npm i exceljs
Требовать это вверху index.js
const exceljs = require("exceljs");
Под нашей первой командой добавьте еще одну.
// A Commander command for listing first column of first sheet commander.program .command("listFirstCol <path>") .description("List first sheet column A") .action(listFirstColAction);
action
здесь будет вызывать listFirstColAction()
, которого еще не существует. Идите и создайте это.
// Function for reading XLSX, logging first column of first sheet function listFirstColAction(path) { // List logic here }
Читая документацию по ExcelJS, я вижу, что чтение файлов XLSX происходит так:
// Create an instance of workbook to load data into const workbook = new exceljs.Workbook(); // Read the file workbook.xlsx.readFile(path) { .then(function(book) { // Do something with the workbook }); }
Если у вас есть ссылка на книгу в переменной book
, вы можете получить конкретный лист.
// Get reference to first worksheet const sheet = book.getWorksheet(1);
И, наконец, вы можете записать значения первого столбца в консоль.
// Log the values of first column console.log(sheet.getColumn(1).values);
Вы можете заметить, что некоторые части ExcelJS индексируются по одному. В этом отличие от нативного JavaScript, который имеет нулевую индексацию. Первый лист имеет индекс 1. Первый столбец имеет индекс 1.
Вся функция listFirstColAction()
выглядит так:
// Function for reading XLSX, logging first column of first sheet function listFirstColAction(path) { // Create an instance of workbook to load data into const workbook = new exceljs.Workbook(); // Read the file workbook.xlsx.readFile(path) .then(function(book) { // Get reference to first worksheet const sheet = book.getWorksheet(1); // Log the values of first column console.log(sheet.getColumn(1).values); }); }
Если вам интересно, почему мы должны использовать .then()
после чтения файла, это просто соглашение, которое использует ExcelJS. Это популярный шаблон, который называется "обещания", и он является альтернативой шаблону обратного вызова, который мы использовали ранее. Не все библиотеки JavaScript используют обещания, и не все также используют обратные вызовы. Однако некоторые даже поддерживают и то, и другое!
В любом случае выполнение этой команды дает ожидаемый результат.
Вот как выглядит полный index.js
. Он становится приличного размера.
// Require outside packages const fs = require("fs"); const commander = require("commander"); const exceljs = require("exceljs"); // Function for taking a file path and logging the contents function logAction(path) { // Used as a callback when a file is read function readFileCallback(err, data) { if (err !== null) { switch (err.code) { case "ENOENT": console.error("That file doesn't exist."); break; default: console.error(err.message); } } else { // Convert the file's data buffer to a string const fileContents = data.toString(); // Log the file contents console.log(fileContents); } } // Read the file at the path fs.readFile(path, "", readFileCallback); } // Function for reading XLSX, logging first column of first sheet function listFirstColAction(path) { // Create an instance of workbook to load data into const workbook = new exceljs.Workbook(); // Read the file workbook.xlsx.readFile(path) .then(function(book) { // Get reference to first worksheet const sheet = book.getWorksheet(1); // Log the values of first column console.log(sheet.getColumn(1).values); }); } // A Commander command for reading files and logging the contents commander.program .command("log <path>") .description("Log a text file to the console") .action(logAction); // A Commander command for listing first column of first sheet commander.program .command("listFirstCol <path>") .description("List first sheet column A") .action(listFirstColAction); // Parse the CLI arguments with Commander commander.program.parse(process.argv);
Это более 60 строк кода, включая комментарии. Несмотря на то, что файлы исходного кода обычно превышают это количество строк, я все же вижу некоторую ценность в разделении нашего кода на логические разделы в настоящее время.
logAction()
и listFirstColAction()
можно переместить в свои файлы.
Создайте новую папку с именем actions
. Внутри него создайте два файла с именами log
и listFirstcol
.
Вырежьте всю функцию logAction()
и вставьте ее в actions/log.js
.
Нам нужно указать Node.js «экспортировать», что эту функцию следует «экспортировать» из файла каждый раз, когда она «требуется» в другом файле. Просто добавьте module.exports =
перед определением функции.
module.exports = function logAction(path) { // ... snip ... };
Поскольку эта функция использует fs
, мы должны убедиться, что она требуется в верхней части этого файла. Добавьте требование вверху файла.
// Require outside packages const fs = require("fs");
Весь файл actions/log.js
выглядит так:
// Require outside packages const fs = require("fs"); // Function for taking a file path and logging the contents module.exports = function logAction(path) { // Used as a callback when a file is read function readFileCallback(err, data) { if (err !== null) { switch (err.code) { case "ENOENT": console.error("That file doesn't exist."); break; default: console.error(err.message); } } else { // Convert the file's data buffer to a string const fileContents = data.toString(); // Log the file contents console.log(fileContents); } } // Read the file at the path fs.readFile(path, "", readFileCallback); };
Повторите этот же процесс для actions/listFirstCol.js
, помня, что он не использует fs
пакет, но использует exceljs
.
// Require outside packages const exceljs = require("exceljs"); // Function for reading XLSX, logging first column of first sheet module.exports = function listFirstColAction(path) { // Create an instance of workbook to load data into const workbook = new exceljs.Workbook(); // Read the file workbook.xlsx.readFile(path) .then(function(book) { // Get reference to first worksheet const sheet = book.getWorksheet(1); // Log the values of first column console.log(sheet.getColumn(1).values); }); };
Теперь, когда index.js
не использует ни fs
, ни exceljs
, вы можете удалить для них require
строки.
Поскольку мы переместили каждое из наших двух действий в отдельные файлы, index.js
теперь намного меньше.
// Require outside packages const commander = require("commander"); // A Commander command for reading files and logging the contents commander.program .command("log <path>") .description("Log a text file to the console") .action(logAction); // A Commander command for listing first column of first sheet commander.program .command("listFirstCol <path>") .description("List first sheet column A") .action(listFirstColAction); // Parse the CLI arguments with Commander commander.program.parse(process.argv);
Но если вы попытаетесь запустить программу, вы увидите ошибку.
logAction
используется в нашей программе, но нигде не определен. Верно, потому что мы его переместили.
Мы можем просто require
это из сохраненного файла. Сделайте это для обоих действий.
// Require outside packages const commander = require("commander"); const logAction = require("./actions/log"); const listFirstColAction = require("./actions/listFirstCol");
Сохраните файл, попробуйте еще раз, и он работает!
В этой статье мы узнали, как читать и анализировать файлы XLSX с помощью ExcelJS. Пока что мы использовали лишь очень небольшой набор функций из этого пакета. Вы можете подумать о том, чтобы прочитать документацию и увидеть все, что умеет ExcelJS.
В следующей статье мы попытаемся сгенерировать некоторые сводные данные из нашей электронной таблицы.