中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁 > news >正文

前端做網(wǎng)站難嗎哈爾濱最新今日頭條新聞

前端做網(wǎng)站難嗎,哈爾濱最新今日頭條新聞,個人網(wǎng)站備案 備注,網(wǎng)站設(shè)計的研究方案前言 最近在學(xué)go操作excel,畢竟在web開發(fā)里,操作excel是非常非常常見的。這里我選擇用 excelize 庫來實現(xiàn)操作excel。 為了方便和通用,我們需要把導(dǎo)入導(dǎo)出進行封裝,這樣以后就可以很方便的拿來用,或者進行擴展。 我參…

前言

最近在學(xué)go操作excel,畢竟在web開發(fā)里,操作excel是非常非常常見的。這里我選擇用 excelize 庫來實現(xiàn)操作excel。

為了方便和通用,我們需要把導(dǎo)入導(dǎo)出進行封裝,這樣以后就可以很方便的拿來用,或者進行擴展。

在這里插入圖片描述

我參考的是這篇文章:【GO】excelize導(dǎo)入導(dǎo)出封裝

功能

這個導(dǎo)入導(dǎo)出封裝,除了基本的導(dǎo)入導(dǎo)出,我還需要一些其他功能。例如:設(shè)置隔行背景色、自適應(yīng)行高、忽略指定字段或?qū)С鲋付ㄗ侄?、?fù)雜表頭 等等。

因為實際項目中,操作excel不可能只是導(dǎo)出一個很簡單的excel,實際項目中的要求往往要復(fù)雜的多。

在這里插入圖片描述

導(dǎo)入

導(dǎo)入有以下幾個通用的實現(xiàn)

  • 導(dǎo)入單個sheet的數(shù)據(jù)(已完成)
  • 導(dǎo)入指定sheet的數(shù)據(jù)(已完成)
  • 導(dǎo)入多個sheet的數(shù)據(jù)(已完成)

導(dǎo)出

導(dǎo)出呢,就要復(fù)雜很多了,一級表頭的普通導(dǎo)出是最簡單的,實際項目中往往還會有多級表頭,然后不管是一級還是多級表頭,還需要有各種要求的樣式,隔行背景色、自適應(yīng)行高這種已經(jīng)算簡單的了,復(fù)雜點的還有一對多的縱向單元格合并。

所以導(dǎo)出需要實現(xiàn)以下這些:

  • 普通導(dǎo)出(已完成)
    • 一級表頭
    • 單個sheet
  • 復(fù)雜表頭、樹形結(jié)構(gòu)表頭導(dǎo)出(未完成)
  • 多個sheet導(dǎo)出(未完成)
  • 基于map導(dǎo)出(未完成)
  • 一對多縱向合并單元格(未完成)
  • 動態(tài)導(dǎo)出列(已完成)
    • 忽略指定字段
    • 導(dǎo)出指定字段
    • 動態(tài)更改表頭名稱
  • 隔行背景色樣式(已完成)
  • 自適應(yīng)行高樣式(已完成)

這篇文章我們就來實現(xiàn)那幾個已完成(未完成的還沒開始實現(xiàn)呢,還有好多沒實現(xiàn),哭了)

在這里插入圖片描述

其實上面這些功能,我之前早就在Java中實現(xiàn)了。感興趣的話可以去這篇文章看看,有完整代碼:

poi+easypoi實現(xiàn)表頭多層循環(huán),多級動態(tài)表頭、樹形結(jié)構(gòu)動態(tài)表頭、縱向合并單元格、多個sheet導(dǎo)出

實現(xiàn)

我們先在項目中,創(chuàng)建一個excel文件夾,里面放的就是我們封裝的實現(xiàn)函數(shù)

在這里插入圖片描述

準備

既然是通用的導(dǎo)入導(dǎo)出,那每次導(dǎo)入導(dǎo)出不同表格時,不可能說寫死導(dǎo)入哪些列(列名),而是應(yīng)該是按照不同表格對應(yīng)的不同結(jié)構(gòu)體來進行解析數(shù)據(jù)或?qū)С鰯?shù)據(jù)。

所以我們可以定義一個專門用于解析excel的tag結(jié)構(gòu)體(類似于easypoi的@Excel注解),在這個tag結(jié)構(gòu)體定義幾個字段,什么表頭名稱、列下標、列寬啊這些

