131 lines
3.6 KiB
Go
131 lines
3.6 KiB
Go
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)
|
||
}
|