首頁 > 軟體

如何使用 Go 和 Excelize 構建電子試算表

2022-10-02 14:00:42

前言

分析任何規模的資料的重要性怎麼強調都不為過。 我們日常生活的幾乎每個部分都是資料驅動的,作為開發人員,在構建任何合理大小的應用程式時,首要考慮的因素之一是使用什麼資料庫以及如何構建資料。

但是,它不僅限於儲存資料,您還需要通過提取並以任何非技術人員都能理解的格式呈現這些資料來理解這些資料。 例如,電子商務企業每天都會產生大量資料,這意味著我們需要跟蹤產品庫存、月收入、財務報表等資訊。 目前,有許多服務提供這些型別的解決方案,但快速提取和呈現資料的最簡單方法之一是生成電子試算表或 CSV 檔案。

在本文中,我們將探索如何在 Go 中建立電子試算表,方法是構建一個簡單的費用報告並使用 Excelize 庫將其匯出為 CSV 格式。 中找到本教學的完整程式碼 您可以在 GitHub 儲存庫 。 讓我們開始吧!

  • 生成費用報告
  • 建立工作表
  • 新增資料和建立樣式
  • 儲存工作表
  • 匯出為 CSV

生成費用報告

費用報告是一份詳細的清單,儘可能詳細地顯示公司在一段時間內的支出。 我們將構建一個類似於下圖中的報告:

建立工作表

要開始使用,請確保您已安裝 Go ≥v1.15 並建立一個新的專案資料夾。

在專案目錄中,建立一個 main.go檔案並使用以下程式碼初始化 Go 模組:

$ mkdir <project-name>
$ cd <project-name>
$ touch main.go
$ go mod init github.com/<your-username>/<project-name>

The main.go file is the entry point of our Go application, and we use the generated go.mod file for dependency management. Next, install the Excelize library by running the command below:

$ go get github.com/xuri/excelize/v2

Excelize is a Go library with no dependencies that provides primitives for reading and writing to XLSX files and other supported spreadsheet file formats. In your main.go file, import Excelize, create a new file, create a new worksheet, and set the active sheet to the worksheet you just created:

package main
import "github.com/xuri/excelize/v2"
const (
   SheetName = "Expense Report"
)
func main() {
   var err error
   f := excelize.NewFile()
   index := f.NewSheet("Sheet1")
   f.SetActiveSheet(index)
   f.SetSheetName("Sheet1", SheetName)
}

新增資料和建立樣式

建立工作表後,我們可以開始構建報告。 首先,我們將設定一些尺寸以適應我們想要的結構,如下圖所示。

將以下程式碼塊新增到您的 main功能:

//main.go
//...
   err = f.SetColWidth(SheetName, "A", "A", 6)
   err = f.SetColWidth(SheetName, "H", "H", 6)
   err = f.SetColWidth(SheetName, "B", "B", 12)
   err = f.SetColWidth(SheetName, "C", "C", 16)
   err = f.SetColWidth(SheetName, "D", "D", 13)
   err = f.SetColWidth(SheetName, "E", "E", 15)
   err = f.SetColWidth(SheetName, "F", "F", 22)
   err = f.SetColWidth(SheetName, "G", "G", 13)

我們只需要列 A至 G對於報告,所以我們使用 SetColWidth調整列的寬度以滿足我們的要求。 你會注意到我們已經定義了一個 error變數到頂部 main函數,我們只是將這些函數返回的任何錯誤分配給它。 理想情況下,您應該正確處理每個錯誤,因為它在 Go 中是慣用的,但保持程式碼最少也是可以的。

Over 200k developers use LogRocket to create better digital experiences Learn more →

報告的第一部分包含靜態資訊,因此我們將對其進行寫死。 將以下程式碼塊新增到您的 main 函數中:

//main.go
//...
   err = f.SetRowHeight(SheetName, 1, 12)
   err = f.MergeCell(SheetName, "A1", "H1")
​
   err = f.SetRowHeight(SheetName, 2, 25)
   err = f.MergeCell(SheetName, "B2", "D2")
​
   style, err := f.NewStyle(&excelize.Style{Font: &excelize.Font{Size: 20, Color: "6d64e8"}})
   err = f.SetCellStyle(SheetName, "B2", "D2", style)
   err = f.SetSheetRow(SheetName, "B2", &[]interface{}{"Gigashots Inc."})
   err = f.MergeCell(SheetName, "B3", "D3")
   err = f.SetSheetRow(SheetName, "B3", &[]interface{}{"3154 N Richardt Ave"})
​
   err = f.MergeCell(SheetName, "B4", "D4")
   err = f.SetSheetRow(SheetName, "B4", &[]interface{}{"Indianapolis, IN 46276"})
​
   style, err = f.NewStyle(&excelize.Style{Font: &excelize.Font{Color: "666666"}})
   err = f.MergeCell(SheetName, "B5", "D5")
   err = f.SetCellStyle(SheetName, "B5", "D5", style)
   err = f.SetSheetRow(SheetName, "B5", &[]interface{}{"(317) 854-0398"})
