最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

GO excelize讀取excel進(jìn)行時間類型轉(zhuǎn)換的示例代碼(自動轉(zhuǎn)換)

 更新時間:2024年10月25日 09:17:10   作者:chu_yubo  
我們經(jīng)常會遇到如何自動識別excel中的時間類型數(shù)據(jù)并轉(zhuǎn)化成對應(yīng)的 "Y-m-d H:i:s"類型數(shù)據(jù),本文小編給大家介紹了GO excelize讀取excel進(jìn)行時間類型轉(zhuǎn)換的示例代碼(自動轉(zhuǎn)換),需要的朋友可以參考下

需求分析

需求:如何自動識別excel中的時間類型數(shù)據(jù)并轉(zhuǎn)化成對應(yīng)的 "Y-m-d H:i:s"類型數(shù)據(jù)。

分析:excelize在讀取excel時,GetRows() 返回的都是字符串類型,并且有些時間類型的數(shù)據(jù)會進(jìn)行轉(zhuǎn)換,如果全部轉(zhuǎn)化成 float64 格式,然后轉(zhuǎn)換成對應(yīng)的字符串,并且excelize提供函數(shù)

func ExcelDateToTime(excelDate float64, use1904Format bool) (time.Time, error) {
    ...
}

可以將float64 轉(zhuǎn)換成time.Time 類型,time.Time 很容易轉(zhuǎn)化成對應(yīng)"Y-m-d H:i:s"格式字符串類型數(shù)據(jù)。所以我們的難點就在于如何自動識別excel中時日期時間類型數(shù)據(jù)

excel 單元格格式

以下3月1日數(shù)據(jù)寫入到excel中,excel都會識別成2024/3/1,但是對應(yīng)單元格格式不同,轉(zhuǎn)化為常規(guī)類型的話大部分都相同

  • 2024年3月1日------------- yyyy"年"m"月"d"日"-------------453352
  • 2024/3/1------------- yyyy/m/d-------------453352
  • Mar-24------------- mmm-yy-------------453352
  • 2024年3月------------- yyyy"年"m"月"-------------453352
  • 2024/3/1 0:00-------------yyyy/m/d h:mm-------------453352
  • '2024-03-01 00:00:00-------------通用-------------2024-03-01 00:00:00

excelize 讀取

func parseFileUrl(filePath string) ([]map[string]string, error) {
	f, err := excelize.OpenFile(filePath)
	if err != nil {
		return nil, err
	}
	sheetName := f.GetSheetName(0)
	rows, err := f.GetRows(sheetName)
	if err != nil {
		return nil, err
	}
	if len(rows) > 0 {
		for rowKey, cols := range rows {
			if len(cols) > 0 {
				for colKey, value := range cols {
					fmt.Println(rowKey, "-", colKey, ":", value)
				}
			}
		}
	}
	return nil, err
}

結(jié)果打印

0 - 0 : 45352
1 - 0 : 03-01-24
2 - 0 : Mar-24
3 - 0 : 45352
4 - 0 : 3/1/24 00:00
5 - 0 : 2024-03-01 00:00:00

由此我們可以看出時間類型打印出來的內(nèi)容不盡相同,這里我們可以想辦法把他們?nèi)哭D(zhuǎn)化成45352

這里我們就把他們轉(zhuǎn)化成常規(guī)類型,常規(guī)類型的數(shù)據(jù)大部分都為45352

func parseFileUrl(filePath string) ([]map[string]string, error) {
	f, err := excelize.OpenFile(filePath)
	if err != nil {
		return nil, err
	}
	sheetName := f.GetSheetName(0)
	rows, err := f.GetRows(sheetName)
	if err != nil {
		return nil, err
	}
    //轉(zhuǎn)化為常規(guī)類型,對應(yīng)style NumFmt 0
	styleId, _ := f.NewStyle(&excelize.Style{NumFmt: 0})
    //示例例中都放入A列,所以將A列數(shù)據(jù)全部轉(zhuǎn)化成對應(yīng)的常規(guī)類型
	_ = f.SetColStyle(sheetName, "A", styleId)
	rows, err = f.GetRows(sheetName)
	if len(rows) > 0 {
		for rowKey, cols := range rows {
			if len(cols) > 0 {
				for colKey, value := range cols {
					fmt.Println(rowKey, "-", colKey, ":", value)
				}
			}
		}
	}
	return nil, err
}

