Files
go-dockit/workbook/utils.go
2025-04-16 16:12:33 +08:00

131 lines
3.6 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package workbook
import (
"fmt"
"strconv"
"strings"
"time"
)
// CellRef 根据行列索引生成单元格引用
// 例如: CellRef(0, 0) 返回 "A1"
func CellRef(row, col int) string {
return fmt.Sprintf("%s%d", ColIndexToName(col), row+1)
}
// ColIndexToName 将列索引转换为列名
// 例如: ColIndexToName(0) 返回 "A", ColIndexToName(25) 返回 "Z", ColIndexToName(26) 返回 "AA"
func ColIndexToName(colIndex int) string {
if colIndex < 0 {
return ""
}
result := ""
for colIndex >= 0 {
remainder := colIndex % 26
result = string(rune('A'+remainder)) + result
colIndex = colIndex/26 - 1
if colIndex < 0 {
break
}
}
return result
}
// ColNameToIndex 将列名转换为列索引
// 例如: ColNameToIndex("A") 返回 0, ColNameToIndex("Z") 返回 25, ColNameToIndex("AA") 返回 26
func ColNameToIndex(colName string) int {
colName = strings.ToUpper(colName)
result := 0
for i := 0; i < len(colName); i++ {
result = result*26 + int(colName[i]-'A'+1)
}
return result - 1
}
// ParseCellRef 解析单元格引用为行列索引
// 例如: ParseCellRef("A1") 返回 (0, 0)
func ParseCellRef(cellRef string) (row, col int, err error) {
// 找到字母和数字的分界点
index := 0
for index < len(cellRef) && (cellRef[index] < '0' || cellRef[index] > '9') {
index++
}
if index == 0 || index == len(cellRef) {
return 0, 0, fmt.Errorf("invalid cell reference: %s", cellRef)
}
colName := cellRef[:index]
rowStr := cellRef[index:]
// 解析行号
rowNum, err := strconv.Atoi(rowStr)
if err != nil {
return 0, 0, fmt.Errorf("invalid row number in cell reference: %s", cellRef)
}
// 解析列名
colIndex := ColNameToIndex(colName)
return rowNum - 1, colIndex, nil
}
// FormatDate 将时间格式化为Excel日期格式
func FormatDate(t time.Time, format string) string {
// Excel日期格式映射到Go时间格式
format = strings.Replace(format, "yyyy", "2006", -1)
format = strings.Replace(format, "yy", "06", -1)
format = strings.Replace(format, "mm", "01", -1)
format = strings.Replace(format, "dd", "02", -1)
format = strings.Replace(format, "hh", "15", -1)
format = strings.Replace(format, "ss", "05", -1)
// 确保分钟格式正确处理
if strings.Contains(format, "15:01") {
format = strings.Replace(format, "01", "04", -1)
}
return t.Format(format)
}
// GetExcelSerialDate 将时间转换为Excel序列日期值
// Excel日期系统: 1900年1月1日为1每天加1
func GetExcelSerialDate(t time.Time) float64 {
// 转换到当地时区,避免时区问题
t = t.Local()
// Excel基准日期: 1900年1月0日但Excel实际以1900年1月1日为1
baseDate := time.Date(1899, 12, 30, 0, 0, 0, 0, time.Local)
// 计算相差的天数(包括小数部分来表示时间)
days := t.Sub(baseDate).Hours() / 24.0
// Excel有一个关于1900年2月29日的错误实际上1900年不是闰年
// 如果日期在1900年3月1日之后需要加1来匹配Excel的错误
if t.After(time.Date(1900, 3, 1, 0, 0, 0, 0, time.Local)) {
days += 1
}
// Excel中1900年1月1日是1而不是0
return days + 1
}
// GetTimeFromExcelSerialDate 将Excel序列日期值转换为时间
func GetTimeFromExcelSerialDate(serialDate float64) time.Time {
// Excel基准日期: 1900年1月0日
baseDate := time.Date(1899, 12, 30, 0, 0, 0, 0, time.Local)
// 减1是因为Excel中1900年1月1日是1而不是0
daysPassed := serialDate - 1
// 处理Excel的1900年2月29日错误
if serialDate >= 60 {
daysPassed -= 1
}
// 计算时间
duration := time.Duration(daysPassed * 24 * float64(time.Hour))
return baseDate.Add(duration)
}