paint-brush
使用 Vue 导入和导出 Excel XLSX:指南经过@mesciusinc
444 讀數
444 讀數

使用 Vue 导入和导出 Excel XLSX:指南

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

太長; 讀書

了解如何在 Vue 应用程序中导入和导出 Excel XLSX 文件。
featured image - 使用 Vue 导入和导出 Excel XLSX:指南
MESCIUS inc. HackerNoon profile picture

“看起来很棒,但是你能添加 Excel 导入吗?”


如果您从事软件开发已有很长时间,那么您可能不止一次听到经理问过这个问题。对于非技术人员来说,要求导入/导出 Excel 听起来不是什么大问题。这能有多难呢,对吧?


但这个问题常常让开发人员心生恐惧。在大多数平台上,处理 Excel 文件需要大量工作。从历史上看,在网络上更是如此。在网络应用中处理 Excel 数据的感觉有点像xkcd 漫画中的情节:“很难解释简单的事情和几乎不可能的事情之间的区别。”使用 Excel 导入和 Excel 导出功能构建自己的浏览器内电子表格感觉像是一个需要五年时间和一个研究团队才能解决的问题。


这种情况正在改变。我们现在拥有交钥匙库,可让您将功能齐全的电子表格放入您的 Web 应用程序中。SpreadJS 就是其中之一。我们将研究如何使用SpreadJS来改进现有的 Vue 应用程序(使用 Vuex 存储的真实应用程序)。


本文的其余部分假设您已经了解 HTML、CSS 和 JavaScript。还假设您具备用于创建 Web UI 的Vue.js渐进式 JavaScript 框架的实际知识。如果您使用过Vuex进行状态管理,这将很有帮助,但如果您没有使用过也不必担心。它直观且易于理解,如果您使用过 Vue,只需阅读代码就能弄清楚发生了什么。


在此博客中,我们将介绍如何按照以下步骤将 Excel 导入和导出功能添加到您的 Vue 应用程序:


  1. Vue 应用程序结构
  2. 将 SpreadJS 添加到您的 Vue 应用程序中
  3. 添加 Excel 导出
  4. 添加 Excel 导入
  5. 测试你的 Vue 应用

Vue 应用程序

我们将要开发的 Vue 应用是一个简单的销售仪表板,其中包含一些摘要面板和一个数据表。这种应用属于“不错”类别:


Vue 销售仪表板


虽然这只是一个演示,但它正是企业 Web 开发人员必须创建的应用程序。它也正是我们通常被要求添加 Excel 功能的应用程序,因此它将是本文其余部分的完美示例。


此应用程序的代码可以在这里找到。


如果您想了解如何从头开始创建 Vue 应用程序,请查看此快速入门指南


首先,仪表板是一个使用 Vue 制作的单页应用程序。它使用最新、最出色的Vue 最佳实践:单文件组件和 Vuex 数据存储。它还使用Bootstrap作为其 CSS 组件和网格系统。


Bootstrap 不再像以前那么流行,但实际上,Bootstrap 仍然无处不在——尤其是在通常需要 Excel 支持的企业 Web 应用程序中。我们敢打赌,到 2030 年,许多新的企业 Web 应用程序仍将使用 Bootstrap。


如果您更愿意在支持电子表格的应用中使用BulmaTachyons ,那就继续吧!SpreadJS 可以与其中任何一个很好地配合使用。

Vue 应用程序结构

让我们看一下代码的结构。我们的 Vuex 存储和 Vue 应用程序均在main.js中定义。我们有几个单文件 Vue 组件,均位于 components 文件夹中。


如果你查看我们的 Vuex 商店,你会看到以下内容:


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


我们商店的初始状态设置为 recentSales 的值,这是我们导入的一组虚拟数据。我们还有一个函数,用于在最近的销售发生变化时更新它们。


等一下。如果我们只有一组数据,我们如何生成三个图表一个表格?要查看发生了什么,请打开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”。这将安装运行应用程序所需的依赖项。依赖项安装完成后,运行“npm serve”以查看更新后的应用程序。如果您想专门导入使用的库,可以使用以下命令:


 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 与我们用于生成纯 HTML 表的 tableData 完全相同。我们可以将数据原样放入 SpreadJS,无需进行任何更改!


最后,在工作表中,我们定义列来告诉 SpreadJS 如何显示我们的数据。dataField 属性告诉我们此列应显示基础数据集的哪个属性,headerText 为 SpreadJS 提供了一个格式良好的列名以供使用。每列的其余绑定都很简单。SpreadJS 文档列出了可以传递给 gc-column 的所有内容的完整列表


那么,有了模板,需要多少代码才能使这一切正常工作?幸运的是,一点也不多!这是我们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 实例中的值发生变化时自动更新数据。