再次進(jìn)行打印

0 - 0 : 45352
1 - 0 : 45352
2 - 0 : 45352
3 - 0 : 45352
4 - 0 : 45352
5 - 0 : 2024-03-01 00:00:00

這時我們就可以看到大部分?jǐn)?shù)據(jù)都已經(jīng)轉(zhuǎn)化成了45352,所以接下來很簡單將數(shù)據(jù)轉(zhuǎn)化成float64類型,再轉(zhuǎn)化成time.time類型,最后轉(zhuǎn)化成我們想要的數(shù)據(jù)類型

func parseFileUrl(filePath string) ([]map[string]string, error) {
	f, err := excelize.OpenFile(filePath)
	if err != nil {
		return nil, err
	}
	sheetName := f.GetSheetName(0)
	rows, err := f.GetRows(sheetName)
	if err != nil {
		return nil, err
	}
	styleId, _ := f.NewStyle(&excelize.Style{NumFmt: 0})
	_ = f.SetColStyle(sheetName, "A", styleId)
	rows, err = f.GetRows(sheetName)
	if len(rows) > 0 {
		for rowKey, cols := range rows {
			if len(cols) > 0 {
				for colKey, value := range cols {
					timeFloat, err := strconv.ParseFloat(value, 64)
					if err != nil {
						//err 說明無法轉(zhuǎn)化成float64 那么有可能本身是字符串時間進(jìn)行返回
						timeTime, err := time.Parse("2006-01-02 15:04:05", value)
						if err != nil {
							fmt.Println(rowKey, "-", colKey, ":", value)
						} else {
							value = timeTime.Format("2006-01-02 15:04:05")
							fmt.Println(rowKey, "-", colKey, ":", value)
						}
						break
					}
					timeTime, _ := excelize.ExcelDateToTime(timeFloat, false)
					value = timeTime.Format("2006-01-02 15:04:05")
					fmt.Println(rowKey, "-", colKey, ":", value)
				}
			}
		}
	}
	return nil, err
}

打印結(jié)果

0 - 0 : 2024-03-01 00:00:00
1 - 0 : 2024-03-01 00:00:00
2 - 0 : 2024-03-01 00:00:00
3 - 0 : 2024-03-01 00:00:00
4 - 0 : 2024-03-01 00:00:00
5 - 0 : 2024-03-01 00:00:00

此時可以解決了我們的問題,指定對應(yīng)的列,轉(zhuǎn)化為常規(guī)類型,然后再轉(zhuǎn)化為float64(針對無法轉(zhuǎn)化的數(shù)據(jù)返回),再轉(zhuǎn)化為time.time類型,最后轉(zhuǎn)化成我們需要的類型

進(jìn)階

那么如何自動進(jìn)行轉(zhuǎn)化?

其實我們可以根據(jù)單元格自定義類型來進(jìn)行轉(zhuǎn)化,正如上面的例子,如當(dāng)單元格自定義類型為:

  • yyyy"年"m"月"d"日"
  • yyyy/m/d
  • mmm-yy
  • yyyy"年"m"月"
  • yyyy/m/d h:mm
  • ...
  • 等類型的時候我們需要將他們轉(zhuǎn)化成常規(guī)類型,然后根據(jù)后續(xù)操作轉(zhuǎn)化成我們想要的類型。

如何自定類型判斷呢?

其實根據(jù)上述轉(zhuǎn)化成常規(guī)類型的操作我們就可以知道是哪個字段來進(jìn)行確定單元格格式類型

styleId, _ := f.NewStyle(&excelize.Style{NumFmt: 0})

Style 中的 NumFmt 來進(jìn)行決定

我們可以看下excelize 中 針對 NumFmt 的注釋(在NewStyle方法上面有詳細(xì)注釋),這里我只粘貼部分注釋代碼

