paint-brush
Импорт и экспорт Excel XLSX с использованием Vue: руководствок@mesciusinc
246 чтения

Импорт и экспорт Excel XLSX с использованием Vue: руководство

к MESCIUS inc.17m2024/06/26
Read on Terminal Reader

Слишком долго; Читать

Узнайте, как импортировать и экспортировать файлы Excel XLSX в приложении Vue.
featured image - Импорт и экспорт Excel XLSX с использованием Vue: руководство
MESCIUS inc. HackerNoon profile picture

«Выглядит великолепно, но не могли бы вы просто добавить импорт из Excel?»


Если вы давно занимаетесь разработкой программного обеспечения, то наверняка не раз слышали этот вопрос от менеджера. Для людей, не разбирающихся в технических вопросах, запрос на импорт/экспорт Excel не кажется чем-то большим. Как это может быть сложно, правда?


Но слишком часто этот вопрос вселяет страх в сердца разработчиков. На большинстве платформ работа с файлами Excel требует больших усилий. Исторически сложилось так, что в Интернете это было вдвойне верно. Работа с данными Excel в веб-приложении немного напоминает этот комикс xkcd : «Может быть сложно объяснить разницу между простым и практически невозможным». Создание собственной электронной таблицы в браузере с помощью импорта и экспорта Excel кажется проблемой, на решение которой потребуется пять лет и исследовательская группа.


Это меняется. Теперь у нас есть готовые библиотеки, которые позволяют вам добавить полностью функционирующую электронную таблицу в ваше веб-приложение. SpreadJS — один из них. Мы рассмотрим, как взять существующее приложение Vue — реальное приложение, использующее хранилище Vuex — и улучшить его с помощью SpreadJS.


В остальной части статьи предполагается, что вы уже понимаете HTML, CSS и JavaScript. Также предполагается, что у вас есть практические знания прогрессивной платформы JavaScript Vue.js для создания веб-интерфейса. Будет полезно, если вы использовали Vuex для управления состоянием, но не волнуйтесь, если вы этого не сделали. Он интуитивно понятен и прост для понимания, и вы сможете понять, что происходит, просто прочитав код, если вы использовали Vue.


В этом блоге мы расскажем, как добавить импорт и экспорт Excel в ваше приложение Vue, выполнив следующие действия:


  1. Структура приложения Vue
  2. Добавьте SpreadJS в свое приложение Vue
  3. Добавить экспорт в Excel
  4. Добавить импорт Excel
  5. Проверьте свое приложение Vue

Приложение Vue

Приложение Vue, над которым мы будем работать, представляет собой простую панель управления продажами с несколькими сводными панелями и таблицей данных. Это приложение из категории «неплохих»:


Панель продаж Vue


Хотя это всего лишь демо-версия, это именно то приложение, которое должны создавать корпоративные веб-разработчики. Это также именно то приложение, в которое нас обычно просят добавить функциональность Excel, поэтому оно станет прекрасным примером для оставшейся части этой статьи.


Код этого приложения можно найти здесь .


Если вы хотите узнать, как создать приложение Vue с нуля, ознакомьтесь с этим кратким руководством .


Чтобы подготовить почву, панель мониторинга представляет собой одностраничное приложение, созданное с помощью Vue. Он использует новейшие и лучшие лучшие практики Vue : однофайловые компоненты и хранилище данных Vuex. Он также использует Bootstrap для своих CSS-компонентов и системы сеток.


Bootstrap не так популярен, как раньше, но на самом деле Bootstrap по-прежнему повсюду — особенно в корпоративных веб-приложениях, где обычно требуется поддержка Excel. Мы готовы поспорить, что множество новых корпоративных веб-приложений по-прежнему будут использовать Bootstrap в 2030 году.


Если вы предпочитаете использовать Bulma или Tachyons в своих приложениях с поддержкой электронных таблиц, вперед! SpreadJS будет хорошо работать с любым из них.

Структура приложения Vue

Давайте посмотрим, как структурирован код. Наше хранилище Vuex и приложение Vue определены в main.js. У нас есть несколько однофайловых компонентов Vue, все они расположены в папке компонентов.


Если вы посмотрите наш магазин Vuex, вы увидите следующее:


 const store = new Vuex.Store({ state: { recentSales } mutations: { UPDATE_RECENT_SALES(state) { state.recentSales.push([]); state.recentSales.pop(); } } });


Исходное состояние нашего магазина установлено в значение недавних продаж — набора фиктивных данных, которые мы импортировали. У нас также есть функция, которая обрабатывает обновление последних продаж при их изменении.