最后一个变化:我们为组件提供了一个作用域样式,以帮助电子表格样式本身。我们在之前将 hostClass 传递给 gc-spread-sheets 元素时看到了这一点。由于 hostClass 设置为“spreadsheet”,我们将创建一个名为电子表格的 CSS 类:


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


此时,如果我们不做其他更改并加载我们的仪表板,它将看起来像这样:


新的 Vue 仪表板


但等一下,还有更多!


还记得我们如何将表格数据传递到电子表格而不对数据集进行任何更改吗?现在我们的数据在电子表格中,我们可以编辑它。


如果我们将销售 #6 的价值从 35,000 美元更改为 3500 美元,会发生什么情况?如果我们进入工作表并编辑值,我们将获得如下所示的仪表板:


编辑 Vue 仪表板


哇!发生了什么事?


我们更新了 SpreadJS 表,它自动更新了我们的 Vuex 存储。


看起来 Angela 的销售业绩从当月的辉煌变成了平淡。很抱歉,Angela!


我们现在拥有一个增强的仪表板,经理们会对此感到满意。他们可以修改数据并亲眼看到仪表板的更新,但我们可以通过添加导入和导出 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 的点击处理程序。我们稍后会添加它,但首先,我们将从名为 file-saver 的 NPM 包中导入一个函数:


 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 来访问它。如果我们需要直接与工作表交互,则可以在函数中的其他地方使用它。


然后,我们实例化 SpreadJS 的 ExcelIO 库,将工作表转换为 JSON,并要求 SpreadJS 保存它。瞧!我们已经从支持电子表格的 Vue 应用程序中导出了一个 Excel 文件!


请注意,我们将两个序列化选项传递给工作表的 toJSON 调用:includeBindingSource 和 columnHeadersAsFrozenRows。这些选项共同确保我们绑定到工作表的数据正确导出,并且工作表包含我们的列标题。因此,查看导出的 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 文件与导出 Excel 文件非常相似,只是操作相反。选择文件后,我们要求 ExcelIO 导入它。完成后,它会将工作表信息作为 JavaScript 对象传递给回调函数。接下来,我们将导入的数据传递给自定义函数,以从中提取所需的数据,然后将其提交回 Vuex 存储。


通常,导入文件很简单,只需调用 ExcelIO open 方法,但使用工作簿“fromJSON”方法即可。在这种情况下,我们只想解析导入文件中的数据并更新存储,然后存储将更新 SpreadJS。


在我们的 extractSheetData 函数中(您可以在 src/util.util.js 文件中找到该函数),您会看到我们从 ExcelIO 返回的 JavaScript 对象中提取数据并重新构造它以匹配我们 Vuex 存储中数据的形状。


我们的导入功能假设导入工作表中的数据将具有与原始数据集相同的列。如果有人上传的电子表格不符合此要求,我们的应用将无法处理它。这是大多数业务线应用中可以接受的限制。由于我们的仪表板旨在显示特定数据类型,因此要求用户以应用期望的格式提供数据是合理的。


数据提取完成后,我们在 Vuex 存储上调用提交并发送更新后的销售交易数据。然后,SpreadJS 工作表和仪表板面板会自行更新以反映新数据。我们实际上可以使用不同的变异函数来导入而不是更改值,以便我们可以将其作为“IMPORT_RECENT_SALES”添加到main.js文件中:


 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 应用

现在您已经看到了代码,让我们在 Vue 应用程序中测试 Excel 导入和导出。


首先点击“导出到 Excel”按钮。然后,您的网络浏览器将下载一个 Excel 电子表格,其中包含我们在仪表板电子表格中看到的所有数据。


在 Excel 中打开工作表,添加几行数据。如果您使用新的国家/地区或新的销售人员,这没问题;我们所有的仪表板组件都可以处理。只需注意不要更改列顺序或名称。完成后,单击“最近销售”面板底部的“选择文件”按钮。选择您刚刚编辑的 Excel 文件。


当您选择该文件时,您将看到更新的仪表板组件。

结论

大功告成!我们采用了一个普通的 Vue 仪表板应用,并向其中添加了一个实时电子表格。现在我们可以编辑工作表中的数据,并观察整个仪表板的更新情况。我们的增强型仪表板还能够导入和导出 Excel 文件。


Vue、Vuex 和 SpreadJS 相得益彰。借助 Vue 的简单模板和数据绑定、Vuex 的反应式数据存储和 SpreadJS 的交互式电子表格,可以在数小时内创建复杂的企业 JavaScript 应用程序。


虽然这看起来很棒,但我们仅仅触及了 SpreadJS 功能的表面。为了更好地了解 SpreadJS 可以为您做什么,请参阅SpreadJS 演示,其中包括 SpreadJS 不同功能的完整演示、说明和展示这些功能的实时代码。如果您想深入了解如何在自己的应用程序中使用 SpreadJS, SpreadJS 文档有您需要的信息。


了解有关此 JavaScript 电子表格组件的更多信息: