GO excelize 读取excel进行时间类型转换(自动转换)
GO excelize 读取excel进行时间类型转换(自动转换)
需求分析
需求:如何自动识别excel中的时间类型数据并转化成对应的 "Y-m-d H:i:s"类型数据。
分析:excelize在读取excel时,GetRows() 返回的都是字符串类型,并且有些时间类型的数据会进行转换,如果全部转化成 float64 格式,然后转换成对应的字符串,并且excelize提供函数
func ExcelDateToTime(excelDate float64, use1904Format bool) (time.Time, error) {...
}
可以将float64 转换成time.Time 类型,time.Time 很容易转化成对应"Y-m-d H:i:s"格式字符串类型数据。所以我们的难点就在于如何自动识别excel中时日期时间类型数据
excel 单元格格式
以下3月1日数据写入到excel中,excel都会识别成2024/3/1,但是对应单元格格式不同,转化为常规类型的话大部分都相同
- 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 }
结果打印
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
由此我们可以看出时间类型打印出来的内容不尽相同,这里我们可以想办法把他们全部转化成45352
这里我们就把他们转化成常规类型,常规类型的数据大部分都为45352func 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}//转化为常规类型,对应style NumFmt 0styleId, _ := f.NewStyle(&excelize.Style{NumFmt: 0})//示例例中都放入A列,所以将A列数据全部转化成对应的常规类型_ = 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 }
再次进行打印
0 - 0 : 45352 1 - 0 : 45352 2 - 0 : 45352 3 - 0 : 45352 4 - 0 : 45352 5 - 0 : 2024-03-01 00:00:00
这时我们就可以看到大部分数据都已经转化成了45352,所以接下来很简单将数据转化成float64类型,再转化成time.time类型,最后转化成我们想要的数据类型
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 说明无法转化成float64 那么有可能本身是字符串时间进行返回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 }
打印结果
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
此时可以解决了我们的问题,指定对应的列,转化为常规类型,然后再转化为float64(针对无法转化的数据返回),再转化为time.time类型,最后转化成我们需要的类型
进阶
那么如何自动进行转化?
其实我们可以根据单元格自定义类型来进行转化,正如上面的例子,如当单元格自定义类型为:
- yyyy"年"m"月"d"日"
- yyyy/m/d
- mmm-yy
- yyyy"年"m"月"
- yyyy/m/d h:mm
- ...
等类型的时候我们需要将他们转化成常规类型,然后根据后续操作转化成我们想要的类型。
如何自定类型判断呢?
其实根据上述转化成常规类型的操作我们就可以知道是哪个字段来进行确定单元格格式类型
styleId, _ := f.NewStyle(&excelize.Style{NumFmt: 0})
Style 中的 NumFmt 来进行决定
我们可以看下excelize 中 针对 NumFmt 的注释(在NewStyle方法上面有详细注释),这里我只粘贴部分注释代码
// 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 对应的值代表着各种单元格格式,此时我们可以整理一下我们需要将其转化成常规类型的数据(只做参考,并没有全部实验,自己可以把常用的实验一下)
var ConversionTimeNumFmt = []int{14, //m/d/yy15, //d-mmm-yy17, //mmm-yy22, //m/d/yy h:mm27, // yyyy"年"m"月"30, //m-d-yy31, //yyyy"年"m"月"d"日"36, //yyyy"年"m"月50, //yyyy"年"m"月52, //yyyy"年"m"月57, //yyyy"年"m"月 }
好了,现在我们要转换的单元格格式了,那么接下来我们就可以遍历一下excel的全部单元格格式类型,看一下哪些字段需要进行转化了,不过接下来问题又来了,如何知道excel里面对应的单元格格式呢
如何知道excel中单元格格式
excelize 中提供方法 GetCellStyle() 可以获取该单元格的所有样式对应的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) {... }
根据styleId 我们可以找到对应的所有样式配置 GetStyle()
// GetStyle provides a function to get style definition by given style index. func (f *File) GetStyle(idx int) (*Style, error) {... }
单元格格式 就对应的是 style.NumFmt
这时我们只需要知道每一个单元格的styleId 对应的 style.NumFmt 就可以将数据进行转化(这里做了三个循环,第一遍是获取了对应styleId, 第二遍是更改表样式,将指定类型转化为常规类型,第三遍就是获取对应的数据)
// 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 数组styles := make([]int, 0)//所有需要更改单元格格式的 styleId 数组needChangeStyleIds := make([]int, 0)//所更改的cellsneedChangeCells := make([]string, 0)if len(rows) > 0 {//需要转化成的 style 对应style IdstyleIdZero, _ := 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 说明无法转化成float64 那么有可能本身是字符串时间进行返回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/yy15, //d-mmm-yy17, //mmm-yy22, //m/d/yy h:mm27, // yyyy"年"m"月"30, //m-d-yy31, //yyyy"年"m"月"d"日"36, //yyyy"年"m"月50, //yyyy"年"m"月52, //yyyy"年"m"月57, //yyyy"年"m"月 }
其中InArray方法为
// InArray 判断元素是否再数组内 func InArray[T int | float64 | string](array []T, value T) bool {for _, v := range array {if v == value {return true}}return false }
通过三次遍历操作,自动转化了时间类型
相关文章:
GO excelize 读取excel进行时间类型转换(自动转换)
GO excelize 读取excel进行时间类型转换(自动转换) 需求分析 需求:如何自动识别excel中的时间类型数据并转化成对应的 "Y-m-d H:i:s"类型数据。 分析:excelize在读取excel时,GetRows() 返回的都是字符串类…...
【算法与数据结构】二分查找思想
#1024程序员节|征文# 正文: 二分查找(binary search)是一种基于分治策略的高效搜索算法。它利用数据的有序性,每轮缩小一半搜索范围,直至找到目标元素或搜索区间为空为止,其实有时候数据没有序…...
PHP PDO:安全、灵活的数据持久层解决方案
PHP PDO:安全、灵活的数据持久层解决方案 PHP PDO(PHP Data Objects)是一个轻量级的、具有兼容接口的数据持久层抽象层。它提供了一个统一的API来访问多种数据库系统,如MySQL、PostgreSQL、SQLite、Oracle等。PDO扩展在PHP 5.1.0…...
九、Linux实战案例:项目部署全流程深度解析
Linux实战案例:项目部署全流程深度解析 在当今信息技术领域,Linux服务器凭借其卓越的稳定性、安全性以及强大的性能表现,被广泛应用于各类项目部署场景之中。本文将全面深入地介绍如何将一个项目成功部署至Linux服务器的完整流程,…...
GIS常见前端开发框架
#1024程序员节|征文# 伴随GIS的发展,陆续出现了众多开源地图框架,这些地图框架与众多行业应用融合,极大地拓展了GIS的生命力,这里介绍几个常见的GIS前端开发框架,排名不分先后。 1.Leaflet https://leafl…...
Java | Leetcode Java题解之第506题相对名次
题目: 题解: class Solution {public String[] findRelativeRanks(int[] score) {int n score.length;String[] desc {"Gold Medal", "Silver Medal", "Bronze Medal"};int[][] arr new int[n][2];for (int i 0; i &…...
数据结构 - 堆
今天我们将学习新的数据结构-堆。 01定义 堆是一种特殊的二叉树,并且满足以下两个特性: (1)堆是一棵完全二叉树; (2)堆中任意一个节点元素值都小于等于(或大于等于)左…...
html----图片按钮,商品展示
源码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>图标</title><style>.box{width:…...
YOLOv11改进策略【卷积层】| ECCV-2024 小波卷积WTConv 增大感受野,降低参数量计算量,独家创新助力涨点
一、本文介绍 本文记录的是利用小波卷积WTConv模块优化YOLOv11的目标检测网络模型。WTConv的目的是在不出现过参数化的情况下有效地增加卷积的感受野,从而解决了CNN在感受野扩展中的参数膨胀问题。本文将其加入到深度可分离卷积中,有效降低模型参数量和计算量,并二次创新C3…...
redis高级篇之redis源码分析List类型quicklist底层演变 答疑159节
(1)ziplist压缩配置:list-compress-depth 0 表示一个quicklist两端不被压缩的节点个数。这里的节点是指quicklist双向链表的节点,而不是指ziplist里面的数据项个数参数list-compress-depth的取值含义如下: 0:是个特殊值,表示都不压缩。这是Redis的默认值…...
Elasticsearch 与 Lucene 的区别和联系
Elasticsearch 与 Lucene 的区别和联系 Elasticsearch 与 Lucene 的区别和联系一、知识背景Elasticsearch 简介Lucene 简介 二、Elasticsearch 和 Lucene 的区别适用场景性能优势和劣势架构设计的异同点 三、Elasticsearch和Lucene的联系四、Elasticsearch和Lucene的应用案例及…...
OpenCV视觉分析之运动分析(5)背景减除类BackgroundSubtractorMOG2的使用
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 基于高斯混合模型的背景/前景分割算法。 该类实现了在文献[320]和[319]中描述的高斯混合模型背景减除。 cv::BackgroundSubtractorMOG2 类是 O…...
【SAP Hana】X-DOC:数据仓库ETL如何抽取SAP中的CDS视图数据
【SAP Hana】X-DOC:数据仓库ETL如何抽取SAP中的CDS视图数据 1、无参CDS对应数据库视图2、有参CDS对应数据库表函数3、封装有参CDS为无参CDS,从而对应数据库视图 1、无参CDS对应数据库视图 select * from ZFCML_REP_V where mandt 300;2、有参CDS对应数…...
WPF的UpdateSourceTrigger属性
在WPF中,UpdateSourceTrigger属性用于控制数据绑定中何时将绑定目标(通常是UI元素)的值更新回绑定源(通常是数据对象)。这个属性有以下几个值: Default:这是默认值,对于不同的绑定目…...
2024-09-25 环境变量,进程地址空间
一、认识常见的环境变量 1. echo $HOME 输出当前用户对应的家目录 当用户登录系统时,流程如下: (1)用户登录系统后,系统启动Shell程序。 (2)启动bash shell,准备接收用户指令。 &a…...
中国移动机器人将投入养老场景;华为与APUS共筑AI医疗多场景应用
AgeTech News 一周行业大事件 华为与APUS合作,共筑AI医疗多场景应用 中国移动展出人形机器人,预计投入养老等场景 作为科技与奥富能签约,共拓智能适老化改造领域 天与养老与香港科技园,共探智慧养老新模式 中山大学合作中国…...
青少年编程能力等级测评CPA C++ 四级试卷(1)
青少年编程能力等级测评CPA C 四级试卷(1) 一、单项选择题(共15题,每题3分,共45分) CP4_1_1.在面向对象程序设计中,与数据构成一个相互依存的整体的是( )。 A. 对数据…...
树上任意两点的距离
题目描述 给出 n 个点的一棵树,多次询问两点之间的最短距离。 注意:边是双向的。 输入描述 第一行为两个整数 n 和 m。n 表示点数,m 表示询问次数; 下来 n−1 行,每行三个整数 x,y,k,表示点 x 和点 y 之间…...
【 thinkphp8 】00008 thinkphp8数据查询,常用table,name方法,进行数据查询汇总
前言:哈喽,大家好,今天给大家分享一篇文章!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏关注哦 💕 目录 【 t…...
Git的命令合集
关于Git的一些命令合集,会慢慢更新! 20241024程序员节开始写的,记录一下~~ git查看log、查看详细提交记录 会显示之前的提交记录 , 排序由近及远 git log log按q退出 git回退到某个commit命令: 退到/进到指定commit的sha码&…...
博客搭建之路:hexo搜索引擎收录
文章目录 hexo搜索引擎收录以百度为例 hexo搜索引擎收录 hexo版本5.0.2 npm版本6.14.7 next版本7.8.0 写博客的目的肯定不是就只有自己能看到,想让更多的人看到就需要可以让搜索引擎来收录对应的文章。hexo支持生成站点地图sitemap 在hexo下的_config.yml中配置站点…...
创建Windows系统还原点
系统保护...
Linux等保测评需要用到的命令
三权设置 查看账户情况 cd /home/ ll 设置审计账户 useradd shenji passwd shenji 修改密码 passwd新密码 设置管理账户 useradd guanli passwd guanli compgen -u 查看用户 切换到root账户 su root 设置审计用户权限 vim /etc/sudoers shenji ALL (root) NOPASSWD:…...
PostgreSQL的学习心得和知识总结(一百五十六)|auto_explain — log execution plans of slow queries
目录结构 注:提前言明 本文借鉴了以下博主、书籍或网站的内容,其列表如下: 1、参考书籍:《PostgreSQL数据库内核分析》 2、参考书籍:《数据库事务处理的艺术:事务管理与并发控制》 3、PostgreSQL数据库仓库…...
数据结构模板代码合集(不完整)
P3368 【模板】树状数组 2 #include <bits/stdc.h> using namespace std; const int maxn 5e5 7;int n, m, s, t; int ans; int a[maxn]; struct node{int l, r;int num; }tr[maxn * 4];void build(int p, int l, int r){tr[p] {l, r, 0};if(l r){tr[p].num a[l];r…...
shell脚本语法详解
目录 shell语法基础 指定shell解析器 注释 运行 变量 定义变量 引用变量 清除变量值 从键盘获取值 输入单值 添加输入提示语 读取多值 编辑 定义只读变量 环境变量 设置环境变量与查看环境变量 特殊变量 三种引号的作用与区别 小括号与大括号 参数传递 位…...
2021亚洲机器学习会议:面向单阶段跨域检测的域自适应YOLO(ACML2021)
原文标题:Domain Adaptive YOLO for One-Stage Cross-Domain Detection 中文标题:面向单阶段跨域检测的域自适应YOLO 1、Abstract 域转移是目标检测器在实际应用中推广的主要挑战。两级检测器的域自适应新兴技术有助于解决这个问题。然而,两级…...
面试题:描述在前端开发中,如何利用数据结构来优化页面渲染性能,并给出一个具体的示例。
在前端开发中,优化页面渲染性能是提升用户体验的关键之一。合理地使用数据结构可以有效地减少DOM操作的次数、提高数据处理的效率,从而加快页面的渲染速度。以下是一些策略,并给出一个具体的示例。 1. 使用合适的数据结构 数组与对象&#…...
微积分复习笔记 Calculus Volume 1 - 3.2 he Derivative as a Function
3.2 The Derivative as a Function - Calculus Volume 1 | OpenStax...
html 轮播图效果
轮播效果: 1、鼠标没有移入到banner,自动轮播 2、鼠标移入:取消自动轮播、移除开始自动轮播 3、点击指示点开始轮播到对应位置 4、点击前一个后一个按钮,轮播到上一个下一个图片 注意 最后一个图片无缝滚动,就是先克隆第一个图片…...
夺宝网站建设/长沙有实力seo优化
C基础(6)——数据的共享与保护 变量和对象定义在不同的位置(函数体内、类体内、函数原型参数表内、所有函数和类之外)。 其作用域、可见性、生存期都不同。 属于整个类的数据成员——静态数据成员。 用于处理静态数据成员的函数——静态成员函数。 友元…...
网站做好了 怎么做解析/全国疫情地区查询最新
LR常用的函数,协议不一样函数会不一样,这里简单的介绍下HTTP\WEBSERVICE\SOCKET协议常用函数: HTTP: web_set_max_html_param_len("1024");//设置1行数据最大长度,经常会使用到 web_reg_save_param("SupplierId&qu…...
合肥城市建设网站/百度影响力排名顺序
在C语言中对于float,用4字节存储,比如1.618000 ,在内存中为 160 26 207 631.000000, 在内存中为 0 0 128 63那么我有4个字节数据,比如{160 26 207 63},怎么转成float呢?其…...
外包公司做网站多少/四平网络推广
教你简单使用charles 抓取app 里的数据(一般多为http协议)常用的抓包软件有很多,mac 上的charles ,wireshark 等都是不错的抓包工具,今天就简单介绍一下如何安装,如何使用(已经会的小伙伴就不要拍砖了-绕行吧)…...
wordpress dz/东莞百度seo在哪里
Flex布局简单案例练习 一、自适应布局 不同的设备用不同的页面或局部伸缩 设计思路:判断设备的类型或控制局部的变化 1.1 页面跳转为例 index.html <script type"text/javascript">var redirect()>{// 获取设备信息let userAgent navigato…...
做论坛网站价格/广州白云区最新信息
问题 最新想通过界面批量输入数据到系统里面。 思路 使用自动化测试工具解决这个批量操作到问题。 Selenium 镜像 selenium/hubselenium/node-chrome 他们两者之间的关系,就是hub是管理者,node-chrome是被管理者。hub管理这所有测试集群的容器进程…...