如何在Node.js中生成前端Excel電子表格

有時您可能需要在Node.js應用程序生成Excel文件。您可能需要從數據庫或Web服務獲取數據,然後輸出到Excel文件以進行進一步的報告或分析。 SpreadJS可以在服務器端不依賴任何Excel的情況下實現這一點。

Node.js是一種流行的事件驅動的JavaScript運行時環境,通常用於創建Web應用程序。它可以同時處理多個連接,並且不像大多數其他模型那樣依賴於線程。

在本教程中,我們將使用Spread JS收集用戶輸入的信息並自動將其導出到Excel文件 - 所有這些都在Node.js應用程序中。憑藉Spread JS的強大功能,無論是單獨使用Spread JS還是使用Node.js,性能都不會受到影響。

點擊下載項目示例

Generate an Excel file from your Node.js application

SpreadJS和Node.js入門

首先,我們需要安裝Node.js和Mock-Browser,BufferJS和FileReader,這些都可以在以下鏈接中找到:

我們將使用Visual Studio來創建應用程序。打開Visual Studio後,使用JavaScript> Node.js> Blank Node.js控制檯應用程序模板創建一個新應用程序。這將自動創建所需的文件並打開“app.js”文件,本例中我們只需改動這一個文件。

對於BufferJS庫,您需要下載該軟件包,然後通過導航到項目文件夾(一旦創建)並運行以下命令,在項目中手動安裝它:

npm install

安裝完成後,可能需要打開項目的package.json文件並將其添加到“dependencies”部分。文件內容應如下所示:

<code class="language-javascript">
{
  "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"
  }
}
</code>

在此示例中,我們將使用Node.js的文件系統模塊。加載方式:

<code class="language-javascript">
var fs = require('fs')
</code>

爲了將SpreadJS與Node.js一起使用,我們可以加載我們安裝的Mock-Browser:

<code class="language-javascript">
var mockBrowser = require('mock-browser').mocks.MockBrowser
</code>

在加載SpreadJS腳本之前,我們需要初始化模擬瀏覽器。初始化我們稍後可能需要在應用程序中使用到的變量,尤其是“window”:

<code class="language-javascript">
global.window = mockBrowser.createWindow()
global.document = window.document
global.navigator = window.navigator
global.HTMLCollection = window.HTMLCollection
global.getComputedStyle = window.getComputedStyle
</code>

初始化FileReader庫:

<code class="language-javascript">
var fileReader = require('filereader');
global.FileReader = fileReader;
</code>

使用SpreadJS npm包

現在,需要將SpreadJS包和ExcelIO包添加到項目中。您可以通過右鍵單擊解決方案資源管理器的“npm”部分並選擇“安裝新的NPM包”將這些添加到項目中。您可以通過搜索“GrapeCity”並安裝以下2個包:

@grapecity/spread-sheets
@grapectiy/spread-excelio

將SpreadJS npm包添加到項目後,應該使用正確的依賴項自動上傳package.json:

<code class="language-javascript">
{
  "name": "spread-sheets-node-jsapp",
  "version": "0.0.0",
  "description": "SpreadSheetsNodeJSApp",
  "main": "app.js",
  "author": {
    "name": "admin"
  },
  "dependencies": {
    "@grapecity/spread-excelio": "^11.2.1",
    "@grapecity/spread-sheets": "^11.2.1",
    "FileReader": "^0.10.2",
    "bufferjs": "1.0.0",
    "mock-browser": "^0.92.14"
  }
}
</code>

現在我們需要在app.js文件中添加依賴:

<code class="language-javascript">
var GC = require('@grapecity/spread-sheets')
var GCExcel = require('@grapecity/spread-excelio');
</code>

使用npm軟件包時,還需要設置許可證密鑰:

<code class="language-javascript">
GC.Spread.Sheets.LicenseKey = "<YOUR KEY HERE>"
</code>

在這個特定的應用程序中,我們將向用戶顯示他們正在使用的SpreadJS版本。爲此,我們可以請求package.json文件,然後引用依賴項以獲取版本號:

<code class="language-javascript">
var packageJson = require('./package.json')
console.log('\n** Using Spreadjs Version "' + packageJson.dependencies["@grapecity/spread-sheets"] + '" **')
</code>

加載Excel文件

我們將加載現有的Excel模板文件,從用戶那裏獲取數據。接下來,將數據放入文件並導出。在這種情況下,該文件是用戶可以編輯的發票。

首先初始化工作簿和Excel IO變量:

<code class="language-javascript">
var wb = new GC.Spread.Sheets.Workbook();
var excelIO = new GCExcel.IO();
</code>

當我們在文件中讀取時,讓我們將代碼包裝在try / catch塊中。然後我們可以初始化變量“readline” —— 它本質上是一個允許您讀取用戶輸入控制檯數據的庫。接下來,我們將數據存儲到一個JavaScript數組中,可以使用它輕鬆填寫Excel文件:

<code class="language-javascript">
// Instantiate the spreadsheet and modify it
console.log('\nManipulating Spreadsheet\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);
}
</code>

Generate an Excel Spreadsheet from your Node.js Application