​
   style, err = f.NewStyle(&excelize.Style{Font: &excelize.Font{Size: 32, Color: "2B4492", Bold: true}})
   err = f.MergeCell(SheetName, "B7", "G7")
   err = f.SetCellStyle(SheetName, "B7", "G7", style)
   err = f.SetSheetRow(SheetName, "B7", &[]interface{}{"Expense Report"})
​
   style, err = f.NewStyle(&excelize.Style{Font: &excelize.Font{Size: 13, Color: "E25184", Bold: true}})
   err = f.MergeCell(SheetName, "B8", "C8")
   err = f.SetCellStyle(SheetName, "B8", "C8", style)
   err = f.SetSheetRow(SheetName, "B8", &[]interface{}{"09/04/00 - 09/05/00"})
​
   style, err = f.NewStyle(&excelize.Style{Font: &excelize.Font{Size: 13, Bold: true}})
   err = f.SetCellStyle(SheetName, "B10", "G10", style)
   err = f.SetSheetRow(SheetName, "B10", &[]interface{}{"Name", "", "Employee ID", "", "Department"})
   err = f.MergeCell(SheetName, "B10", "C10")
   err = f.MergeCell(SheetName, "D10", "E10")
   err = f.MergeCell(SheetName, "F10", "G10")
​
   style, err = f.NewStyle(&excelize.Style{Font: &excelize.Font{Color: "666666"}})
   err = f.SetCellStyle(SheetName, "B11", "G11", style)
   err = f.SetSheetRow(SheetName, "B11", &[]interface{}{"John Doe", "", "#1B800XR", "", "Brand & Marketing"})
   err = f.MergeCell(SheetName, "B11", "C11")
   err = f.MergeCell(SheetName, "D11", "E11")
   err = f.MergeCell(SheetName, "F11", "G11")
​
   style, err = f.NewStyle(&excelize.Style{Font: &excelize.Font{Size: 13, Bold: true}})
   err = f.SetCellStyle(SheetName, "B13", "G13", style)
   err = f.SetSheetRow(SheetName, "B13", &[]interface{}{"Manager", "", "Purpose"})
   err = f.MergeCell(SheetName, "B13", "C13")
   err = f.MergeCell(SheetName, "D13", "E13")
​
   style, err = f.NewStyle(&excelize.Style{Font: &excelize.Font{Color: "666666"}})
   err = f.SetCellStyle(SheetName, "B14", "G14", style)
   err = f.SetSheetRow(SheetName, "B14", &[]interface{}{"Jane Doe", "", "Brand Campaign"})
   err = f.MergeCell(SheetName, "B14", "C14")
   err = f.MergeCell(SheetName, "D14", "E14")

這段程式碼中有很多內容,所以讓我們分解一下。

如前所述,Excelize 提供了一組原始函數來操作電子試算表。 您需要的每個功能只需要在檔案物件上呼叫一個方法,該方法接受一些引數。

在這種情況下,我們使用了五種主要方法:

  • SetRowHeight
  • MergeCell
  • NewStyle
  • SetCellStyle
  • SetSheetRow

SetRowHeight調整給定行的高度,以及 MergeCell將一行中的多個單元格合併為一個單元格。 要編寫樣式,我們可以使用 excelize.Stylestruct,它提供了定義自定義樣式所需的屬性。 這 NewStyle方法只是採用 Style物件並返回表示樣式的索引。

定義您的自定義樣式後,我們可以使用 SetCellStyle將樣式應用於單個單元格或一系列單元格。 我們用 SetSheetRow將資料新增到單行中的一個單元格或一系列單元格。 它接受一個介面切片,它是任何原始資料型別的容器。 切片是位置的,每個元素將從提供的軸開始放置在相應的單元格中。 因此,在合併多個單元格的某些情況下,我們使用了空字串。

報告的第二部分是一個包含任意長度的動態資料的表格,這意味著我們不能像以前那樣只定義每一行的內容。 表中表示的資料遵循定義的結構,因此我們可以迴圈傳入資料並動態建立每一行。

讓我們定義一些代表費用列表的任意資料。

在您的頂部 main.go檔案,在 main函數,新增以下變數:

//main.go
//...
var (
   expenseData = [][]interface{}{
      {"2022-04-10", "Flight", "Trip to San Fransisco", "", "", "$3,462.00"},
      {"2022-04-10", "Hotel", "Trip to San Fransisco", "", "", "$1,280.00"},
      {"2022-04-12", "Swags", "App launch", "", "", "$862.00"},
      {"2022-03-15", "Marketing", "App launch", "", "", "$7,520.00"},
      {"2022-04-11", "Event hall", "App launch", "", "", "$2,080.00"},
   }
)
//...

現在,將以下程式碼塊新增到您的 main 函數中:

//main.go
//...
   style, err = f.NewStyle(&excelize.Style{
      Font:      &excelize.Font{Size: 13, Bold: true, Color: "2B4492"},
      Alignment: &excelize.Alignment{Vertical: "center"},
   })
   err = f.SetCellStyle(SheetName, "B17", "G17", style)
   err = f.SetSheetRow(SheetName, "B17", &[]interface{}{"Date", "Category", "Description", "", "Notes", "Amount"})
   err = f.MergeCell(SheetName, "D17", "E17")
   err = f.SetRowHeight(SheetName, 17, 32)