用的時候呢,就是在不同結(jié)構(gòu)體中,使用反引號去定義 表頭名稱、列下標、列寬 這些的值。

excel.go

自定義一個tag結(jié)構(gòu)體

package excelimport ("github.com/pkg/errors""github.com/xuri/excelize/v2""regexp""strconv""strings"
)// 定義正則表達式模式
const (ExcelTagKey = "excel"Pattern     = "name:(.*?);|index:(.*?);|width:(.*?);|needMerge:(.*?);|replace:(.*?);"
)type ExcelTag struct {Value     interface{}Name      string // 表頭標題Index     int    // 列下標(從0開始)Width     int    // 列寬NeedMerge bool   // 是否需要合并Replace   string // 替換(需要替換的內(nèi)容_替換后的內(nèi)容。比如:1_未開始 ==> 表示1替換為未開始)
}// 構(gòu)造函數(shù),返回一個帶有默認值的 ExcelTag 實例
func NewExcelTag() ExcelTag {return ExcelTag{// 導(dǎo)入時會根據(jù)這個下標來拿單元格的值,當(dāng)目標結(jié)構(gòu)體字段沒有設(shè)置index時,// 解析字段tag值時Index沒讀到就一直默認為0,拿單元格的值時,就始終拿的是第一列的值Index: -1, // 設(shè)置 Index 的默認值為 -1}
}

定義好了tag結(jié)構(gòu)體,我們還需要給它綁定解析tag的方法

// 讀取字段tag值
func (e *ExcelTag) GetTag(tag string) (err error) {// 編譯正則表達式re := regexp.MustCompile(Pattern)matches := re.FindAllStringSubmatch(tag, -1)if len(matches) > 0 {for _, match := range matches {for i, val := range match {if i != 0 && val != "" {e.setValue(match, val)}}}} else {err = errors.New("未匹配到值")return}return
}// 設(shè)置ExcelTag 對應(yīng)字段的值
func (e *ExcelTag) setValue(tag []string, value string) {if strings.Contains(tag[0], "name") {e.Name = value}if strings.Contains(tag[0], "index") {v, _ := strconv.ParseInt(value, 10, 8)e.Index = int(v)}if strings.Contains(tag[0], "width") {v, _ := strconv.ParseInt(value, 10, 8)e.Width = int(v)}if strings.Contains(tag[0], "needMerge") {v, _ := strconv.ParseBool(value)e.NeedMerge = v}if strings.Contains(tag[0], "replace") {e.Replace = value}
}

用的時候,比如在某個用戶信息結(jié)構(gòu)體中

在這里插入圖片描述

自定義一個excel對象結(jié)構(gòu)體

定義好了tag結(jié)構(gòu)體,同樣是在 excel.go 文件中,我們還需要一個excel對象結(jié)構(gòu)體,里面有excel file對象、樣式等屬性,然后再給它綁定設(shè)置樣式的方法。

type Excel struct {F             *excelize.File // excel 對象TitleStyle    int            // 表頭樣式HeadStyle     int            // 表頭樣式ContentStyle1 int            // 主體樣式1,無背景色ContentStyle2 int            // 主體樣式2,有背景色
}// 初始化
func ExcelInit() (e *Excel) {e = &Excel{}// excel構(gòu)建e.F = excelize.NewFile()// 初始化樣式e.getTitleRowStyle()e.getHeadRowStyle()e.getDataRowStyle()return e
}// 獲取邊框樣式
func getBorder() []excelize.Border {return []excelize.Border{ // 邊框{Type: "top", Color: "000000", Style: 1},{Type: "bottom", Color: "000000", Style: 1},{Type: "left", Color: "000000", Style: 1},{Type: "right", Color: "000000", Style: 1},}
}// 標題樣式
func (e *Excel) getTitleRowStyle() {e.TitleStyle, _ = e.F.NewStyle(&excelize.Style{Alignment: &excelize.Alignment{ // 對齊方式Horizontal: "center", // 水平對齊居中Vertical:   "center", // 垂直對齊居中},Fill: excelize.Fill{ // 背景顏色Type:    "pattern",Color:   []string{"#fff2cc"},Pattern: 1,},Font: &excelize.Font{ // 字體Bold: true,Size: 16,},Border: getBorder(),})
}// 列頭行樣式
func (e *Excel) getHeadRowStyle() {e.HeadStyle, _ = e.F.NewStyle(&excelize.Style{Alignment: &excelize.Alignment{ // 對齊方式Horizontal: "center", // 水平對齊居中Vertical:   "center", // 垂直對齊居中WrapText:   true,     // 自動換行},Fill: excelize.Fill{ // 背景顏色Type:    "pattern",Color:   []string{"#FDE9D8"},Pattern: 1,},Font: &excelize.Font{ // 字體Bold: true,Size: 14,},Border: getBorder(),})
}// 數(shù)據(jù)行樣式
func (e *Excel) getDataRowStyle() {style := excelize.Style{}style.Border = getBorder()style.Alignment = &excelize.Alignment{Horizontal: "center", // 水平對齊居中Vertical:   "center", // 垂直對齊居中WrapText:   true,     // 自動換行}style.Font = &excelize.Font{Size: 12,}e.ContentStyle1, _ = e.F.NewStyle(&style)style.Fill = excelize.Fill{ // 背景顏色Type:    "pattern",Color:   []string{"#cce7f5"},Pattern: 1,}e.ContentStyle2, _ = e.F.NewStyle(&style)
}

導(dǎo)入

接下來我們就可以來實現(xiàn)導(dǎo)入函數(shù)的封裝了,在 excel_import.go 文件中

package excelimport ("github.com/pkg/errors""github.com/xuri/excelize/v2""go-web/util""reflect""strconv"
)// ImportExcel 導(dǎo)入數(shù)據(jù)(單個sheet)
// 需要在傳入的結(jié)構(gòu)體中的字段加上tag:excel:"title:列頭名稱;"
// f 獲取到的excel對象、dst 導(dǎo)入目標對象【傳指針】
// headIndex 表頭的索引,從0開始(用于獲取表頭名字)
// startRow 頭行行數(shù)(從第startRow+1行開始掃)
func ImportExcel(f *excelize.File, dst interface{}, headIndex, startRow int) (err error) {sheetName := f.GetSheetName(0) // 單個sheet時,默認讀取第一個sheeterr = importData(f, dst, sheetName, headIndex, startRow)return
}// ImportBySheet 導(dǎo)入數(shù)據(jù)(讀取指定sheet)sheetName Sheet名稱
func ImportBySheet(f *excelize.File, dst interface{}, sheetName string, headIndex, startRow int) (err error) {// 當(dāng)需要讀取多個sheet時,可以通過下面的方式,來調(diào)用 ImportBySheet 這個函數(shù)//sheetList := f.GetSheetList()//for _, sheetName := range sheetList {//	ImportBySheet(f,dst,sheetName,headIndex,startRow)//}err = importData(f, dst, sheetName, headIndex, startRow)return
}// 解析數(shù)據(jù)
func importData(f *excelize.File, dst interface{}, sheetName string, headIndex, startRow int) (err error) {rows, err := f.GetRows(sheetName) // 獲取所有行if err != nil {err = errors.New(sheetName + "工作表不存在")return}dataValue := reflect.ValueOf(dst) // 取目標對象的元素類型、字段類型和 tag// 判斷數(shù)據(jù)的類型if dataValue.Kind() != reflect.Ptr || dataValue.Elem().Kind() != reflect.Slice {err = errors.New("Invalid data type")}heads := []string{}                        // 表頭dataType := dataValue.Elem().Type().Elem() // 獲取導(dǎo)入目標對象的類型信息// 遍歷行,解析數(shù)據(jù)并填充到目標對象中for rowIndex, row := range rows {if rowIndex == headIndex {heads = row}if rowIndex < startRow { // 跳過頭行continue}newData := reflect.New(dataType).Elem() // 創(chuàng)建新的目標對象// 遍歷目標對象的字段for i := 0; i < dataType.NumField(); i++ {// 這里要用構(gòu)造函數(shù),構(gòu)造函數(shù)里指定了Index默認值為-1,當(dāng)目標結(jié)構(gòu)體的tag沒有指定index的話,那么 excelTag.Index 就一直為0// 那么 row[excelizeIndex] 就始終是 row[0],始終拿的是第一列的數(shù)據(jù)var excelTag = NewExcelTag()field := dataType.Field(i) // 獲取字段信息和tagtag := field.Tag.Get(ExcelTagKey)if tag == "" { // 如果tag不存在,則跳過continue}err = excelTag.GetTag(tag)if err != nil {return}cellValue := ""if excelTag.Index >= 0 { // 當(dāng)tag里指定了index時,根據(jù)這個index來拿數(shù)據(jù)excelizeIndex := excelTag.Index // 解析tag的值if excelizeIndex >= len(row) {  // 防止下標越界continue}cellValue = row[excelizeIndex] // 獲取單元格的值} else { // 否則根據(jù)表頭名稱來拿數(shù)據(jù)if util.IsContain(heads, excelTag.Name) { // 當(dāng)tag里的表頭名稱和excel表格里面的表頭名稱相匹配時if i >= len(row) { // 防止下標越界continue}cellValue = row[i] // 獲取單元格的值}}// 根據(jù)字段類型設(shè)置值switch field.Type.Kind() {case reflect.Int:v, _ := strconv.ParseInt(cellValue, 10, 64)newData.Field(i).SetInt(v)case reflect.String:newData.Field(i).SetString(cellValue)}}// 將新的目標對象添加到導(dǎo)入目標對象的slice中dataValue.Elem().Set(reflect.Append(dataValue.Elem(), newData))}return
}

導(dǎo)入這里用到了一個 IsContain 函數(shù),代碼如下:

// 判斷數(shù)組中是否包含指定元素
func IsContain(items interface{}, item interface{}) bool {switch items.(type) {case []int:intArr := items.([]int)for _, value := range intArr {if value == item.(int) {return true}}case []string:strArr := items.([]string)for _, value := range strArr {if value == item.(string) {return true}}default:return false}return false
}

導(dǎo)出

excel_export.go 文件中

package excelimport ("fmt""github.com/pkg/errors""github.com/xuri/excelize/v2""net/http""reflect""sort""strings"
)// GetExcelColumnName 根據(jù)列數(shù)生成 Excel 列名
func GetExcelColumnName(columnNumber int) string {columnName := ""for columnNumber > 0 {columnNumber--columnName = string('A'+columnNumber%26) + columnNamecolumnNumber /= 26}return columnName
}// ================================= 普通導(dǎo)出 =================================// NormalDownLoad 導(dǎo)出excel并下載(單個sheet)
func NormalDownLoad(fileName, sheet, title string, isGhbj bool, list interface{}, res http.ResponseWriter) error {f, err := NormalDynamicExport(list, sheet, title, "", isGhbj, false, nil)if err != nil {return err}DownLoadExcel(fileName, res, f)return nil
}// NormalDynamicDownLoad 動態(tài)導(dǎo)出excel并下載(單個sheet)
// isIgnore 是否忽略指定字段(true 要忽略的字段 false 要導(dǎo)出的字段)
// fields 選擇的字段,多個字段用逗號隔開,最后一個字段后面也要加逗號,如:字段1,字段2,字段3,
// changeHead 要改變表頭的字段,格式是{"字段1":"更改的表頭1","字段2":"更改的表頭2"}
func NormalDynamicDownLoad(fileName, sheet, title, fields string, isGhbj, isIgnore bool,list interface{}, changeHead map[string]string, res http.ResponseWriter) error {f, err := NormalDynamicExport(list, sheet, title, fields, isGhbj, isIgnore, changeHead)if err != nil {return err}DownLoadExcel(fileName, res, f)return nil
}// NormalDynamicExport 導(dǎo)出excel
// ** 需要在傳入的結(jié)構(gòu)體中的字段加上tag:excelize:"title:列頭名稱;index:列下標(從0開始);"
// list 需要導(dǎo)出的對象數(shù)組、sheet sheet名稱、title 標題、isGhbj 是否設(shè)置隔行背景色
func NormalDynamicExport(list interface{}, sheet, title, fields string, isGhbj, isIgnore bool, changeHead map[string]string) (file *excelize.File, err error) {e := ExcelInit()err = ExportExcel(sheet, title, fields, isGhbj, isIgnore, list, changeHead, e)if err != nil {return}return e.F, err
}// 構(gòu)造表頭(endColName 最后一列的列名 dataRow 數(shù)據(jù)行開始的行號)
func normalBuildTitle(e *Excel, sheet, title, fields string, isIgnore bool, changeHead map[string]string, dataValue reflect.Value) (endColName string, dataRow int, err error) {dataType := dataValue.Type().Elem() // 獲取導(dǎo)入目標對象的類型信息var exportTitle []ExcelTag          // 遍歷目標對象的字段for i := 0; i < dataType.NumField(); i++ {var excelTag ExcelTagfield := dataType.Field(i) // 獲取字段信息和tagtag := field.Tag.Get(ExcelTagKey)if tag == "" { // 如果非導(dǎo)出則跳過continue}if fields != "" { // 選擇要導(dǎo)出或要忽略的字段if isIgnore && strings.Contains(fields, field.Name+",") { // 忽略指定字段continue}if !isIgnore && !strings.Contains(fields, field.Name+",") { // 導(dǎo)出指定字段continue}}err = excelTag.GetTag(tag)if err != nil {return}// 更改指定字段的表頭標題if changeHead != nil && changeHead[field.Name] != "" {excelTag.Name = changeHead[field.Name]}exportTitle = append(exportTitle, excelTag)}// 排序sort.Slice(exportTitle, func(i, j int) bool {return exportTitle[i].Index < exportTitle[j].Index})var titleRowData []interface{} // 列頭行for i, colTitle := range exportTitle {endColName := GetExcelColumnName(i + 1)if colTitle.Width > 0 { // 根據(jù)給定的寬度設(shè)置列寬_ = e.F.SetColWidth(sheet, endColName, endColName, float64(colTitle.Width))} else {_ = e.F.SetColWidth(sheet, endColName, endColName, float64(20)) // 默認寬度為20}titleRowData = append(titleRowData, colTitle.Name)}endColName = GetExcelColumnName(len(titleRowData)) // 根據(jù)列數(shù)生成 Excel 列名if title != "" {dataRow = 3 // 如果有title,那么從第3行開始就是數(shù)據(jù)行,第1行是title,第2行是表頭e.F.SetCellValue(sheet, "A1", title)e.F.MergeCell(sheet, "A1", endColName+"1") // 合并標題單元格e.F.SetCellStyle(sheet, "A1", endColName+"1", e.TitleStyle)e.F.SetRowHeight(sheet, 1, float64(30)) // 第一行行高e.F.SetRowHeight(sheet, 2, float64(30)) // 第二行行高e.F.SetCellStyle(sheet, "A2", endColName+"2", e.HeadStyle)if err = e.F.SetSheetRow(sheet, "A2", &titleRowData); err != nil {return}} else {dataRow = 2 // 如果沒有title,那么從第2行開始就是數(shù)據(jù)行,第1行是表頭e.F.SetRowHeight(sheet, 1, float64(30))e.F.SetCellStyle(sheet, "A1", endColName+"1", e.HeadStyle)if err = e.F.SetSheetRow(sheet, "A1", &titleRowData); err != nil {return}}return
}// 構(gòu)造數(shù)據(jù)行
func normalBuildDataRow(e *Excel, sheet, endColName, fields string, row int, isGhbj, isIgnore bool, dataValue reflect.Value) (err error) {//實時寫入數(shù)據(jù)for i := 0; i < dataValue.Len(); i++ {startCol := fmt.Sprintf("A%d", row)endCol := fmt.Sprintf("%s%d", endColName, row)item := dataValue.Index(i)typ := item.Type()num := item.NumField()var exportRow []ExcelTagmaxLen := 0 // 記錄這一行中,數(shù)據(jù)最多的單元格的值的長度//遍歷結(jié)構(gòu)體的所有字段for j := 0; j < num; j++ {dataField := typ.Field(j) //獲取到struct標簽,需要通過reflect.Type來獲取tag標簽的值tagVal := dataField.Tag.Get(ExcelTagKey)if tagVal == "" { // 如果非導(dǎo)出則跳過continue}if fields != "" { // 選擇要導(dǎo)出或要忽略的字段if isIgnore && strings.Contains(fields, dataField.Name+",") { // 忽略指定字段continue}if !isIgnore && !strings.Contains(fields, dataField.Name+",") { // 導(dǎo)出指定字段continue}}var dataCol ExcelTagerr = dataCol.GetTag(tagVal)fieldData := item.FieldByName(dataField.Name) // 取字段值rwsTemp := fieldData.Len()                    // 當(dāng)前單元格內(nèi)容的長度if rwsTemp > maxLen {                         //這里取每一行中的每一列字符長度最大的那一列的字符maxLen = rwsTemp}// 替換if dataCol.Replace != "" {split := strings.Split(dataCol.Replace, ",")for j := range split {s := strings.Split(split[j], "_") // 根據(jù)下劃線進行分割,格式:需要替換的內(nèi)容_替換后的內(nèi)容if s[0] == fieldData.String() {dataCol.Value = s[1]}}} else {dataCol.Value = fieldData}if err != nil {return}exportRow = append(exportRow, dataCol)}// 排序sort.Slice(exportRow, func(i, j int) bool {return exportRow[i].Index < exportRow[j].Index})var rowData []interface{} // 數(shù)據(jù)列for _, colTitle := range exportRow {rowData = append(rowData, colTitle.Value)}if isGhbj && row%2 == 0 {_ = e.F.SetCellStyle(sheet, startCol, endCol, e.ContentStyle2)} else {_ = e.F.SetCellStyle(sheet, startCol, endCol, e.ContentStyle1)}if maxLen > 25 { // 自適應(yīng)行高d := maxLen / 25f := 25 * d_ = e.F.SetRowHeight(sheet, row, float64(f))} else {_ = e.F.SetRowHeight(sheet, row, float64(25)) // 默認行高25}if err = e.F.SetSheetRow(sheet, startCol, &rowData); err != nil {return}row++}return
}// 下載
func DownLoadExcel(fileName string, res http.ResponseWriter, file *excelize.File) {// 設(shè)置響應(yīng)頭res.Header().Set("Content-Type", "text/html; charset=UTF-8")res.Header().Set("Content-Type", "application/octet-stream")res.Header().Set("Content-Disposition", "attachment; filename="+fileName+".xlsx")res.Header().Set("Access-Control-Expose-Headers", "Content-Disposition")err := file.Write(res) // 寫入Excel文件內(nèi)容到響應(yīng)體if err != nil {http.Error(res, err.Error(), http.StatusInternalServerError)return}
}

測試

ok,終于寫完了導(dǎo)入導(dǎo)出,接下來就是測試啦

在這里插入圖片描述

excel_main.go 文件中

package mainimport ("fmt""github.com/xuri/excelize/v2""go-web/util/excel"
)func main() {//export()imports()
}type Test struct {Id       string `excel:"name:用戶賬號;"`Name     string `excel:"name:用戶姓名;index:1;"`Email    string `excel:"name:用戶郵箱;width:25;"`Com      string `excel:"name:所屬公司;"`Dept     string `excel:"name:所在部門;"`RoleKey  string `excel:"name:角色代碼;"`RoleName string `excel:"name:角色名稱;replace:1_超級管理員,2_普通用戶;"`Remark   string `excel:"name:備注;width:40;"`
}// 導(dǎo)出
func export() {var testList = []Test{{"fuhua", "符華", "fuhua@123.com", "太虛劍派", "開發(fā)部", "CJGLY", "1", "備注備注"},{"baiye", "白夜", "baiye@123.com", "天命科技有限公司", "執(zhí)行部", "PTYG", "2", ""},{"chiling", "熾翎", "chiling@123.com", "太虛劍派", "行政部", "PTYG", "2", "備注備注備注備注"},{"yunmo", "云墨", "yunmo@123.com", "太虛劍派", "財務(wù)部", "CJGLY", "1", ""},{"yuelun", "月輪", "yuelun@123.com", "天命科技有限公司", "執(zhí)行部", "CJGLY", "1", ""},{"xunyu", "迅羽","xunyu@123.com哈哈哈哈哈哈哈哈這里是最大行高測試哈哈哈哈哈哈哈哈這11111111111里是最大行高測試哈哈哈哈哈哈哈哈這里是最大行高測試","天命科技有限公司", "開發(fā)部", "PTYG", "2","備注備注備注備注com哈哈哈哈哈哈哈哈這里是最大行高測試哈哈哈哈哈哈哈哈這里是最大行高測試哈哈哈哈哈哈哈哈這里是最大行高測里是最大行高測試哈哈哈哈哈哈哈哈這里是最大行高測試"},}changeHead := map[string]string{"Id": "賬號", "Name": "真實姓名"}//f, err := excel.NormalExport(testList, "Sheet1", "用戶信息", "Id,Email,", true, true, changeHead)f, err := excel.NormalDynamicExport(testList, "Sheet1", "用戶信息", "", true, false, changeHead)if err != nil {fmt.Println(err)return}f.Path = "C:\\Users\\Administrator\\Desktop\\測試.xlsx"if err := f.Save(); err != nil {fmt.Println(err)return}
}// 導(dǎo)入
func imports() {f, err := excelize.OpenFile("C:\\Users\\Administrator\\Desktop\\測試.xlsx")if err != nil {fmt.Println("文件打開失敗")}importList := []Test{}err = excel.ImportExcel(f, &importList, 1, 2)if err != nil {fmt.Println(err)}for _, t := range importList {fmt.Println(t)}
}

實現(xiàn)效果

然后我們再來看看實現(xiàn)效果,說實話,我覺得這表格還挺好看的哩,不愧是我

在這里插入圖片描述

導(dǎo)出

在這里插入圖片描述

導(dǎo)入

在這里插入圖片描述

最后

這樣,我們就實現(xiàn)了一個通用的導(dǎo)入導(dǎo)出工具封裝。

上面這些就是全部代碼啦,后續(xù)等我把剩下幾個復(fù)雜導(dǎo)出弄完(挖坑…),我會把這些代碼全部抽出來,做成一個獨立的組件模塊,然后上傳到Git上,這樣以后不管做哪個項目,用的時候直接在go.mod引入就可以啦~完美😁
在這里插入圖片描述

好啦,以上就是本篇文章的全部內(nèi)容了,如果你覺得對你有幫助或者覺得博主寫得不錯,千萬不要吝嗇你的大拇指喲(^U^)ノ~YO

在這里插入圖片描述

http://www.risenshineclean.com/news/57849.html

相關(guān)文章:

  • 企業(yè)營銷網(wǎng)站服務(wù)器1g夠個人怎么開跨境電商店鋪
  • 濟南網(wǎng)站制作創(chuàng)意百度信息流推廣
  • 專業(yè)做俄語網(wǎng)站建設(shè)司拉人頭最暴利的app
  • 開平做網(wǎng)站重慶關(guān)鍵詞seo排名
  • 網(wǎng)站建設(shè)教程下載上海百度搜索排名優(yōu)化
  • 做網(wǎng)站導(dǎo)流點金推廣優(yōu)化公司
  • 建一個o2o網(wǎng)站如何優(yōu)化推廣網(wǎng)站
  • 淘寶上可以做網(wǎng)站嗎域名ip查詢查網(wǎng)址
  • 中國紀檢監(jiān)察報電子報北京網(wǎng)站優(yōu)化步驟
  • 做網(wǎng)站需要多少錢呢網(wǎng)站制作鄭州
  • 英文版網(wǎng)站建設(shè)方案廈門seo公司
  • 誰能幫我做網(wǎng)站活動策劃方案
  • 企業(yè)官網(wǎng)和小程序的區(qū)別內(nèi)江seo
  • 優(yōu)秀網(wǎng)站設(shè)計欣賞圖片廣告策劃案優(yōu)秀案例
  • 南昌建站推廣公司如何優(yōu)化搜索引擎的搜索功能
  • 做美直播網(wǎng)站設(shè)計網(wǎng)頁
  • 建企業(yè)門戶網(wǎng)站刷神馬關(guān)鍵字排名軟件
  • 網(wǎng)站的空間域名如何銷售自己產(chǎn)品方法有哪些
  • 寧波做網(wǎng)站費用網(wǎng)站開發(fā)是做什么的
  • 網(wǎng)站運營心得推廣普通話手抄報模板可打印
  • 知名b2b網(wǎng)站怎么給自己的網(wǎng)站設(shè)置關(guān)鍵詞
  • 怎么做網(wǎng)站電影沈陽企業(yè)網(wǎng)站seo公司
  • 網(wǎng)站的安全度google下載app
  • 網(wǎng)站內(nèi)部資源推廣案例在線培訓(xùn)課程
  • 網(wǎng)站做代理還可以刷水嗎視頻外鏈工具
  • 國家企業(yè)信息年報系統(tǒng)優(yōu)化方案
  • 專門做nba評論的網(wǎng)站獨立站優(yōu)化
  • 做網(wǎng)站常用的css無錫網(wǎng)站優(yōu)化
  • 百度做網(wǎng)站按點擊量收費嗎品牌廣告圖片
  • 徐州靠譜網(wǎng)站開發(fā)買鏈接網(wǎng)