//	 Index | Format String
//	-------+----------------------------------------------------
//	 0     | General
//	 1     | 0
//	 2     | 0.00
//	 3     | #,##0
//	 4     | #,##0.00
//	 5     | ($#,##0_);($#,##0)
//	 6     | ($#,##0_);[Red]($#,##0)
//	 7     | ($#,##0.00_);($#,##0.00)
//	 8     | ($#,##0.00_);[Red]($#,##0.00)
//	 9     | 0%
//	 10    | 0.00%
//	 11    | 0.00E+00
//	 12    | # ?/?
//	 13    | # ??/??
//	 14    | m/d/yy
//	 15    | d-mmm-yy
//	 16    | d-mmm
//	 17    | mmm-yy
//	 18    | h:mm AM/PM
//	 19    | h:mm:ss AM/PM
//	 20    | h:mm
//	 21    | h:mm:ss
//	 22    | m/d/yy h:mm
//	 ...   | ...
//	 37    | (#,##0_);(#,##0)
//	 38    | (#,##0_);[Red](#,##0)
//	 39    | (#,##0.00_);(#,##0.00)
//	 40    | (#,##0.00_);[Red](#,##0.00)
//	 41    | _(* #,##0_);_(* (#,##0);_(* "-"_);_(@_)
//	 42    | _($* #,##0_);_($* (#,##0);_($* "-"_);_(@_)
//	 43    | _(* #,##0.00_);_(* (#,##0.00);_(* "-"??_);_(@_)
//	 44    | _($* #,##0.00_);_($* (#,##0.00);_($* "-"??_);_(@_)
//	 45    | mm:ss
//	 46    | [h]:mm:ss
//	 47    | mm:ss.0
//	 48    | ##0.0E+0
//	 49    | @

// Number format code in zh-cn language:
//
//	 Index | Symbol
//	-------+-------------------------------------------
//	 27    | yyyy"年"m"月"
//	 28    | m"月"d"日"
//	 29    | m"月"d"日"
//	 30    | m-d-yy
//	 31    | yyyy"年"m"月"d"日"
//	 32    | h"時"mm"分"
//	 33    | h"時"mm"分"ss"秒"
//	 34    | 上午/下午 h"時"mm"分"
//	 35    | 上午/下午 h"時"mm"分"ss"秒
//	 36    | yyyy"年"m"月
//	 50    | yyyy"年"m"月
//	 51    | m"月"d"日
//	 52    | yyyy"年"m"月
//	 53    | m"月"d"日
//	 54    | m"月"d"日
//	 55    | 上午/下午 h"時"mm"分
//	 56    | 上午/下午 h"時"mm"分"ss"秒
//	 57    | yyyy"年"m"月
//	 58    | m"月"d"日"

我們可以知道NumFmt 對應(yīng)的值代表著各種單元格格式,此時我們可以整理一下我們需要將其轉(zhuǎn)化成常規(guī)類型的數(shù)據(jù)(只做參考,并沒有全部實驗,自己可以把常用的實驗一下)

var ConversionTimeNumFmt = []int{
	14, //m/d/yy
	15, //d-mmm-yy
	17, //mmm-yy
	22, //m/d/yy h:mm
	27, // yyyy"年"m"月"
	30, //m-d-yy
	31, //yyyy"年"m"月"d"日"
	36, //yyyy"年"m"月
	50, //yyyy"年"m"月
	52, //yyyy"年"m"月
	57, //yyyy"年"m"月
}

好了,現(xiàn)在我們要轉(zhuǎn)換的單元格格式了,那么接下來我們就可以遍歷一下excel的全部單元格格式類型,看一下哪些字段需要進(jìn)行轉(zhuǎn)化了,不過接下來問題又來了,如何知道excel里面對應(yīng)的單元格格式呢

如何知道excel中單元格格式

excelize 中提供方法 GetCellStyle() 可以獲取該單元格的所有樣式對應(yīng)的styleId

// GetCellStyle provides a function to get cell style index by given worksheet
// name and cell reference. This function is concurrency safe.
func (f *File) GetCellStyle(sheet, cell string) (int, error) {
    ...
}

根據(jù)styleId 我們可以找到對應(yīng)的所有樣式配置 GetStyle()

// GetStyle provides a function to get style definition by given style index.
func (f *File) GetStyle(idx int) (*Style, error) {
    ...
}

單元格格式 就對應(yīng)的是 style.NumFmt

這時我們只需要知道每一個單元格的styleId 對應(yīng)的 style.NumFmt 就可以將數(shù)據(jù)進(jìn)行轉(zhuǎn)化(這里做了三個循環(huán),第一遍是獲取了對應(yīng)styleId, 第二遍是更改表樣式,將指定類型轉(zhuǎn)化為常規(guī)類型,第三遍就是獲取對應(yīng)的數(shù)據(jù))