​
   startRow := 18
   for i := startRow; i < (len(expenseData) + startRow); i++ {
      var fill string
      if i%2 == 0 {
         fill = "F3F3F3"
      } else {
         fill = "FFFFFF"
      }
      style, err = f.NewStyle(&excelize.Style{
         Fill:      excelize.Fill{Type: "pattern", Pattern: 1, Color: []string{fill}},
         Font:      &excelize.Font{Color: "666666"},
         Alignment: &excelize.Alignment{Vertical: "center"},
      })
      err = f.SetCellStyle(SheetName, fmt.Sprintf("B%d", i), fmt.Sprintf("G%d", i), style)
      err = f.SetSheetRow(SheetName, fmt.Sprintf("B%d", i), &expenseData[i-18])
      err = f.SetCellRichText(SheetName, fmt.Sprintf("C%d", i), []excelize.RichTextRun{
         {Text: expenseData[i-18][1].(string), Font: &excelize.Font{Bold: true}},
      })
​
      err = f.MergeCell(SheetName, fmt.Sprintf("D%d", i), fmt.Sprintf("E%d", i))
      err = f.SetRowHeight(SheetName, i, 18)
   }

我們仍然使用相同的方法來組合樣式和新增資料。 但是,我們正在迴圈 expenseData列出並將每個專案新增到當前行。 我們開始迴圈 18,這是電子試算表中的當前行。 為了使表格的行更加清晰易讀,我們通過使用 modulo手術。

匯出為 CSV

到目前為止,我們已經探索了使用 XLSX 檔案,但是,還有其他格式適合呈現這種資料。 CSV 檔案是一個文字檔案,其中包含由逗號分隔的資料行,主要用於匯入和匯出資料。

考慮一種情況,我們希望將費用報告中的表儲存在某個自託管資料庫中。 我們可以將這個表格提取為 CSV 格式,然後通過幾個步驟將其匯入資料庫。

首先,在主函數之外建立一個名為 generateCSV並在下面新增程式碼塊:

//main.go
//...
type Axis struct {
   row int
   col string
}
​
func generateCSV(f *excelize.File, start, end Axis) error {
   var data [][]string
​
   for i := start.row; i <= end.row; i++ {
      row := []string{}
      for j := []rune(start.col)[0]; j <= []rune(end.col)[0]; j++ {
         value, err := f.GetCellValue(SheetName, fmt.Sprintf("%s%d", string(j), i), excelize.Options{})
         if err != nil {
            return err
         }
         row = append(row, value)
      }
      data = append(data, row)
   }
​
   file, err := os.Create("expenses.csv")
   if err != nil {
      return err
   }
   defer f.Close()
​
   writer := csv.NewWriter(file)
   return writer.WriteAll(data)
}

這 generateCSV函數接受一個 excelize.File型別、起始軸和結束軸。 軸只是構成單元格的行和列的組合。 我們迴圈遍歷每一行,對於每一行,我們迴圈遍歷開始軸和結束軸邊界內的每一列。

然後我們使用 f.GetCellValue提取每個單元格的當前值。 因為列表示為字母字串,所以我們將它們轉換為符文以獲取底層的 unicode 十進位制。 最後,我們將提取的資料儲存到 .csv檔案 使用標準庫中的 CSV 包 。

我們可以在儲存工作表並傳遞檔案控制程式碼後呼叫此函數。

在你的 main函數,新增以下程式碼塊:

//main.go
///...
   err = f.SaveAs("expense-report.xlsx")
   err = generateCSV(f, Axis{17, "B"}, Axis{22, "G"})
​
   if err != nil {
      log.Fatal(err)
   }

我們提供了我們之前為工作表建立的檔案和表示表格範圍的軸。

如果你執行 main.go檔案,您應該會看到生成的 XLSX 檔案和 CSV 檔案:

$ go run main.go

結論

以電子試算表相容的格式呈現資料有很多用例,包括分析、轉換和驗證。 在本文中,我們學習瞭如何使用 Go 和 Excelize 包通過生成費用報告來處理電子試算表。

當您考慮 Excelize 開箱即用的其他功能時,我們只是觸及了皮毛。 您可以新增影象、建立圖表、迷你圖、形狀、資料透視表等。 我希望你學到了一些新的東西,如果你有任何問題,請發表評論。 快樂編碼!

LogRocket 主動顯示和診斷您的應用程式和網站中最重要的問題

成千上萬的工程和產品團隊使用 LogRocket 來減少了解技術和可用性問題的根本原因所需的時間。 使用 LogRocket,您將減少與客戶來回對話的時間,並消除無休止的故障排除過程。 LogRocket 讓您可以花更多時間構建新事物,而減少修復錯誤的時間。

到此這篇關於如何使用 Go 和 Excelize 構建電子試算表的文章就介紹到這了,更多相關Go 與 Excelize 構建表格內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com