excel文件中多個sheet單元格總分校驗功能的實現

前言

最近在聽一次需求宣講會上,聽業務部門的負責人對着後端同窗講:「大家研發同窗能不能幫咱們實現一下這個功能,具體來講就是一些地市分行彙總上來的一份Excel文件裏有多個sheet表,第一個sheet表是彙總數據,其餘sheet表是各分行數據,那麼咱們要作的工做就是仔細校驗一下各分行每一個單元格的數據相加是否等於總行出納記錄出來的數據,而後向上彙報給銀監會。這個不能出一點差錯,否則很麻煩,因此咱們如今都是人工覈對。咱們從英國留學回來的碩士,天天就作這些工做浪費了大量時間,如今但願能借助科技的力量省一些時間,讓他去作其餘更有意義的事。指望大家能幫忙校驗一下這些數據,對於出錯了的單元格,背景展現爲紅色,沒出錯則顯示正常。」現場展現Excel文件以下⏬ 特別說明 銀行對信息安全的管理十分嚴格,故以上數據均爲僞造數據
後端同窗一看這個表格,表示能作是能作的,可是須要傳上去的數據表頭和錶行不能這麼複雜,須要是有規律的一行一行,一列一列的數據,像這樣的他們很差作。我定睛一看,嘿!這功能前端徹底能搞啊,並且不須要那麼多他們說的表頭錶行限制的,沒準是什麼樣校驗完就能返回什麼樣。「悄悄地進村,打槍的不要。」,沒有確切把握的事情就不聲張了,會上沒發聲,會下搞起了預研,併成功的實現了這個需求。html

實現原理

要想實現這樣一個Excel文件中的多個sheet表格的總分校驗功能,原理其實很簡單,核心API就是使用XLSXreadFile()xlsx-style的設置樣式功能。再結合node.js的writeFile,將其寫入指定的文件中。

Excel的功能很強大,它的宏功能已經相似於程序運算了,也徹底能夠實現多張sheet表的元素在一張總表sheet內相加的功能,但它畢竟只能作一些輔助運算工做,對於比較分析幾萬條數據而後標記樣式這種主觀操做單靠軟件自身仍是無能爲力的。還須要藉助工具實現主觀操做,提取裏面有用的信息按照設定意圖來進行分析比較,進而最終拿到預期結果。前端

xlsx

熟悉xlsx這個npm包的同窗們應該都知道,它是前端處理Excel文件的利器,目前npm官網提供的是開源社區版本,加強的pro版本須要付費。這裏咱們不用須要Pro版本,把社區版弄明白就夠用了。支持的輸入輸出格式有不少,好比csv/html/json,我就不貼官網的api了,有興趣的本身去細看,主要記錄下實現過程。踩了一些坑,也更加明白基礎的重要性。node

1.Parsing Workbooks(讀取excel文件)

解析文件的第一步,是去讀,這涉及到獲取數據源並將其導入到庫中,一些常見的場景是用node.js讀,或者photoshop的擴展腳本,ajax請求、瀏覽器拓轉或者瀏覽器的文件上傳。 這裏咱們用第一種場景,使用node.js來讀取文件,拿到數據源,進而進行分析校驗。注意這裏讀的時候使用的type是buffer,方便後面設置樣式的時候寫入。以前使用其餘類型也能正確讀出來,可是設置樣式無效。ajax

const XLSX = require('xlsx');
const fs = require('fs');
const path = require('path');
const XLSXStyle = require('xlsx-style');
const wb = XLSX.readFile(path.resolve(__dirname, './test99.xls'), {type: "buffer"});
複製代碼

因爲表格較大,只截取部分結果以下: 從SheetNames裏能夠觀察到,讀取到了本來隱藏的sheet,而從sheets裏觀察到,讀取到了本來隱藏或者摺疊行裏的數據。這裏咱們並不須要關心隱藏的sheet表,只須要關注總計、分行1、分行2、分行三這四個sheet表來完成總分校驗功能。 單獨打印出總計表,截取部分結果以下: 這裏每一個單元格數據用js來描述其實就是一個對象,v原文是raw value,意指未加工的原始數據,t指的是type,那麼n就是number,意思是他是個number類型的數據,w原文是formatted text,意指格式化後的文本,f原文是 cell formula encoded as an A1-style string (if applicable),按照個人理解便是原單元格所設定的公式。好比G9單元格的f是F9/C9,指的是在原sheet表中給這個單元格設定的公式。express

2.Working with the Workbook(解析Excel文件)

根據官網文檔,本段落主要講如何去讀一個具體的單元格、給Excel文件增長一個sheet表,從頭開始建立一個新的工做簿。 但這都不是咱們須要的功能,筆者是遍歷要校驗的單元格判斷總分校驗是否相等便可。
這裏咱們須要從C6檢驗到L32,因爲都是僞造數據,都對應不上校驗出來都是錯誤,故僅校驗前三行(C6-L8)數據測試是否正確便可,校驗代碼以下: 注意點:
npm

    1. 0.1 + 0.2 !== 0.3,這個你們都知道,所以須要將分行數據轉爲整數來相加。共有若干個分行數據,取到其中小數點位數最多的那一條數據max,每一個數據與max相乘後相加不就能規避精度丟失的問題了?其實並非,來看這個結果:

所以須要逐個數據判斷有幾位小數後取整,若批量取整而後再相加就不能拿到正確的結果了。json

    1. Excel文件單元格有它本身的格式,於是你看到的數據並不必定是它的真實數據,來看這樣一個單元格:它上面的格式是D9/C9,計算出來的結果是0.018490754622689,可實際呈現的是1.85%,也即0.0185,計算時應該按照0.0185來比對,可事實是計算機及程序是很是嚴謹的,它會無視單元格的格式限制,而採用0.018490754622689來進行計算,所以得出的比對結果是錯誤的。因此在上述比對代碼中,若碰到小數位數多於4位的狀況,咱們就須要四捨五入來計算了。

3.Styling Workbooks(給sheet表設置樣式)

找到有錯誤的單元格後,咱們接下來就是要給其設置樣式了。這裏咱們用到的是xlsx-style這個插件。 後端

4.Writing Workbooks(寫excel文件)

設置好樣式以後,咱們須要將它寫入指定的Excel文件中,拿到結果。官方文檔給了好多種寫入的應用場景,這裏咱們採用node.js寫入。 api

獲取到結果

在當前項目根目錄下獲取到結果文件以下: 第七行是隱藏行,比對下來均錯,意料之中。C6單元格故意寫錯,成功檢測出來。後面再分別測試了百分比單元格,小數點單元格、除不盡單元格,均能拿到預期結果,就都不一一貼出來了。至此,完成了這個總分校驗功能的實現。瀏覽器

想要經過上傳下載來實現?

最核心的功能實現了,上傳下載感受都是輔助功能了。若是想經過上傳源文件——>比對處理後——>下載,能夠經過FileSaver來實現。具體步驟是使用express或者koa來實現一個僞後臺,獲取到上傳的文件後進行解析,而後進行數據校驗後,將文件buffer流傳輸給客戶端瀏覽器,再經過FileSaver.saveAs方法來實現文件的保存。

相關文章
相關標籤/搜索