// parseFileUrl 解析文件流excel
func parseFileUrl(filePath string) ([]map[string]string, error) {
	f, err := excelize.OpenFile(filePath)
	if err != nil {
		return nil, err
	}
	sheetName := f.GetSheetName(0)
	rows, err := f.GetRows(sheetName)
	if err != nil {
		return nil, err
	}
	//讀取excel 所有styleId 數(shù)組
	styles := make([]int, 0)
	//所有需要更改單元格格式的 styleId 數(shù)組
	needChangeStyleIds := make([]int, 0)
    //所更改的cells
	needChangeCells := make([]string, 0)
	if len(rows) > 0 {
		//需要轉(zhuǎn)化成的 style 對應(yīng)style Id
		styleIdZero, _ := f.NewStyle(&excelize.Style{NumFmt: 0})
		for rowKey, cols := range rows {
			if len(cols) > 0 {
				for colKey, _ := range cols {
					columnNumber, _ := excelize.CoordinatesToCellName(colKey+1, rowKey+1)
					styleId, _ := f.GetCellStyle(sheetName, columnNumber)
					if !arrayHelper.InArray(styles, styleId) {
						styles = append(styles, styleId)
					}
				}
			}
		}

		fmt.Println(styles)
		if len(styles) > 0 {
			for _, styleId := range styles {
				style, _ := f.GetStyle(styleId)
				if arrayHelper.InArray(ConversionTimeNumFmt, style.NumFmt) {
					needChangeStyleIds = append(needChangeStyleIds, styleId)
				}
			}
		}

		for rowKey, cols := range rows {
			if len(cols) > 0 {
				for colKey, _ := range cols {
					columnNumber, _ := excelize.CoordinatesToCellName(colKey+1, rowKey+1)
					styleId, _ := f.GetCellStyle(sheetName, columnNumber)
					if arrayHelper.InArray(needChangeStyleIds, styleId) {
						_ = f.SetCellStyle(sheetName, columnNumber, columnNumber, styleIdZero)
                        needChangeCells = append(needChangeCells, columnNumber)
					}
				}
			}
		}

		rows, err = f.GetRows(sheetName)
		if err != nil {
			return nil, err
		}

		if len(rows) > 0 {
			for rowKey, cols := range rows {
				if len(cols) > 0 {
					for colKey, value := range cols {
                        columnNumber, _ := excelize.CoordinatesToCellName(colKey+1, rowKey+1)
						if arrayHelper.InArray(needChangeCells, columnNumber) {
						    timeFloat, err := strconv.ParseFloat(value, 64)
						    if err != nil {
						    	//err 說明無法轉(zhuǎn)化成float64 那么有可能本身是字符串時間進(jìn)行返回
						    	timeTime, err := time.Parse("2006-01-02 15:04:05", value)
						    	if err != nil {
						    		fmt.Println(rowKey, "-", colKey, ":", value)
						    	} else {
						    		value = timeTime.Format("2006-01-02 15:04:05")
						    		fmt.Println(rowKey, "-", colKey, ":", value)
						    	}
						    	break
						    }
						    timeTime, _ := excelize.ExcelDateToTime(timeFloat, false)
						    value = timeTime.Format("2006-01-02 15:04:05")
						    fmt.Println(rowKey, "-", colKey, ":", value)
					    }
                    }
				}
			}
		}
	}
	return nil, err
}

var ConversionTimeNumFmt = []int{
	14, //m/d/yy
	15, //d-mmm-yy
	17, //mmm-yy
	22, //m/d/yy h:mm
	27, // yyyy"年"m"月"
	30, //m-d-yy
	31, //yyyy"年"m"月"d"日"
	36, //yyyy"年"m"月
	50, //yyyy"年"m"月
	52, //yyyy"年"m"月
	57, //yyyy"年"m"月
}

其中InArray方法為

// InArray 判斷元素是否再數(shù)組內(nèi)
func InArray[T int | float64 | string](array []T, value T) bool {
	for _, v := range array {
		if v == value {
			return true
		}
	}
	return false
}

通過三次遍歷操作,自動轉(zhuǎn)化了時間類型

