JavaScript 生成 Excel 文件,简单方法






4.19/5 (12投票s)
一个前端库,用于创建 Excel 文件,包括单元格的格式化和样式设置
引言
很多时候,我们需要将 Web 应用程序中的数据导出为 Excel 格式。通常,我们在浏览器中已经有了这些数据:作为表格内容的一部分,或者作为某个模型的一个实例……用户已经审阅过,对它感到满意,并希望在 Excel 中打开。在这种情况下,开发者有不同的选择
- 什么都不做,甚至不提供该选项。在这种情况下,用户被迫直接从浏览器中选择数据,然后将其复制粘贴到 Excel 中。
- 后端,在服务器上生成 Excel 文件。我敢肯定,无论你使用何种后端(.NET、Java、Node.js、PHP 等),都有许多库可以生成精美的 Excel 文件。
- 前端,直接在浏览器中生成 Excel。
“什么都不做”的方法大多数时候是可行的,但通常结果会很糟糕。所有单元格格式都会在过程中丢失,同一行中的多个单元格会合并……
后端方法是最流行的。现有的库使得实现此功能快速且成本低廉。但是,存在一些缺点,这些缺点可能会或可能不会影响你
- 它使用了服务器资源,这在高负载系统上可能会成为一个问题。
- 存在“延迟”,浏览器必须将“生成我的 Excel”请求发送到服务器,服务器必须生成它,然后将其发送回浏览器进行下载。这会导致用户按下“导出为 Excel”按钮和实际文件下载之间出现明显的“延迟”
- 通常,后端需要访问前端已有的相同数据。对于持久性数据,我们需要数据库查询、服务器上实现的数据缓存……或者浏览器连同“生成 Excel 请求”一起发送要包含的数据。所有这些都会增加后端的工作负载、网络流量和上述延迟。
使用前端方法,所有先前的问题都会消失。通常这非常快,因为根本不需要网络。然而,可用的库数量相当少,并且通常存在某种权衡。
一方面,我们有一些库不生成真正的 Excel,而是生成 Excel 可以打开的其他格式(XML、CSV 等)。如果你只需要纯数据导出,而不需要 Excel 的任何特定功能(多于一个工作表、单元格格式等),它们就足够了。
关于生成真正 Excel 的库,它们要么是功能有限的小型库(例如:完全没有单元格格式),要么是提供全范围 Excel 功能的大型库(`js-xlsx`、`exceljs`、`openxmlsdkjs` 等),并且通常有巨大的文档。
在本文中,我介绍了一个小型库,它以一种清晰简洁的方式呈现了最基本的功能。尽管如此,这正是我在 90% 的 Excel 生成需求中所需要的功能。
Using the Code
该库旨在在浏览器中使用,因此它是一个 JavaScript 库,有两个依赖项
- JSZip v3.1.3 by Stuart Knightley, http://stuartk.com/jszip
- FileSaver.js by Eli Grey, http://eligrey.com
要使用它,我们只需将其包含在我们的 `
` 标签中<script type="text/javascript" src="jszip.js"></script>
<script type="text/javascript" src="FileSaver.js"></script>
<script type="text/javascript" src="myexcel.js"></script>
该库定义了一个全局对象 `$JExcel`。该对象包含一些通用转换和一个 Excel 对象生成器。
var excel = $JExcel.new(); // Create an Excel with system default font
var excel = $JExcel.new("Arial 10 #333333"); // Default font is Arial 10 in RGB #333
Excel 对象定义了四个方法
addSheet
addStyle
set
generate
``addSheet`` 用于向 Excel 对象添加额外的工作表。它需要一个名称。Excel 对象始终有一个默认工作表(索引 0)。工作表通过其创建索引进行引用。
``addStyle`` 用于在 Excel 文档中注册样式。它需要一个样式定义对象,该对象最多包含 5 个属性
{
fill: "#ECECEC" , // background color in #RRGGBB
border: "none,none,none,thin #333333" // left border,right border,top border, bottom border
font: "Calibri 12 #0000AA B"}); // font-name font-size font-color font-style
format: "yyyy.mm.dd hh:mm:ss", // display format
align: "R T", // horizontal-align vertical-align
}
边框定义由“边框样式”和“RGB 边框颜色”组成。允许的边框样式可在 `$JExcel.borderStyles` 数组中找到。
如果 `font-style` 包含 **B** 字符,则字体为粗体,**U** 表示下划线,**I** 表示斜体。
在 `$JExcel.formats` 数组中有许多预定义的显示格式。也可以自定义它们。
对于水平对齐和垂直对齐,应用以下约定:C:居中 L:左 R:右 T:顶部 B:底部 -:无。
``set`` 用于在单元格/行/列/工作表上设置值或样式。设置的内容由非 `undefined` 的参数决定。适用以下规则
- 如果仅定义了工作表索引,则设置工作表名称
- 如果仅定义了工作表索引和行号,则可以为该工作表中的行设置样式,并为行高设置值
- 如果仅定义了工作表索引和列号,则可以为该工作表中的列设置样式,并为列宽设置值
- 如果定义了工作表索引、列号和行号,则可以为定义的单元格设置样式,并为其内容设置值
``set`` 方法允许使用规范列表参数,或单个对象参数。在规范形式中,将 `undefined` 用作不应用的值;在对象参数中,只需不包含该属性。
set(0,undefined,undefined,"Summary"); // Set name of SHEET 0 to Summary
var fillEC=excel.addStyle ( {fill: "#ECECEC"}); // Style in ECECEC background color
set(2,undefined,1,undefined,fillEC); // Set fillEC style in row 1 in sheet 2
set( {sheet:2,row:1,style:fillEC}); // alternatively
var Arial10B=excel.addStyle ({font: "Arial 10 B"}); // Define style Arial 10 bold
set( {sheet:0,col:5,row:3,value: "HELLO",style:Arial10B}); // Set HELLO in col 5 and row 3 in sheet 0
set(0,5,3,"HELLO",Arial10B); // alternatively
``generate`` 方法生成一个 Excel 工作簿并使其可供下载。
关注点
XLSX 格式只是一堆 zip 在一起的 XML 文件。这些 XML 文件遵循 OpenXML 约定。该库通过定义 Excel 对象模型(工作表、行、单元格、样式……)并在内存中进行设置来工作,当调用 **`generate`** 方法时,会创建 Excel 对象所需的 XML 节点。
然后,“打印”这些 XML 节点并与 OpenXML 模板合并,然后将所有内容 zip 起来,生成的流即可下载。
Excel 不像 JavaScript 那样处理日期时间。它们使用不同的 EPOCH 时刻。该库定义了以下转换函数 `$JExcel.toExcelLocalTime(jsDate)`、`$JExcel.toExcelUTCTime(jsDate)`
为了处理 RGB 值,还提供了以下函数 `$JExcel.rgbToHex(red,green,blue)`。
示例
以下示例……
function randomDate(start, end) {
var d= new Date(start.getTime() + Math.random() * (end.getTime() - start.getTime()));
return d;
}
var excel = $JExcel.new("Calibri light 10 #333333");
excel.set( {sheet:0,value:"This is Sheet 0" } );
var evenRow=excel.addStyle( { border: "none,none,none,thin #333333"});
var oddRow=excel.addStyle ( { fill: "#ECECEC" ,border: "none,none,none,thin #333333"});
for (var i=1;i<50;i++) excel.set({row:i,style: i%2==0 ? evenRow: oddRow });
excel.set({row:3,value: 30 });
var headers=["Header 0","Header 1","Header 2","Header 3","Header 4"];
var formatHeader=excel.addStyle ( {
border: "none,none,none,thin #333333",font: "Calibri 12 #0000AA B"}
);
for (var i=0;i<headers.length;i++){ // Loop headers
excel.set(0,i,0,headers[i],formatHeader); // Set CELL header text & header format
excel.set(0,i,undefined,"auto"); // Set COLUMN width to auto
}
var initDate = new Date(2000, 0, 1);
var endDate = new Date(2016, 0, 1);
var dStyle = excel.addStyle ( {
align: "R",
format: "yyyy.mm.dd hh:mm:ss",
font: "#00AA00"}
);
for (var i=1;i<50;i++){ // Generate 50 rows
excel.set(0,0,i,"This is line "+i); // This column is a TEXT
var d=randomDate(initDate,endDate); // Get a random date
excel.set(0,1,i,d.toLocaleString()); // Random date as STRING
excel.set(0,2,i,$JExcel.toExcelLocalTime(d)); // Date as a NUMERIC
excel.set(0,3,i,$JExcel.toExcelLocalTime(d),dStyle); // Date as a NUMERIC in dStyle.format
excel.set(0,4,i,"Some other text"); // Some other text
}
excel.set(0,1,undefined,30); // Set COLUMN B to 30 chars width
excel.set(0,3,undefined,30); // Set COLUMN D to 20 chars width
excel.set(0,4,undefined,20, excel.addStyle( {align:"R"})); // Align column 4 to the right
excel.set(0,1,3,undefined,excel.addStyle( {align:"L T"})); // CELL B4 to LEFT-TOP
excel.set(0,2,3,undefined,excel.addStyle( {align:"C C"})); // CELL C4 to CENTER-CENTER
excel.set(0,3,3,undefined,excel.addStyle( {align:"R B"})); // CELL D4 to RIGHT-BOTTOM
excel.generate("SampleData.xlsx");
……生成以下 Excel 工作簿
请注意 B、C 和 D 列的不同显示,它们基本上包含相同的数据,但格式不同。此外,第 4 行中所有列的大小和单元格对齐方式的差异也很明显。
公式
要使用公式,只需像在 Excel 中一样输入即可
excel.set(0,8,1,15); // Grid position 8,1 references cell I2
excel.set(0,8,2,13); // Grid position 8,2 references cell I3
excel.set(0,8,3,"=I2+I3"); // In cell I4: I2+I3 => 15+13 => 28
最后
实现这个转换器比预期的要容易。代码简短且注释良好,并且应该易于修改以添加新功能(例如,单元格合并)。你可以在 http://jsegarra1971.github.io/MyExcel/sample.html 找到演示,并且最新的代码可在 https://github.com/jsegarra1971/MyExcel 获取
如果你使用它,请告诉我!!!