Подождите минуту. Если у нас есть только один набор данных, как нам создать три диаграммы и таблицу? Чтобы увидеть, что происходит, откройте компонент Dashboard.vue . В нем вы увидите, что на основе данных в хранилище Vuex генерируются несколько вычисляемых свойств:


 <template> <div style="background-color: #ddd"> <NavBar title="Awesome Dashboard"/> <div class="container"> <div class="row"> <TotalSales :total="totalSales"/> <SalesByCountry :salesData="countrySales"/> <SalesByPerson :salesData="personSales"/> <SalesTable :tableData="salesTableData"/> </div> </div> </div> </template> <script> import NavBar from "./NavBar"; import TotalSales from "./TotalSales"; import SalesByCountry from "./SalesByCountry"; import SalesByPerson from "./SalesByPerson"; import SalesTable from "./SalesTable"; import { groupBySum } from "../util/util"; export default { components: { NavBar, SalesByCountry, SalesByPerson, SalesTable, TotalSales }, computed: { totalSales() { const items = this.$store.state.recentSales; const total = items.reduce((acc, sale) => (acc += sale.value), 0); return parseInt(total); }, chartData() { const items = this.$store.state.recentSales; const groups = groupBySum(items, "country", "value"); return groups; }, personSales() { const items = this.$store.state.recentSales; const groups = groupBySum(items, "soldBy", "value"); return groups; }, salesTableData() { return this.$store.state.recentSales; }, } }; </script>


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


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

Добавление SpreadJS в ваше приложение Vue

Вот где начинается веселье! У нас есть панель мониторинга, но мы хотим избавиться от этой неуклюжей старой HTML-таблицы. Итак, нам придется немного изменить ситуацию. У нас есть отличная отправная точка, но мы должны запустить наше приложение локально, чтобы использовать SpreadJS в режиме разработки без лицензии.


Вы можете скачать готовый код, чтобы увидеть конечный результат.


Начните с открытия исходного проекта без SpreadJS. Откройте терминал, перейдите в каталог, в котором вы клонировали репозиторий, и запустите «npm install». При этом устанавливаются зависимости, необходимые для запуска приложения. Когда установка зависимостей завершится, запустите npmserve, чтобы увидеть обновленное приложение в действии. Если вы хотите специально импортировать используемые библиотеки, вы можете использовать эту команду:


 npm install @mescius/spread-sheets @mescius/spread-sheets-vue @mescius/spread-excelio file-saver bootstrap


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


 <template> <TablePanel title="Recent Sales"> </TablePanel> </template>


После удаления таблицы у нас есть готовая панель таблицы и ожидание электронной таблицы, поэтому давайте добавим ее! После добавления листа SpreadJS наш шаблон будет выглядеть так:


 <template> <TablePanel title="Recent Sales"> <gc-spread-sheets :hostClass='hostClass' @workbookInitialized='workbookInit'> <gc-worksheet :dataSource='tableData' :autoGenerateColumns='autoGenerateColumns'> <gc-column :width='50' :dataField="'id'" :headerText="'ID'" :visible = 'visible' :resizable = 'resizable' > </gc-column> <gc-column :width='300' :dataField="'client'" :headerText="'Client'" :visible = 'visible' :resizable = 'resizable' > </gc-column> <gc-column :width="350" :headerText="'Description'" :dataField="'description'" :visible = 'visible' :resizable = 'resizable' > </gc-column> <gc-column :width="100" :dataField="'value'" :headerText="'Value'" :visible = 'visible' :formatter = 'priceFormatter' :resizable = 'resizable' > </gc-column> <gc-column :width="100" :dataField="'itemCount'" :headerText="'Quantity'" :visible = 'visible' :resizable = 'resizable' > </gc-column> <gc-column :width="100" :dataField="'soldBy'" :headerText="'Sold By'" :visible = 'visible' :resizable = 'resizable' ></gc-column> <gc-column :width="100" :dataField="'country'" :headerText="'Country'" :visible = 'visible' :resizable = 'resizable' ></gc-column> </gc-worksheet> </gc-spread-sheets> </TablePanel> </template>


Это очень много, поэтому давайте пройдемся по всему, чтобы понять, что происходит.


Сначала мы создаем электронную таблицу, используя элемент gc-spread-sheets и привязывая его к двум свойствам нашего компонента: hostClass и workbookInit.


Внутри электронной таблицы мы создаем новый рабочий лист с элементом gc-worksheet и привязываем его к свойствам tableData и autoGenerateColumns нашего компонента. Обратите внимание, что tableData — это в точности тот же tableData, который мы использовали для создания простой HTML-таблицы. Мы можем поместить наши данные в SpreadJS как есть, без каких-либо изменений!


Наконец, внутри листа мы определяем столбцы, которые сообщают SpreadJS, как отображать наши данные. Свойство dataField сообщает нам, какое свойство базового набора данных должен отображать этот столбец, а headerText дает SpreadJS красиво отформатированное имя столбца для использования. Остальные привязки для каждого столбца просты. В документации SpreadJS есть полный список всего, что вы можете передать в столбец gc.


Итак, с нашим шаблоном, сколько кода понадобится, чтобы все это заработало? К счастью, совсем немного! Вот новый код сценария нашего компонента SalesTable.vue :


 import "@mescius/spread-sheets/styles/gc.spread.sheets.excel2016colorful.css"; // SpreadJS imports import GC from "@mescius/spread-sheets"; import "@mescius/spread-sheets-vue"; import Excel from "@mescius/spread-excelio"; import TablePanel from "./TablePanel"; export default { components: { TablePanel }, props: ["tableData"], data(){ return { sheetName: 'Sales Data', hostClass:'spreadsheet', autoGenerateColumns:true, width:200, visible:true, resizable:true, priceFormatter:"$ #.00" } }, methods: { workbookInit: function(_spread_) { this._spread = spread; var self = this; spread.bind(GC.Spread.Sheets.Events.ValueChanged, function () { const store = self.$store; var sheet = self._spread.getSheetFromName("Sales Data"); var newSalesData = sheet.getDataSource(); store.commit('UPDATE_RECENT_SALES', newSalesData); }); } } };


Благодаря простоте Vue для выполнения этой работы требуется очень мало кода. Если здесь есть что-то, с чем вы не знакомы, раздел «Подробные сведения о компонентах» документации Vue подробно объясняет компоненты Vue. Единственное, что изменилось, — это несколько операций импорта, некоторые свойства данных и пара методов. Свойства данных должны выглядеть знакомо; мы видели их минуту назад в шаблоне. Это параметры конфигурации, которые мы привязываем к компонентам в нашей электронной таблице SpreadJS.


Метод workbookInit — это обратный вызов, который SpreadJS вызывает при инициализации листа. В этом методе мы сохраняем наш объект электронной таблицы SheetJS как переменную экземпляра нашего компонента, чтобы при необходимости мы могли взаимодействовать с ним напрямую. Мы также добавили функцию привязки для события ValueChanged для автоматического обновления данных при каждом изменении значений в экземпляре SpreadJS.


Последнее изменение: мы даем нашему компоненту стиль с ограниченной областью действия, чтобы улучшить стиль самой электронной таблицы. Мы видели это ранее, когда передавали хост-класс элементу gc-spread-sheets. Поскольку для хост-класса установлено значение «электронная таблица», мы собираемся создать класс CSS с именем «электронная таблица»:


 <style scoped> .spreadsheet { width: 100%; height: 400px; border: 1px solid lightgray; } </style>


На этом этапе, если мы не будем вносить никаких других изменений и загрузим нашу панель мониторинга, она будет выглядеть так:


Новая панель управления Vue


Но подождите, это еще не все!


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


Что произойдет, если мы изменим стоимость продажи №6 с 35 000 долларов США до 3500 долларов США? Если мы зайдем на лист и отредактируем значение, мы получим панель мониторинга, которая выглядит следующим образом:


Отредактированная панель управления Vue


Ух ты! Что случилось?


Мы обновили таблицу SpreadJS, и она автоматически обновила наш магазин Vuex.


Похоже, что месяц продаж Анжелы из впечатляющего превратился в посредственный. Прости за это, Анжела!


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

Добавление экспорта Excel

Добавить экспорт Excel на наш лист легко. Во-первых, давайте добавим кнопку экспорта на нашу панель инструментов. Мы собираемся разместить его внизу панели таблицы в файле SalesTable.vue , сразу после закрывающего тега gc-spread-sheets:


 … </gc-spread-sheets> <div class="dashboardRow"> <button class="btn btn-primary dashboardButton" @click="exportSheet"> Export to Excel </button> </div> </TablePanel> </template>


Как видите, наша кнопка ожидает обработчик кликов с именем ExportSheet. Мы добавим его чуть позже, но сначала импортируем функцию из пакета NPM с именем file-saver:


 import { saveAs } from 'file-saver';