以上就是GO excelize讀取excel進(jìn)行時間類型轉(zhuǎn)換的示例代碼(自動轉(zhuǎn)換)的詳細(xì)內(nèi)容,更多關(guān)于GO excelize excel時間類型轉(zhuǎn)換的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Go語言使用sqlx操作MySQL

    Go語言使用sqlx操作MySQL

    sqlx 包作為一個擴(kuò)展庫,它在 database/sql 的基礎(chǔ)上,提供了更高級別的便利,極大地簡化了數(shù)據(jù)庫操作,本文章將介紹如何通過sqlx包來操作 MySQL 數(shù)據(jù)庫,感興趣的可以了解下
    2024-11-11
  • Go?語言進(jìn)階freecache源碼學(xué)習(xí)教程

    Go?語言進(jìn)階freecache源碼學(xué)習(xí)教程

    這篇文章主要為大家介紹了Go?語言進(jìn)階freecache源碼學(xué)習(xí)教程,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-04-04
  • 詳解如何在Go中如何編寫出可測試的代碼

    詳解如何在Go中如何編寫出可測試的代碼

    在編寫測試代碼之前,還有一個很重要的點,容易被忽略,就是什么樣的代碼是可測試的代碼,所以本文就來聊一聊在?Go?中如何寫出可測試的代碼吧
    2023-08-08
  • 從源碼深入理解golang?RWMutex讀寫鎖操作

    從源碼深入理解golang?RWMutex讀寫鎖操作

    這篇文章主要介紹了從源碼深入理解golang?RWMutex讀寫鎖操作,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-05-05
  • 使用systemd部署和守護(hù)golang應(yīng)用程序的操作方法

    使用systemd部署和守護(hù)golang應(yīng)用程序的操作方法

    systemd是一個流行的守護(hù)進(jìn)程管理器,可以輕松管理服務(wù)的啟動、停止、重啟等操作,讓我們的應(yīng)用程序始終保持在線,本文介紹了如何使用systemd部署和守護(hù)golang應(yīng)用程序,感興趣的朋友一起看看吧
    2023-10-10
  • Go 庫性能分析工具pprof

    Go 庫性能分析工具pprof

    這篇文章主要為大家介紹了Go 庫性能分析工具pprof,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • Golang如何實現(xiàn)任意進(jìn)制轉(zhuǎn)換的方法示例

    Golang如何實現(xiàn)任意進(jìn)制轉(zhuǎn)換的方法示例

    進(jìn)制轉(zhuǎn)換是人們利用符號來計數(shù)的方法,進(jìn)制轉(zhuǎn)換由一組數(shù)碼符號和兩個基本因素“基數(shù)”與“位權(quán)”構(gòu)成,這篇文章主要給大家介紹了關(guān)于Golang如何實現(xiàn)10進(jìn)制轉(zhuǎn)換62進(jìn)制的方法,文中給出了詳細(xì)的示例代碼供大家參考學(xué)習(xí)學(xué)習(xí),下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-09-09
  • golang 實現(xiàn)時間戳和時間的轉(zhuǎn)化

    golang 實現(xiàn)時間戳和時間的轉(zhuǎn)化

    這篇文章主要介紹了golang 實現(xiàn)時間戳和時間的轉(zhuǎn)化操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-05-05
  • golang中實現(xiàn)給gif、png、jpeg圖片添加文字水印

    golang中實現(xiàn)給gif、png、jpeg圖片添加文字水印

    這篇文章主要介紹了golang中實現(xiàn)給gif、png、jpeg圖片添加文字水印,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-04-04
  • grpc-go如何通過context傳遞額外數(shù)據(jù)

    grpc-go如何通過context傳遞額外數(shù)據(jù)

    metadata是grpc內(nèi)置的,用RPC服務(wù)傳遞http頭數(shù)據(jù),分in和out兩種,對應(yīng)的key都為一個空struct,這篇文章主要介紹了grpc-go通過context傳遞額外數(shù)據(jù),需要的朋友可以參考下
    2024-02-02

最新評論

安岳县| 桃园市| 偃师市| 灵丘县| 明星| 确山县| 墨竹工卡县| 乌审旗| 米脂县| 南汇区| 柳林县| 麟游县| 华容县| 沾益县| 永新县| 翁牛特旗| 健康| 兴业县| 措美县| 宁国市| 九龙城区| 井研县| 武乡县| 昭平县| 平遥县| 常宁市| 喀喇| 休宁县| 卢龙县| 招远市| 横山县| 永和县| 烟台市| 津南区| 五大连池市| 工布江达县| 扬州市| 巴青县| 花莲县| 通许县| 方城县|