共计 11507 个字符,预计需要花费 29 分钟才能阅读完成。
Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境,通常用于创立网络应用程序。它能够同时解决多个连贯,并且不像其余大多数模型那样依赖线程。
对于 Web 开发者来说,从数据库或 Web 服务器获取数据,而后输入到 Excel 文件以进行进一步剖析的场景时有发生。咱们的技术团队在跟国内外各行各业用户交换的过程中,就曾发现有很多的用户尝试在 Node.js 的环境下运行 SpreadJS 纯前端表格控件,借助该控件,能够在服务器不预装任何 Excel 依赖项的状况下,收集用户输出的信息,并将其主动导出到 Excel 文件中。
为了满足宽广技术爱好者的须要,同时缩小大家在将来技术选型方面所走的弯路,本文将就 SpreadJS 与 Node.js 之间的技术性计划进行探讨!
一、装置 SpreadJS 和 Node .js
首先,咱们须要装置 Node.js 以及 Mock-Browser,BufferJS 和 FileReader,大家能够返回以下链接进行下载,同步操作:
- Installing Node.js viaPackage Manager
- Mock-Browser
- BufferJS
- FileReader
咱们将应用 Visual Studio 创立应用程序。关上 Visual Studio 后,应用 JavaScript\> Node.js\>Blank Node.js 控制台应用程序模板创立一个新应用程序。这将主动创立所需的文件并关上 ” app.js” 文件,也是咱们将要更改的惟一文件。
对于 BufferJS 库,您须要下载该软件包,而后通过导航到我的项目文件夹(一旦创立)并运行以下命令,将其手动装置到我的项目中:
npm install
装置实现后,您可能须要关上我的项目的 package.json 文件并将其增加到 ” dependencies” 局部。文件内容应如下所示:
{
"name": "spread-sheets-node-jsapp",
"version": "0.0.0",
"description": "SpreadSheetsNodeJSApp",
"main": "app.js",
"author": {"name": "admin"},
"dependencies": {
"FileReader": "^0.10.2",
"bufferjs": "1.0.0",
"mock-browser": "^0.92.14"
}
}
在此示例中,咱们将应用 Node.js 的文件系统模块。咱们能够将其加载到:
var fs = require('fs')
为了将 SpreadJS 与 Node.js 联合应用,咱们还须要加载已装置的 Mock-Browser:
var mockBrowser =require('mock-browser').mocks.MockBrowser
在加载 SpreadJS 脚本之前,咱们须要初始化模仿浏览器。初始化咱们稍后在应用程序中可能须要应用的变量,尤其是 ” window” 变量:
global.window =mockBrowser.createWindow()
global.document = window.document
global.navigator = window.navigator
global.HTMLCollection =window.HTMLCollection
global.getComputedStyle =window.getComputedStyle
初始化 FileReader 库:
var fileReader = require('filereader');
global.FileReader = fileReader;
二、应用 SpreadJS npm 包
将 SpreadJS 安装文件中的 SpreadJS Sheets 和 ExcelIO 包增加到我的项目中。
您能够通过右键单击解决方案资源管理器的 ” npm” 局部并将它们增加到您的我的项目中,而后抉择 ” 装置新的 NPM 软件包 ”。您应该可能搜寻 ” GrapeCity” 并装置以下 2 个软件包:
@grapecity/spread-sheets
@grapectiy/spread-excelio
将 SpreadJS npm 软件包增加到我的项目后,正确的依赖关系将被写入 package.json:
1. {
2. "name": "spread-sheets-node-jsapp",
3. "version": "0.0.0",
4. "description": "SpreadSheetsNodeJSApp",
5. "main": "app.js",
6. "author": {
7. "name": "admin"
8. },
9. "dependencies":{
10. "@grapecity/spread-excelio": "^11.2.1",
11. "@grapecity/spread-sheets": "^11.2.1",
12. "FileReader": "^0.10.2",
13. "bufferjs": "1.0.0",
14. "mock-browser": "^0.92.14"
15. }
16. }
当初咱们须要在 app.js 文件中引入它:
var GC =require('@grapecity/spread-sheets')
var GCExcel =require('@grapecity/spread-excelio');
应用 npm 软件包时,还须要设置许可证密钥(点击此处,收费申请许可证密钥):
GC.Spread.Sheets.LicenseKey ="<YOUR KEY HERE>"
在这个特定的应用程序中,咱们将向用户显示他们正在应用哪个版本的 SpreadJS。为此,咱们能够引入 package.json 文件,而后援用依赖项以获取版本号:
var packageJson =require('./package.json')
console.log('\n** Using Spreadjs Version"' + packageJson.dependencies["@grapecity/spread-sheets"] +'"**')
三、将 Excel 文件加载到您的 Node.js 应用程序中
点击此处,下载现成的 Excel 模板文件,该文件蕴含了从用户那里获取数据。接下来,将数据放入文件中并导出。在这种状况下,文件是用户能够编辑的状态。
初始化工作簿和 ExcelIO 变量:
var wb = new GC.Spread.Sheets.Workbook();
var excelIO = new GCExcel.IO();
咱们在读取文件时将代码包装在 try / catch 块中。而后,初始化变量 ” readline”,让您读取用户输出到控制台的数据。接下来,咱们将其存储到一个 JavaScript 数组中,以便轻松填写 Excel 文件:
// Instantiate the spreadsheet and modifyit
console.log('\nManipulatingSpreadsheet\n---');
try {var file = fs.readFileSync('./content/billingInvoiceTemplate.xlsx');
excelIO.open(file.buffer, (data) => {wb.fromJSON(data);
const readline = require('readline');
var invoice = {generalInfo: [],
invoiceItems: [],
companyDetails: []};
});
} catch (e) {console.error("** Error manipulating spreadsheet **");
console.error(e);
}
四、收集用户输出信息
上图显示了咱们正在应用的 Excel 文件。咱们能够在 excelio.open 调用中创立一个独自的函数,以在控制台中提醒用户须要的每一项内容。咱们也能够创立一个独自的数组,将数据保留到每个输出后,而后将其推送到咱们创立的 invoice.generalInfo 数组中:
fillGeneralInformation();
function fillGeneralInformation() {console.log("-----------------------\nFill in InvoiceDetails\n-----------------------")
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
var generalInfoArray = [];
rl.question('Invoice Number:', (answer) => {generalInfoArray.push(answer);
rl.question('Invoice Date (dd Month Year):', (answer) => {generalInfoArray.push(answer);
rl.question('Payment Due Date (ddMonth Year):', (answer) => {generalInfoArray.push(answer);
rl.question('Customer Name:',(answer) => {generalInfoArray.push(answer);
rl.question('CustomerCompany Name:', (answer) => {generalInfoArray.push(answer);
rl.question('Customer Street Address:', (answer) => {generalInfoArray.push(answer);
rl.question('Customer City, State, Zip (<City>, <State Abbr><Zip>):', (answer) => {generalInfoArray.push(answer);
rl.question('Invoice Company Name:', (answer) => {generalInfoArray.push(answer);
rl.question('Invoice Street Address:', (answer) => {generalInfoArray.push(answer);
rl.question('Invoice City, State, Zip (<City>, <State Abbr><Zip>):', (answer) => {generalInfoArray.push(answer);
rl.close();
invoice.generalInfo.push({"invoiceNumber": generalInfoArray[0],
"invoiceDate": generalInfoArray[1],
"paymentDueDate": generalInfoArray[2],
"customerName": generalInfoArray[3],
"customerCompanyName": generalInfoArray[4],
"customerStreetAddress": generalInfoArray[5],
"customerCityStateZip": generalInfoArray[6],
"invoiceCompanyName": generalInfoArray[7],
"invoiceStreetAddress": generalInfoArray[8],
"invoiceCityStateZip": generalInfoArray[9],
});
console.log("General Invoice Information Stored");
fillCompanyDetails();});
});
});
});
});
});
});
});
});
});
}
该函数被称为 ” fillCompanyDetails”,目标是收集无关公司的信息以填充到工作簿的第二张表中:
function fillCompanyDetails() {console.log("-----------------------\nFill in CompanyDetails\n-----------------------")
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
var companyDetailsArray = []
rl.question('Your Name:', (answer) => {companyDetailsArray.push(answer);
rl.question('Company Name:', (answer) => {companyDetailsArray.push(answer);
rl.question('Address Line 1:',(answer) => {companyDetailsArray.push(answer);
rl.question('Address Line 2:',(answer) => {companyDetailsArray.push(answer);
rl.question('Address Line3:', (answer) => {companyDetailsArray.push(answer);
rl.question('AddressLine 4:', (answer) => {companyDetailsArray.push(answer);
rl.question('Address Line 5:', (answer) => {companyDetailsArray.push(answer);
rl.question('Phone:', (answer) => {companyDetailsArray.push(answer);
rl.question('Facsimile:', (answer) => {companyDetailsArray.push(answer);
rl.question('Website:', (answer)=> {companyDetailsArray.push(answer);
rl.question('Email:', (answer) => {companyDetailsArray.push(answer);
rl.question('Currency Abbreviation:', (answer) => {companyDetailsArray.push(answer);
rl.question('Beneficiary:',(answer) => {companyDetailsArray.push(answer);
rl.question('Bank:', (answer) => {companyDetailsArray.push(answer);
rl.question('Bank Address:', (answer) => {companyDetailsArray.push(answer);
rl.question('Account Number:', (answer) => {companyDetailsArray.push(answer);
rl.question('RoutingNumber:', (answer) => {companyDetailsArray.push(answer);
rl.question('Make Checks Payable To:', (answer) => {companyDetailsArray.push(answer);
rl.close();
invoice.companyDetails.push({"yourName": companyDetailsArray[0],
"companyName": companyDetailsArray[1],
"addressLine1": companyDetailsArray[2],
"addressLine2": companyDetailsArray[3],
"addressLine3": companyDetailsArray[4],
"addressLine4": companyDetailsArray[5],
"addressLine5": companyDetailsArray[6],
"phone":companyDetailsArray[7],
"facsimile": companyDetailsArray[8],
"website":companyDetailsArray[9],
"email": companyDetailsArray[10],
"currencyAbbreviation":companyDetailsArray[11],
"beneficiary": companyDetailsArray[12],
"bank":companyDetailsArray[13],
"bankAddress": companyDetailsArray[14],
"accountNumber": companyDetailsArray[15],
"routingNumber": companyDetailsArray[16],
"payableTo": companyDetailsArray[17]
});
console.log("Invoice Company Information Stored");
console.log("-----------------------\nFillin Invoice Items\n-----------------------")
fillInvoiceItemsInformation();});
});
});
});
});
});
});
});
});
});
});
});
});
});
});
});
});
});
}
当初咱们曾经有了用户的根本信息,咱们能够集中精力收集单个我的项目,并另命名为 ” fillInvoiceItemsInformation” 函数。在每个我的项目执行之前,咱们会询问用户是否要增加一个我的项目。如果他们持续输出 ” y”,那么咱们将收集该项目标信息,而后再次询问直到他们键入 ” n”:
function fillInvoiceItemsInformation() {
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
var invoiceItemArray = [];
rl.question('Add item?(y/n):', (answer) => {switch (answer) {
case "y":
console.log("-----------------------\nEnter ItemInformation\n-----------------------");
rl.question('Quantity:',(answer) => {invoiceItemArray.push(answer);
rl.question('Details:',(answer) => {invoiceItemArray.push(answer);
rl.question('UnitPrice:', (answer) => {invoiceItemArray.push(answer);
invoice.invoiceItems.push({"quantity":invoiceItemArray[0],
"details": invoiceItemArray[1],
"unitPrice": invoiceItemArray[2]
});
console.log("ItemInformation Added");
rl.close();
fillInvoiceItemsInformation();});
});
});
break;
case "n":
rl.close();
return fillExcelFile();
break;
default:
console.log("Incorrectoption, Please enter'y'or'n'.");
}
});
}
五、填入您的 Excel 文件
在收集所有必须的用户信息后,咱们能够将其填入到 Excel 文件中:
function fillExcelFile() {console.log("-----------------------\nFilling in Excelfile\n-----------------------");
fillBillingInfo();
fillCompanySetup();}
function fillBillingInfo() {var sheet = wb.getSheet(0);
sheet.getCell(0, 2).value(invoice.generalInfo[0].invoiceNumber);
sheet.getCell(1, 1).value(invoice.generalInfo[0].invoiceDate);
sheet.getCell(2, 2).value(invoice.generalInfo[0].paymentDueDate);
sheet.getCell(3, 1).value(invoice.generalInfo[0].customerName);
sheet.getCell(4, 1).value(invoice.generalInfo[0].customerCompanyName);
sheet.getCell(5, 1).value(invoice.generalInfo[0].customerStreetAddress);
sheet.getCell(6, 1).value(invoice.generalInfo[0].customerCityStateZip);
sheet.getCell(3, 3).value(invoice.generalInfo[0].invoiceCompanyName);
sheet.getCell(4, 3).value(invoice.generalInfo[0].invoiceStreetAddress);
sheet.getCell(5, 3).value(invoice.generalInfo[0].invoiceCityStateZip);
}
function fillCompanySetup() {var sheet = wb.getSheet(1);
sheet.getCell(2, 2).value(invoice.companyDetails[0].yourName);
sheet.getCell(3, 2).value(invoice.companyDetails[0].companyName);
sheet.getCell(4, 2).value(invoice.companyDetails[0].addressLine1);
sheet.getCell(5, 2).value(invoice.companyDetails[0].addressLine2);
sheet.getCell(6, 2).value(invoice.companyDetails[0].addressLine3);
sheet.getCell(7, 2).value(invoice.companyDetails[0].addressLine4);
sheet.getCell(8, 2).value(invoice.companyDetails[0].addressLine5);
sheet.getCell(9, 2).value(invoice.companyDetails[0].phone);
sheet.getCell(10, 2).value(invoice.companyDetails[0].facsimile);
sheet.getCell(11, 2).value(invoice.companyDetails[0].website);
sheet.getCell(12, 2).value(invoice.companyDetails[0].email);
sheet.getCell(13, 2).value(invoice.companyDetails[0].currencyAbbreviation);
sheet.getCell(14, 2).value(invoice.companyDetails[0].beneficiary);
sheet.getCell(15, 2).value(invoice.companyDetails[0].bank);
sheet.getCell(16, 2).value(invoice.companyDetails[0].bankAddress);
sheet.getCell(17, 2).value(invoice.companyDetails[0].accountNumber);
sheet.getCell(18, 2).value(invoice.companyDetails[0].routingNumber);
sheet.getCell(19, 2).value(invoice.companyDetails[0].payableTo);
}
为了避免用户增加的数量超过工作表最大行数,咱们能够在工作表中主动增加更多行。在设置数组中表单中的我的项目之前,默认增加行:
function fillInvoiceItems() {var sheet = wb.getSheet(0);
var rowsToAdd = 0;
if (invoice.invoiceItems.length > 15) {
rowsToAdd = invoice.invoiceItems.length - 15;
sheet.addRows(22, rowsToAdd);
}
var rowIndex = 8;
if (invoice.invoiceItems.length >= 1) {for (var i = 0; i < invoice.invoiceItems.length; i++) {sheet.getCell(rowIndex,1).value(invoice.invoiceItems.quantity);
sheet.getCell(rowIndex,2).value(invoice.invoiceItems.details);
sheet.getCell(rowIndex,3).value(invoice.invoiceItems.unitPrice);
rowIndex++;
}
}
}
六、将文档内容从 Node.js 导出到 Excel 文件
在工作簿中填写完信息后,咱们能够将工作簿导出到 Excel 文件中。为此,咱们将应用 excelio 关上性能。在这种状况下,只需将日期输出文件名即可:
function exportExcelFile() {excelIO.save(wb.toJSON(), (data) => {fs.appendFileSync('Invoice' + new Date().valueOf() + '.xlsx', newBuffer(data), function (err) {console.log(err);
});
console.log("Export success");
}, (err) => {console.log(err);
}, {useArrayBuffer: true});
}
实现的文件将如下所示:
以上就是第一篇《从服务端生成 Excel 电子表格(Node.js+SpreadJS)》的全部内容。为了可能解决批量绑定数据源并导出 Excel、批量批改大量 Excel 内容及款式、服务端批量打印以及生成 PDF 文档等需要,咱们提供了更为成熟的官网伎俩:SpreadJS + GcExcel,该计划提供了比 Node.js+SpreadJS 更加优良的性能和稳定性,这就是咱们下一篇《从服务端生成 Excel 电子表格(GcExcel + SpreadJS)》的次要内容,敬请期待。