上圖顯示了我們正在使用的Excel文件。我們要收集的第一個信息是一般發票信息。我們可以在excelio.open調用中創建一個單獨的函數,以便在控制檯中爲我們需要的每個項目來提示用戶去填寫。我們可以創建一個單獨的數組來在每次輸入之後保存數據,然後我們擁有該部分的所有輸入。將它推送到我們創建的invoice.generalInfo數組:

<code class="language-javascript">
fillGeneralInformation();

function fillGeneralInformation() {
    console.log("-----------------------\nFill in Invoice Details\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 (dd Month Year): ', (answer) => {
                generalInfoArray.push(answer);
                rl.question('Customer Name: ', (answer) => {
                    generalInfoArray.push(answer);
                    rl.question('Customer Company 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();
                                        });
                                    });
                                });
                            });
                        });
                    });
                });
            });
        });
    });
}
</code>

在該函數中,我們稱之爲“fillCompanyDetails”,我們將收集有關公司的信息以填入工作簿的第二張表。該功能與之前的功能非常相似:

<code class="language-javascript">
function fillCompanyDetails() {
    console.log("-----------------------\nFill in Company Details\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 Line 3: ', (answer) => {
                        companyDetailsArray.push(answer);
                        rl.question('Address Line 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('Routing Number: ', (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("-----------------------\nFill in Invoice Items\n-----------------------")
                                                                            fillInvoiceItemsInformation();
                                                                        });
                                                                    });
                                                                });
                                                            });
                                                        });
                                                    });
                                                });
                                            });
                                        });
                                    });
                                });
                            });
                        });
                    });
                });
            });
        });
    });
}
</code>

Generate an Excel Spreadsheet from your Node.js Application

現在我們已經獲得了發票的基本信息,我們可以專注於收集各個發票項目,我們將在另一個名爲“fillInvoiceItemsInformation”的函數中執行此操作。在每個項目之前,我們會詢問用戶是否要添加項目。如果他們繼續輸入“y”,那麼我們將收集該項目的信息,然後再次詢問,直到他們輸入“n”:

<code class="language-javascript">
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 Item Information\n-----------------------");
                rl.question('Quantity: ', (answer) => {
                    invoiceItemArray.push(answer);
                    rl.question('Details: ', (answer) => {
                        invoiceItemArray.push(answer);
                        rl.question('Unit Price: ', (answer) => {
                            invoiceItemArray.push(answer);
                            invoice.invoiceItems.push({
                                "quantity": invoiceItemArray[0],
                                "details": invoiceItemArray[1],
                                "unitPrice": invoiceItemArray[2]
                            });
                            console.log("Item Information Added");
                            rl.close();
                            fillInvoiceItemsInformation(); 
                        });
                    });
                });
                break;
            case "n":
                rl.close();
                return fillExcelFile();
                break;
            default:
                console.log("Incorrect option, Please enter 'y' or 'n'.");
        }
    });
}
</code>

填寫您的Excel文件

收集完所有必需的發票信息後,我們可以填寫Excel文件。對於結算信息和公司設置,我們可以從JavaScript數組中手動​​設置單元格中的每個值:

<code class="language-javascript">
function fillExcelFile() {
    console.log("-----------------------\nFilling in Excel file\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);
}
</code>

我們使用的模板中,行數是以發票的項目數來設置的。用戶在添加過程中可能會超過最大值。在這種情況下,我們可以簡單地向工作表添加更多行:

<code class="language-javascript">
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[i].quantity);
            sheet.getCell(rowIndex, 2).value(invoice.invoiceItems[i].details);
            sheet.getCell(rowIndex, 3).value(invoice.invoiceItems[i].unitPrice);
            rowIndex++;
        }
    }
}
</code>

導出到Excel

在工作簿中填寫信息後,我們可以將工作簿導出到Excel文件。爲此,我們將使用excelio open函數。用日期來爲文件命名:

<code class="language-javascript">
function exportExcelFile() {
    excelIO.save(wb.toJSON(), (data) => {
        fs.appendFileSync('Invoice' + new Date().valueOf() + '.xlsx', new Buffer(data), function (err) {
            console.log(err);
        });
        console.log("Export success");
    }, (err) => {
        console.log(err);
    }, { useArrayBuffer: true });
}
</code>

您可以使用上面的代碼段將工作簿導出到Excel文件。您完成的文件如下所示:

Generate an Excel Spreadsheet from your Node.js Application

本例將SpreadJS與Node.js結合使用,演示了SpreadJS的多功能性和可擴展性!有關此類,演示,視頻和教程的更多文章,請查看葡萄城官方博客頁面。

SpreadJS | 下載試用

純前端表格控件SpreadJS,是市面上佈局與功能都與 Excel 高度類似的一款表格控件,全中文操作界面,適用於.NET、Java、移動端等多個平臺的類 Excel 數據開發,備受華爲、中通、民航飛行學院、浪潮等國內知名企業客戶青睞。

您對SpreadJS產品的任何技術問題,都有技術支持工程師提供1對1專業解答,點擊此處即可發帖提問>>技術支持論壇

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章