<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          首期 Go 開源說實錄:Excelize 開源背后的故事

          共 10730字,需瀏覽 22分鐘

           ·

          2021-01-09 20:41



          首期主題:Excelize


          在 Go 中國社區(qū)的首期 Go 開源說線上活動中,開源項目 Excelize 的作者續(xù)日帶來了《Excelize 開源背后的故事》主題分享。


          作者介紹


          續(xù)日,軟件工程師,專注于 Go 語言實踐、中間件研發(fā)與大規(guī)模數(shù)據(jù)處理。目前就職于阿里巴巴,曾就職于百度、奇虎 360 等公司,前百度 Go 語言編程委員會成員,在百度期間從事內部 Go 語言開發(fā)框架和代碼規(guī)范的相關工作。他熱愛開源,會把一些開源項目發(fā)布在他的 GitHub 上:https://github.com/xuri


          內容提要


          本次分享內容主要包括四個部分:Excelize 項目初衷與發(fā)展歷程、實現(xiàn)過程、設計理念與實踐應用。




          關于 Excelize


          Excelize 是 Go 語言編寫的用于操作 Office Excel 文檔基礎庫,基于 ECMA-376,ISO/IEC 29500 國際標準。可以使用它來讀取、寫入由 Microsoft Excel? 2007 及以上版本創(chuàng)建的電子表格文檔。支持 XLSX / XLSM / XLTM 等多種文檔格式,高度兼容帶有樣式、圖片(表)、透視表、切片器等復雜組件的文檔,并提供流式讀寫 API,用于處理包含大規(guī)模數(shù)據(jù)的工作簿。可應用于各類報表平臺、云計算、邊緣計算等系統(tǒng)。
          入選 2020 Gopher China - Go 領域明星開源項目 (GSP)、2018 年開源中國碼云最有價值開源項目 (Gitee Most Valuable Project)。
          GitHub:https://github.com/xuri/excelize

          項目初衷


          提起電子表格大家都比較熟悉,以 Excel 為代表的經(jīng)典電子表格已經(jīng)應用在各行各業(yè)當中,根據(jù)相關研究機構的估算數(shù)據(jù),辦公文檔產(chǎn)生的數(shù)量每年至少以數(shù)十億的規(guī)模增長。電子表格文檔作為一種數(shù)據(jù)承載的重要載體,在很多領域都有應用。作為開發(fā)者,一些情況下需要用編程的方式操作這些電子表格文檔,起初為了滿足從報表系統(tǒng)中導出數(shù)據(jù)的需要,Excelize 的作者續(xù)日調研了市面上多個主流語言的相關基礎庫,希望能夠找到一個高性能、支持復雜樣式并且還能夠跨平臺的解決方案,可是經(jīng)過一番尋找并沒有找到能夠滿足業(yè)務復雜需要的開源實現(xiàn),就這樣他決定從文檔格式標準開始入手,從零開始使用 Go 語言實現(xiàn)一個兼顧性能和兼容性的電子表格文檔基礎庫。總結發(fā)起 Excelize 項目的初衷可以歸結為以下 6 點:
          • 電子表格辦公文檔有著廣泛的應用
          • 自動化電子表格文檔處理系統(tǒng)與云計算、邊緣計算場景融合
          • 開發(fā)者需要通過編程方式處理 Excel 文檔
          • 對復雜或包含大規(guī)模數(shù)據(jù)的 Excel 文檔進行操作的需求
          • 文檔格式領域難以完全實現(xiàn)的復雜技術標準
          • 開源領域、Go 語言缺少具備良好兼容性的基礎庫

          發(fā)展歷程


          在 Excelize 開源之前就在公司內部和多個線上產(chǎn)品中有了應用實踐,2016 年 9 月正式開源時已經(jīng)能夠滿足很多常用的 Excel 文檔操作需求,除了基本的工作簿、工作表和單元格操作,還具備插入圖片、圖表和合并單元格等能力。歷經(jīng)四年多的發(fā)展,截至目前已經(jīng)發(fā)布了 14 個版本。我們來回顧一下 Excelize 的發(fā)展歷程,下面例舉了每個版本中有代表性的部分功能(Excelize 在 GitHub 的 Release 頁面和文檔網(wǎng)站上有更為詳細的發(fā)布記錄):
          • v1.0.0 (2016-09-19) 首次發(fā)布:支持插入圖片、圖表、合并單元格等
          • v1.1.0 (2017-08-19) 支持條件格式、復制工作表
          • v1.2.0 (2017-12-01) 兼容 Go 1.9,支持堆積圖表
          • v1.3.0 (2018-05-11) 行列分組、單元格批量賦值
          • v1.4.0 (2018-08-14) 支持數(shù)據(jù)驗證、色值轉換
          • v1.4.1 (2019-01-01) 搜索單元格、保護工作表
          • v2.0.0 (2019-05-02) 引入流式讀寫,性能進一步提升
          • v2.0.1 (2019-07-01) 頁眉頁腳、文檔屬性設置
          • v2.0.2 (2019-10-09) 嵌入 VBA 工程、數(shù)據(jù)透視表
          • v2.1.0 (2020-02-10) 支持非 UTF-8 編碼文檔
          • v2.2.0 (2020-05-11) 支持圖表工作表、富文本、分頁
          • v2.3.0 (2020-08-06) 新增工作表視圖屬性設置
          • v2.3.1 (2020-09-23) 兼容 Go 1.15,支持讀加密 Excel
          • v2.3.2 (2021-01-04) 圖表、數(shù)據(jù)透視表功能增強,更好的兼容性與更快的流式讀寫

          實現(xiàn)過程


          • 調研市面上主流的技術實現(xiàn)
          在設計 Excelize 之初,續(xù)日調研了主流編程語言的開源和商業(yè)解決方案、對開源領域相關基礎庫的設計和源代碼做了分析,并閱讀了電子表格文檔格式國際標準。使用過 Office 軟件的朋友可能知道,同一份文檔在不同的辦公軟件中打開可能會出現(xiàn)還原不一致的問題,比如存在樣式細節(jié)的差異;開發(fā)者使用編程的方式借助第三方基礎庫操作電子表格文檔,尤其是處理包含復雜樣式的文檔時可能會出現(xiàn)保存后的文檔無法被 Office 正確打開,提示“文檔已損壞”或部分數(shù)據(jù)丟失等問題,導致這些問題的原因通常是由于這些辦公應用或基礎庫對文檔格式標準的實現(xiàn)不一致、不完整或者存在某些缺陷導致的,如果要避免這個問題就需要深入理解復雜的文檔格式標準,這也是實現(xiàn)電子表格基礎庫的難點和挑戰(zhàn)之一。

          • 理解相關技術標準 ECMA-376,ISO/IEC 29500,MS-OFFCRYPTO
          ECMA-376,ISO/IEC 29500 是 Office 辦公文檔的國際標準(以下簡稱技術標準),對應了我們熟知的 Word、Excel、PowerPoint 三大辦公應用產(chǎn)生的文檔,它是一套十分龐大、復雜的技術標準,其官方文檔有超過 7000 頁內容,而 Excel 文檔相關的部分也有 2000 余頁之多。除此之外 Excel 中的部分功能還涉及廠商技術標準,例如對加密文檔的支持需要實現(xiàn) MS-OFFCRYPTO 技術標準,這里就不詳細展開了,接下來主要會介紹一下 ECMA-376,ISO/IEC 29500 標準的主要內容。

          • 使用 Go 語言編寫代碼實現(xiàn)功能
          在了解完相關技術標準后,就開始使用 Go 語言來實現(xiàn)該技術標準了。續(xù)日在 2019 年 12 月的 Gopher Meetup 上曾做過一次題為《Go 語言國際電子表格文檔格式標準實踐》的技術分享,詳細介紹了該國際標準的特點以及使用 Go 語言實現(xiàn)該標準相關的實踐,有興趣的朋友可以看一下 GoCN 社區(qū)中相關的文章。

          • 數(shù)據(jù)結構代碼生成器的設計
          操作電子表格文檔離不開對其內部數(shù)據(jù)結構的處理,由于電子表格文檔內部涉及到的數(shù)據(jù)結構非常多,手工方式編寫代碼耗時耗力且容易出錯,那么能否通過標準文檔中給定的數(shù)據(jù)結構描述自動化生成 Go 語言的結構體代碼呢,由此續(xù)日設計了一個數(shù)據(jù)結構代碼生成器。

          • 公式詞法 / 語法分析、計算框架
          公式計算也是電子表格的主要功能之一,若在不依賴電子表格應用的前提下對表格文檔中的公式進行求值運算,就需要實現(xiàn)一套計算引擎,其中涉及到 Excel 公式的詞法分析和解析等。

          技術標準


          ECMA-376, ISO/IEC 29500 做為國際文檔格式標準是一種基于 XML 和 ZIP 技術的文檔格式,大家常見的 DOCX / XLSX / PPTX 等文檔文件就遵循該規(guī)范。

          • 文檔格式標準解讀

          下面介紹一下標準的主要內容,上層是標記語言部分(Markup Language),它由四類標記語言組成:Word 文檔對應的標記語言叫 WordprocessingML,電子表格則是 SpreadsheetML,演示文稿對應的是 PresentationML。Excelize 主要實現(xiàn)的是 SpreadsheetML 這個部分,除此之外 Office 文檔支持進行跨應用的嵌套,例如:Word 可以嵌套 Excel,Excel 可以嵌套 Word。通用標記是跨應用的文本標記語言:囊括可視化圖表、可擴展標記、源數(shù)據(jù)和目錄引用等。中間層叫做開放包裝公約(Open Packaging Convention),簡稱 OPC,定義了文檔內部組件之間的關聯(lián)依賴關系(Relationships)、文內容類型(Content Types)定義和數(shù)字簽名(Digital Signatures)。底層是機基于 ZIP、XML 和 Unicode 的核心技術。我們可以創(chuàng)建一個 Excel 文檔,將其擴展名修改為 zip 再進行解壓即可得到一個文件夾,其中包含若干子文件夾和 XML 文檔,這種設計有很強的擴展性,相比于二進制類型文檔格式也具備更好的兼容性。

          • 電子表格文檔格式典型關系
          電子表格文檔內部的 XML 文件的布局和依賴關系是怎樣的呢?這邊有一個圖來解釋:


          工作簿(Workbook)包含多個工作表(Sheets),工作表包含圖表(Chart)、表格(Table)和數(shù)據(jù)透視表(Pivot table)等,數(shù)據(jù)透視表又包含數(shù)據(jù)透視緩存(Pivot Cache)和數(shù)據(jù)透視記錄(Pivot Records)。另外,工作簿還與主題(Theme)、樣式(Style)、公式計算鏈(Calc Chain)以及共享字符表(Shared Strings)等部分有關聯(lián)關系。要實現(xiàn)該技術標準,需要先對這些關系進行梳理。

          數(shù)據(jù)結構代碼生成器


          這里引入一個技術名詞 —— XSD(XML Schema Definition)它是 W3C(萬維網(wǎng)聯(lián)盟)推出的一個技術規(guī)范,用于定義 XML 的模式。XML 文件中理論上可以有無限的標簽和屬性,XSD 是用于描述 XML 的模式語言。文檔格式技術標準中,有以 XSD 來描述的數(shù)據(jù)結構定義。下圖是根據(jù)技術標準中 XSD 模式語言對電子表格文檔數(shù)據(jù)結構描述繪制的一個樹狀結構片段:


          可以看到其中對 XML 標簽的根結點、命名空間和 Excel 中自動過濾器(AutoFilter)相關數(shù)據(jù)結構的定義,以及 XML 中相關節(jié)點的嵌套關系、標簽屬性名稱和數(shù)據(jù)類型的定義。描述 XML 的 XSD 之間也可以互相引用,對 Excel 文檔所涉及的主要數(shù)據(jù)結構定義 XSD 文件進行分析和梳理,繪制出如下依賴關系圖:


          sml.xsd 是 Excel 文檔的數(shù)據(jù)結構定義所使用的主文件,sml.xsd 中對通用標記語言相關的數(shù)據(jù)結構做了引用,其中包括依賴關系處理和簡單數(shù)據(jù)類型的相關的結構定義。中間比較多的以 dml- 開頭的 XSD 文件是與跨應用可視化相關的數(shù)據(jù)結構定義文件,例如圖片、圖表、圖形和 SmartArt 等相關的數(shù)據(jù)結構都是在以 dml- 開頭的 XSD 文件中定義。大家看到 dml- 開頭的 XSD 文件比較多,因為它是跨應用的,里面所涉及的 XML 標簽和屬性約為 8000 個,而 sml.xsd 中定義的標簽和屬性也有 2589 個之多。實現(xiàn) Excelize 過程中需要對大量的 XML 進行處理,需要定義對應的數(shù)據(jù)結構( struct 結構體),稱之為數(shù)據(jù)模型,由于數(shù)據(jù)模型的數(shù)量繁多且嵌套關系做錯綜復雜,為了自動化結構體代碼生成就衍生出了一個數(shù)據(jù)結構代碼生成器 xgen (XSD generator):
          xgen -i /path/to/your/xsd -o /path/to/your/output -l Go


          -i 參數(shù)指定了輸入源(input),可以傳入 XSD 目錄,-o 參數(shù)指定了代碼生成的輸出路徑(output),-l 參數(shù)用于指定生成代碼的編程語言(language),該工具也開源到了 GitHub 上:https://github.com/xuri/xgen。這樣我們就獲得了操作數(shù)據(jù)模型所需要的結構體定義代碼了。

          架構設計



          Excelize 技術能力劃分為基礎能力、樣式處理能力、數(shù)據(jù)處理能力、圖片/圖表、工作簿/工作表、單元格和模型處理,7 大部分:
          • 基礎能力 - 文件格式識別、媒體格式支持、元數(shù)據(jù)解析校驗、OPC 封裝與解構、依賴關系處理、擴展標記處理;
          • 樣式處理能力 - 邊框樣式、凍結窗格、字體樣式、行高 / 列寬、數(shù)字格式、色值計算;
          • 模型處理 - 模型組件化、模型校驗、計算引擎、升級擴展能力、模型糾錯驗證;
          • 圖片 / 圖表 - 2D / 3D 處理、簇狀 / 堆積 / 面積圖、柱形 / 錐形 / 棱錐 / 餅圖、氣泡 / 散點 / 折線圖、屬性設置能力;
          • 工作簿 / 工作表 - 可見性設置、行 / 列處理、屬性設置、工作表屬性、頁眉頁腳、視圖屬性、搜索能力、數(shù)據(jù)保護、頁面布局和流式讀寫;
          • 單元格 - 數(shù)據(jù)類型支持、字典、選區(qū)合并、富文本、超鏈接、批注處理、公式處理、樣式索引、單元格樣式和計算緩存處理;
          • 數(shù)據(jù)處理能力 - 數(shù)據(jù)驗證、時間處理、Crypto 加解密、單位轉換、表格 / 過濾器、數(shù)據(jù)透視表、條件格式、VBA 腳本

          公式詞法分析和解析器


          使用 Excelize 提供的 SetCellFormula API 可以方便地為單元格設置公式,設置的公式也可以在不依賴電子表格應用程序的前提下進行讀取和求值運算,下面我們通過一個例子來說明 Excelize 內部是如何實現(xiàn)公式求值的。對于這樣一個公式(為了便于理解,下面的公式僅包含操作數(shù)、操作符和函數(shù),其中的造作數(shù)在實際場景中可以替換為單元格的地址,通過引用取值進行運算):
          =1+SUM(SUM(1,2*3),4)

          Excelize 中對公式的詞法、語法分析均使用 Go 語言編寫。首先通過基于有限狀態(tài)機和堆棧令牌生成器的 efp(Excel Formula Parser)對公式文本字符進行詞法分析:
          import "github.com/xuri/efp"// ...ps := efp.ExcelParser()ps.Parse("=1+SUM(SUM(1,2*3),4)")println(ps.PrettyPrint())
          ?
          得到如下 Token:
          1 <Operand> <Number>+ <OperatorInfix> <Math>SUM <Function> <Start>    SUM <Function> <Start>        1 <Operand> <Number>        , <Argument> <>        2 <Operand> <Number>        * <OperatorInfix> <Math>        3 <Operand> <Number>     <Function> <Stop>    , <Argument> <>    4 <Operand> <Number> <Function> <Stop>

          至此就完成了對公式的詞法分析。

          公式引擎

          在了解完對公式的詞法分析后,我們來看一下 Excelize 中的公式引擎設計。對該中綴表達式進行求值計算,其中用到了 5 個棧(OPD:操作數(shù)、OPT:操作符、OPF:函數(shù)、OPFD:函數(shù)操作數(shù)、OPFT:函數(shù)操作符)和 1 個鏈表(ARGS:函數(shù)參數(shù))來實現(xiàn),運算過程狀態(tài)如下圖所示:

          通過上述過程即可實現(xiàn)對公式的求值運算,具體代碼可參考 Excelize 源代碼 calc.go 文件中的 evalInfoxExp 函數(shù)。公式函數(shù)的動態(tài)調用入口如下:

          // call formula function to evaluateresult, err := callFuncByName(&formulaFuncs{},    strings.NewReplacer(        "_xlfn", "", ".", "").Replace(        opfStack.Peek().(efp.Token).TValue),    []reflect.Value{        reflect.ValueOf(argsList),    })
          ?

          當執(zhí)行公式函數(shù)調用時,將 OPF(函數(shù)棧)棧頂元素類型推斷為 Token,元素的值即為函數(shù)名,先對函數(shù)名稱做預處理,然后進行函數(shù)調用,其中 callFuncByName 的實現(xiàn)如下面的代碼所示,它會根據(jù)給定的函數(shù) Receiver、函數(shù)名稱(name)和函數(shù)參數(shù)(params)進行函數(shù)調用:

          // callFuncByName calls the no error or only// error return function with reflect by given// receiver, name and parameters.func callFuncByName(    receiver interface{},    name string, params []reflect.Value) (    result string, err error) {    function := reflect.ValueOf(        receiver).MethodByName(name)    if function.IsValid() {        rt := function.Call(params)        if len(rt) == 0 {            return        }        if !rt[1].IsNil() {            err = rt[1].Interface().(error)            return        }        result = rt[0].Interface().(string)        return    }    err = fmt.Errorf("not support %s function",        name)    return}


          這樣僅需實現(xiàn)一些列函數(shù)簽名與 callFuncByName 形參數(shù)據(jù)類型相一致的公式函數(shù)即可,例如實現(xiàn)求和公式 SUM


          func (fn *formulaFuncs) SUM(argsList *list.List) (result string, err error)


          余弦三角函數(shù) COS

          func (fn *formulaFuncs) COS(argsList *list.List) (result string, err error)


          中位數(shù)函數(shù) MEDIAN

          func (fn *formulaFuncs) MEDIAN(argsList *list.List) (result string, err error)


          這樣避免了定義公式函數(shù)名與函數(shù)的映射關系,并具備高度的可擴展性,開發(fā)者可以根據(jù)此模式繼續(xù)實現(xiàn)其他公式函數(shù)或創(chuàng)建自定義公式函數(shù)。


          設計理念



          • 使用 Go 語言編寫,得益于其跨平臺、高性能的優(yōu)勢

          選擇使用 Go 語言編寫,支持并發(fā)設置單元格的值,在借助語言性能優(yōu)勢的同時也容易很方便地運行在各種平臺上:Linux、macOS、Windows 和嵌入式系統(tǒng)中。

          • 兼容性第一原則,以高保真無損編輯為目標
          Excelize 在從創(chuàng)建之初就以保障文檔兼容性為第一原則,這要求理解文檔內部大量的數(shù)據(jù)結構,并需要在運行時提供兼容性檢查、模型校驗和糾錯的能力。

          • 簡潔明了的 API 設計,遵循最小可用原則,兼顧其他語言開發(fā)者
          API 的設計力求見名知意,并盡可能做到簡潔、一種功能的實現(xiàn)僅可以通過一種方式來實現(xiàn),避免為開發(fā)者在使用過程中埋坑。對新人友好,API 的設計也考慮到其他語言的開發(fā)者使用習慣、降低學習成本。

          • 圖文并貌的多國語言參考文檔 https://xuri.me/excelize
          在 2016 年 Excelize 首次發(fā)布時 Go 語言的官方文檔 godoc 尚未支持插入圖片,而電子表格功能復雜多樣,很多場景下配合圖片說明更利于開發(fā)者理解,目前 Excelize 官方文檔已經(jīng)支持 9 種語言。

          • 代碼開源,豐富 Go 語言生態(tài)
          Excelize 在滿足業(yè)務需要的同時進行了開源,希望通過開源為 Go 語言生態(tài)的發(fā)展獻一份力,幫助到更多的朋友。沒有想到項目一開源就得到了許多來自社區(qū)的反饋,解決了眾多有同樣需求開發(fā)者的痛點,Excelize 也被應用到了許多不同的應用場景之中。

          • 時刻與開源社區(qū)保持積極互動
          通過開源收到了許多來自社區(qū)的開發(fā)者的建議和反饋,在這里要感謝朋友們的支持!與開源社區(qū)保持積極互動,使得項目愈加完善,吸引更多的開發(fā)者參與進來,通過 Pull Request、Issue、捐贈等各種方式支持開源產(chǎn)品、推動開源項目發(fā)展

          實踐應用


          下面通過 4 個典型的使用場景來介紹對 Excelize 的實踐應用。

          • 動態(tài)度表
          通過下面這段代碼,打開了一個名為 Book1 的工作簿,并通過 AddChart API 在指定的單元格區(qū)域上創(chuàng)建圖表,Excelize 目前支持創(chuàng)建 52 種圖表,每種圖表的枚舉值可以在文檔網(wǎng)站上查詢,圖表格式有很多可配置的參數(shù),例如對圖例項、折線圖的線條寬度和線端類型、氣泡圖的氣泡大小、坐標軸的刻度步長等都可配置。

          靈活運用這個例子,開發(fā)者還可以將創(chuàng)建好的帶有個性化設計圖表的電子表格文檔作為模版,使用 Excelize 打開后通過 API 修改圖表引用的數(shù)據(jù)區(qū)域單元格的值,另存為新的文件,這樣就實現(xiàn)了自定義基于模版生成電子表格文檔。
          f, err := excelize.OpenFile("Book1.xlsx")if err != nil {    fmt.Println(err)    return}f.AddChart("Sheet1", "E1", `{    "type": "col3DClustered",    "series": [    {        "name": "Sheet1!$A$2",        "categories": "Sheet1!$B$1:$D$1",        "values": "Sheet1!$B$2:$D$2"    },    {        "name": "Sheet1!$A$3",        "categories": "Sheet1!$B$1:$D$1",        "values": "Sheet1!$B$3:$D$3"    },    {        "name": "Sheet1!$A$4",        "categories": "Sheet1!$B$1:$D$1",        "values": "Sheet1!$B$4:$D$4"    }],    "title": { "name": "三維簇狀柱形圖" }}`)

          • 數(shù)據(jù)透視

          數(shù)據(jù)透視表是一種交互式的表,是計算、匯總和分析數(shù)據(jù)的強大工具,可以幫助我們了解數(shù)據(jù)中的對比情況、模式和趨勢。通過 Excelize 提供的 AddPivotTable API 我們在一個包含 5 列源數(shù)據(jù)的工作表上創(chuàng)建一個數(shù)據(jù)透視表:

          f.AddPivotTable(&excelize.PivotTableOption{    DataRange: "Sheet1!$A$1:$E$31",    PivotTableRange: "Sheet1!$G$2:$M$24",    Rows: []excelize.PivotTableField{        {Data: "月",         DefaultSubtotal: true},        {Data: "年"}},    Filter: []excelize.PivotTableField{        {Data: "區(qū)域"}},    Columns: []excelize.PivotTableField{        {Data: "類型",         DefaultSubtotal: true}},    Data: []excelize.PivotTableField{        {Data: "銷售額",         Name: "銷售額匯總",         Subtotal: "Sum"}},    RowGrandTotals: true,    ColGrandTotals: true,    ShowDrill: true,    ShowRowHeaders: true,    ShowColHeaders: true,    ShowLastColumn: true,})

          PivotTableOption 中可以指定數(shù)據(jù)透視表中的字段、篩選項、行/列數(shù)據(jù)、聚合維度等多種分析條件。上面的例子實現(xiàn)了按月對各區(qū)域在售的商品銷售額進行分類匯總,并支持按銷售區(qū)域、時間和分類進行篩選。


          • 大規(guī)模數(shù)據(jù)處理
          對于處理包含大規(guī)模數(shù)據(jù)的電子表格文檔,Excelize 提供了流式處理相關的 API:流式讀取可以使用行/列迭代器,生成大文件可以使用流式寫入器。下面的例子中我們首先通過 NewStreamWriter API 創(chuàng)建了一個流式寫入器,接著創(chuàng)建了字體樣式,并按行將數(shù)據(jù)寫入工作表中,與此同時還可以指定單元格的樣式,寫入結束后調用 Flush 結束流式寫入過程,創(chuàng)建了一個包含 102400 行 * 50 列累計 512 萬單元格的工作表。對于需要生成大規(guī)模數(shù)據(jù)的場景,流式 API 相比普通寫入在耗時和內存占用方面都有明顯的優(yōu)勢。
          streamWriter, err := file.NewStreamWriter("Sheet1")if err != nil {    fmt.Println(err)}styleID, err := file.NewStyle(    `{"font":{"color":"#777777"}}`)if err != nil {    fmt.Println(err)}if err := streamWriter.SetRow("A1",    []interface{}{        excelize.Cell{            StyleID: styleID, Value: "Data",        },    }); err != nil {    fmt.Println(err)}for rowID := 2; rowID <= 102400; rowID++ {    row := make([]interface{}, 50)    for colID := 0; colID < 50; colID++ {        row[colID] = rand.Intn(640000)    }    cell, _ := excelize.CoordinatesToCellName(1,        rowID)    if err := streamWriter.SetRow(cell,        row); err != nil {        fmt.Println(err)    }}streamWriter.Flush()

          • 與 Web 應用集成
          Excelize 在離線和在線業(yè)務場景中都很容易被集成。下面的例子中,我們創(chuàng)建一個簡單的 HTTP 服務器接收上傳的電子表格文檔,向接收到的電子表格文檔添加新工作表,并返回下載響應:
          func main() {    http.HandleFunc("/process", process)    http.ListenAndServe(":8090", nil)}

          使用 Excelize 的 OpenReader API 打開數(shù)據(jù)流,接著在內存中對電子表格進行處理:
          func process(w http.ResponseWriter, req *http.Request) {    file, _, err := req.FormFile("file")    if err != nil {        fmt.Fprintf(w, err.Error())        return    }    defer file.Close()    f, err := excelize.OpenReader(file)    if err != nil {        fmt.Fprintf(w, err.Error())        return    }    f.NewSheet("NewSheet")    w.Header().Set("Content-Disposition",        "attachment; filename=Book1.xlsx")    w.Header().Set("Content-Type",        req.Header.Get("Content-Type"))    if _, err := f.WriteTo(w); err != nil {        fmt.Fprintf(w, err.Error())    }    return}

          • 性能表現(xiàn)
          下圖展示了主流編程語言中典型電子表格開源基礎庫,基于普通個人計算機 (OS: macOS Catalina version 10.15.7, CPU: 3.4 GHz Intel Core i5, RAM: 16 GB 2400 MHz DDR4, HDD: 1 TB) 生成 50 列 102400 行純文本單元格的性能表現(xiàn):
          耗時情況
          內存表現(xiàn)

          結語


          總結今天的話題,本期 Go 開源說首先向大家介紹了開源項目 Excelize 的初衷與發(fā)展歷程;實現(xiàn)過程中的多項核心技術點:國際電子表格文檔格式標準和公式計算引擎的設計;設計理念與典型實踐應用場景。Excelize 的開源希望幫助到更多有需要的朋友,未來也將持續(xù)完善和優(yōu)化,同時也歡迎各位 Gopher 通過提交 Issue、Pull Request、Donate、Star 等各種形式參與到開源生態(tài)的建設中。

          問答環(huán)節(jié)


          Q: Excelize 目前在哪些項目中有應用?
          A: 很多企業(yè)應用在數(shù)據(jù)的輸入輸出鏈路上都有對電子表格文檔自動化處理的需求,比如將電子表格中的數(shù)據(jù)導入至系統(tǒng),而為了完成數(shù)據(jù)閉環(huán)一般也會有導出的功能,Excelize 在這些場景已經(jīng)有了廣泛的應用。
          Q: Excelize 與 Office Excel 和 WPS 都兼容嗎?
          A: Excelize 實現(xiàn)了電子表格文檔的國際標準,Office Excel、WPS、Apache Office、LibreOffice 和在線 Office 應用:Google Docs、石墨文檔等對 XLSX 電子表格文檔的支持都遵循同一標準。
          Q: 是否可以將打開的文件對象序列化后存入數(shù)據(jù)庫,在讀取時進行反序列化?
          A: 可以,Excelize 提供了 OpenReader API 打開數(shù)據(jù)流,WriteTo API 寫入數(shù)據(jù)流。
          Q: Excelize 是否有在邊緣計算場景的應用?
          A: 已經(jīng)有開發(fā)者將 Excelize 應用到了 Android 和其他一些嵌入式系統(tǒng)中了,在本地終端進行電子表格文檔操作。
          Q: 你覺得做開源項目最難的點是什么?
          A: 開源不僅是開放源代碼這樣簡單,需要投入持續(xù)的心力,最難的地方在于要有持續(xù)的熱情,不僅要管“生”還要管“養(yǎng)”。
          Q: 做開源項目的過程中有哪些點激勵著你做這件事?
          A: 來自開源社區(qū)和技術交流群里朋友們對項目的支持、在線下的技術分享活動中與使用 Excelize 的開發(fā)者交流,也了解到 Excelize 是如何應用到各種業(yè)務中的、Go 中國社區(qū)組織的開源項目評選的認可等,這些都是項目不斷發(fā)展的動力。
          Q: 做開源的過程中給自己帶來了哪些收獲?
          A: 做開源是一個與社區(qū)互動相互促進的過程,同時開源項目價值的被認可也帶給我了一些榮譽,更重要的是擴展了我的社交圈、結識了很多朋友,這些都是帶給我的收獲。

          《 Go 開源說 》欄目誠邀開源先鋒,如果您有優(yōu)秀的 Go 開源項目,歡迎點擊閱讀原文自薦或推薦,Go中國愿意助力您的開源項目推廣普及~
          瀏覽 66
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  a在线观看视频 | 免费三级久久 | 伊人大香蕉在线观看视频 | 免费无码久久久久成人 | 天堂在线免费视屏 |