Далее, давайте добавим ExportSheet к объекту методов нашего компонента:


 exportSheet: function() { const spread = this._spread; const fileName = "SalesData.xlsx"; //const sheet = spread.getSheet(0); const excelIO = new IO(); const json = JSON.stringify(spread.toJSON({ includeBindingSource: true, columnHeadersAsFrozenRows: true, })); excelIO.save(json, (blob) => { saveAs(blob, fileName); }, function (e) { console.log(e) }); }


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


Затем мы создаем экземпляр библиотеки ExcelIO SpreadJS, конвертируем наш лист в JSON и просим SpreadJS сохранить его. Вуаля! Мы экспортировали файл Excel из нашего приложения Vue с поддержкой электронных таблиц!


Обратите внимание, что мы передаем два параметра сериализации в вызов toJSON листа: includeBindingSource и columnsHeadersAsFrozenRows. Вместе эти параметры гарантируют, что данные, которые мы привязали к листу, экспортируются правильно и что лист содержит заголовки наших столбцов. Итак, просмотрев экспортированный файл Excel, вы поймете каждый столбец.

Добавление импорта Excel

Далее пришло время добавить возможность импорта файлов Excel.


Прямо под кнопкой экспорта мы добавим следующий фрагмент разметки:


 <div> <b>Import Excel File:</b> <div> <input type="file" class="fileSelect" @change='fileChange($event)' /> </div> </div>


Как видите, мы будем использовать стандартный инструмент выбора файлов HTML и запускать метод компонента с именем fileChange при выборе файла.


Теперь, когда мы добавили шаблон, давайте добавим обработчик изменений в объект методов нашего компонента:


 fileChange: function (_e_) { if (this._spread) { const fileDom = e.target || e.srcElement; const excelIO = new Excel.IO(); const spread = this._spread; const store = this.$store; /*const deserializationOptions = { includeBindingSource: true, frozenRowsAsColumnHeaders: true };*/ excelIO.open(fileDom.files[0], (_data_) => { // Used for simply loading the JSON from a file //spread.fromJSON(data, deserializationOptions); var newSalesData = extractSheetData(data); store.commit('IMPORT_RECENT_SALES', newSalesData) }); } }


Импорт файла Excel во многом аналогичен его экспорту, за исключением обратного процесса. После того, как файл выбран, мы просим ExcelIO импортировать его. По завершении он передает информацию о листе в функцию обратного вызова как объект JavaScript. Затем мы передаем импортированные данные через специальную функцию, чтобы извлечь из них нужные нам данные, а затем фиксируем их обратно в хранилище Vuex.


Обычно импорт файла так же прост, как вызов открытого метода ExcelIO, но с использованием метода книги fromJSON. В данном случае мы просто хотим проанализировать данные из импортированного файла и обновить хранилище, которое затем обновит SpreadJS.


В нашей функции extractSheetData, которую вы найдете в файле src/util.util.js, вы увидите, что мы извлекаем данные из объекта JavaScript, возвращаемого ExcelIO, и реструктурируем их, чтобы они соответствовали форме данных в нашем Vuex. магазин.


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


Когда извлечение данных завершено, мы вызываем фиксацию в магазине Vuex и отправляем обновленные данные о транзакции продаж. Затем лист SpreadJS и панели мониторинга обновляются, отражая новые данные. На самом деле мы можем использовать другую функцию мутации для импорта вместо изменяемого значения, чтобы мы могли добавить ее в файл main.js как «IMPORT_RECENT_SALES»:


 const store = new Vuex.Store({ state: { recentSales }, mutations: { UPDATE_RECENT_SALES(state) { state.recentSales.push([]); state.recentSales.pop(); }, IMPORT_RECENT_SALES(state, sales) { state.recentSales = sales; } } });

Тестирование вашего приложения Vue

Теперь, когда вы увидели код, давайте проверим импорт и экспорт Excel в нашем приложении Vue.


Начните с нажатия кнопки «Экспорт в Excel». Затем ваш веб-браузер загрузит электронную таблицу Excel, содержащую все данные, которые мы видели в электронной таблице нашей панели управления.


Откройте лист в Excel и добавьте пару строк данных. Ничего страшного, если вы привлечете новые страны или новых продавцов; все наши компоненты приборной панели справятся с этим. Только будьте осторожны, чтобы не изменить порядок или имена столбцов. Когда вы закончите, нажмите кнопку «Выбрать файл» в нижней части панели «Последние продажи». Выберите файл Excel, который вы только что отредактировали.


Выбрав файл, вы увидите обновленные компоненты информационной панели.

Заключение

Были сделаны! Мы взяли обычное приложение Vue Dashboard и добавили в него живую электронную таблицу. Теперь мы можем редактировать данные на листе и наблюдать за обновлением всей нашей информационной панели. Наша расширенная панель мониторинга также позволяет импортировать и экспортировать файлы Excel.


Vue, Vuex и SpreadJS хорошо дополняют друг друга. Благодаря простым шаблонам и привязке данных Vue, хранилищу реактивных данных Vuex и интерактивным электронным таблицам SpreadJS сложные корпоративные приложения JavaScript можно создавать за считанные часы.


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


Узнайте больше об этом компоненте электронных таблиц JavaScript: