Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e3d9bbbcc5 |
@@ -13,6 +13,7 @@ Excel导出工具提供了将数据导出到Excel文件的功能,支持结构
|
|||||||
- **自定义格式化**:支持自定义字段值的格式化函数
|
- **自定义格式化**:支持自定义字段值的格式化函数
|
||||||
- **自动列宽**:自动调整列宽以适应内容
|
- **自动列宽**:自动调整列宽以适应内容
|
||||||
- **表头样式**:自动应用表头样式(加粗、背景色等)
|
- **表头样式**:自动应用表头样式(加粗、背景色等)
|
||||||
|
- **智能工作表管理**:自动处理工作表的创建和删除,避免产生空sheet
|
||||||
- **ExportData接口**:支持实现ExportData接口进行高级定制
|
- **ExportData接口**:支持实现ExportData接口进行高级定制
|
||||||
|
|
||||||
## 使用方法
|
## 使用方法
|
||||||
@@ -114,7 +115,7 @@ columns := []factory.ExportColumn{
|
|||||||
Header: "创建时间",
|
Header: "创建时间",
|
||||||
Field: "CreatedAt",
|
Field: "CreatedAt",
|
||||||
Width: 20,
|
Width: 20,
|
||||||
Format: excel.FormatDateTimeDefault, // 使用便捷的格式化函数
|
Format: excel.AdaptTimeFormatter(tools.FormatDateTime), // 使用适配器直接调用tools函数
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Header: "状态",
|
Header: "状态",
|
||||||
@@ -215,8 +216,18 @@ file.SetCellStyle("Sheet2", "A1", "A1", style)
|
|||||||
|
|
||||||
**返回:** 错误信息
|
**返回:** 错误信息
|
||||||
|
|
||||||
|
**工作表处理逻辑:**
|
||||||
|
- 如果 `sheetName` 为空或未指定,默认使用 "Sheet1"
|
||||||
|
- 如果指定的工作表已存在,直接使用该工作表
|
||||||
|
- 如果指定的工作表不存在,会自动创建新工作表
|
||||||
|
- 如果使用自定义名称(非"Sheet1"),会自动删除默认的"Sheet1"工作表,避免产生空sheet
|
||||||
|
|
||||||
**示例:**
|
**示例:**
|
||||||
```go
|
```go
|
||||||
|
// 使用默认Sheet1
|
||||||
|
fac.ExportToExcel(w, "", columns, users)
|
||||||
|
|
||||||
|
// 使用自定义工作表名称
|
||||||
fac.ExportToExcel(w, "用户列表", columns, users)
|
fac.ExportToExcel(w, "用户列表", columns, users)
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -232,8 +243,18 @@ fac.ExportToExcel(w, "用户列表", columns, users)
|
|||||||
|
|
||||||
**返回:** 错误信息
|
**返回:** 错误信息
|
||||||
|
|
||||||
|
**工作表处理逻辑:**
|
||||||
|
- 如果 `sheetName` 为空或未指定,默认使用 "Sheet1"
|
||||||
|
- 如果指定的工作表已存在,直接使用该工作表
|
||||||
|
- 如果指定的工作表不存在,会自动创建新工作表
|
||||||
|
- 如果使用自定义名称(非"Sheet1"),会自动删除默认的"Sheet1"工作表,避免产生空sheet
|
||||||
|
|
||||||
**示例:**
|
**示例:**
|
||||||
```go
|
```go
|
||||||
|
// 使用默认Sheet1
|
||||||
|
fac.ExportToExcelFile("users.xlsx", "", columns, users)
|
||||||
|
|
||||||
|
// 使用自定义工作表名称
|
||||||
fac.ExportToExcelFile("users.xlsx", "用户列表", columns, users)
|
fac.ExportToExcelFile("users.xlsx", "用户列表", columns, users)
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -270,38 +291,42 @@ type ExportColumn struct {
|
|||||||
- `Width`: 列宽,0表示自动调整
|
- `Width`: 列宽,0表示自动调整
|
||||||
- `Format`: 格式化函数,用于自定义字段值的显示格式
|
- `Format`: 格式化函数,用于自定义字段值的显示格式
|
||||||
|
|
||||||
### 便捷函数
|
### 格式化函数适配器
|
||||||
|
|
||||||
#### excel.FormatDateTime(layout string) func(interface{}) string
|
#### excel.AdaptTimeFormatter(fn func(time.Time, ...string) string) func(interface{}) string
|
||||||
|
|
||||||
创建日期时间格式化函数。
|
适配器函数:将tools包的格式化函数转换为Excel Format字段需要的函数类型。
|
||||||
|
|
||||||
**参数:**
|
**参数:**
|
||||||
- `layout`: 时间格式,如 "2006-01-02 15:04:05"
|
- `fn`: tools包的格式化函数(如 `tools.FormatDate`、`tools.FormatDateTime` 等)
|
||||||
|
|
||||||
**返回:** 格式化函数
|
**返回:** Excel Format字段需要的格式化函数
|
||||||
|
|
||||||
|
**说明:**
|
||||||
|
- 允许直接使用tools包的任何格式化函数
|
||||||
|
- 推荐使用此适配器,避免重复实现格式化逻辑
|
||||||
|
- 与factory中的FormatDateTime等方法保持一致
|
||||||
|
|
||||||
**示例:**
|
**示例:**
|
||||||
```go
|
```go
|
||||||
Format: excel.FormatDateTime("2006-01-02 15:04:05")
|
import (
|
||||||
```
|
"git.toowon.com/jimmy/go-common/excel"
|
||||||
|
"git.toowon.com/jimmy/go-common/tools"
|
||||||
|
)
|
||||||
|
|
||||||
#### excel.FormatDate(value interface{}) string
|
// 使用tools.FormatDate
|
||||||
|
Format: excel.AdaptTimeFormatter(tools.FormatDate)
|
||||||
|
|
||||||
格式化日期(格式:2006-01-02)。
|
// 使用tools.FormatDateTime
|
||||||
|
Format: excel.AdaptTimeFormatter(tools.FormatDateTime)
|
||||||
|
|
||||||
**示例:**
|
// 使用tools.FormatTime
|
||||||
```go
|
Format: excel.AdaptTimeFormatter(tools.FormatTime)
|
||||||
Format: excel.FormatDate
|
|
||||||
```
|
|
||||||
|
|
||||||
#### excel.FormatDateTimeDefault(value interface{}) string
|
// 使用自定义格式化函数
|
||||||
|
Format: excel.AdaptTimeFormatter(func(t time.Time) string {
|
||||||
格式化日期时间(格式:2006-01-02 15:04:05)。
|
return tools.Format(t, "2006-01-02 15:04:05", "Asia/Shanghai")
|
||||||
|
})
|
||||||
**示例:**
|
|
||||||
```go
|
|
||||||
Format: excel.FormatDateTimeDefault
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### ExportData接口
|
### ExportData接口
|
||||||
@@ -356,7 +381,7 @@ func exportUsersHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
Header: "创建时间",
|
Header: "创建时间",
|
||||||
Field: "CreatedAt",
|
Field: "CreatedAt",
|
||||||
Width: 20,
|
Width: 20,
|
||||||
Format: excel.FormatDateTimeDefault,
|
Format: excel.AdaptTimeFormatter(tools.FormatDateTime),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Header: "状态",
|
Header: "状态",
|
||||||
@@ -411,6 +436,10 @@ func main() {
|
|||||||
5. **嵌套字段**:支持嵌套字段访问(如 "User.Name"),但需要确保字段路径正确
|
5. **嵌套字段**:支持嵌套字段访问(如 "User.Name"),但需要确保字段路径正确
|
||||||
6. **格式化函数**:格式化函数返回的字符串会直接写入Excel单元格
|
6. **格式化函数**:格式化函数返回的字符串会直接写入Excel单元格
|
||||||
7. **列宽设置**:Width为0时会自动调整列宽,但可能影响性能(大数据量时建议设置固定宽度)
|
7. **列宽设置**:Width为0时会自动调整列宽,但可能影响性能(大数据量时建议设置固定宽度)
|
||||||
|
8. **工作表处理**:
|
||||||
|
- 使用默认"Sheet1"时,会直接使用默认工作表,不会产生空sheet
|
||||||
|
- 使用自定义工作表名称时,会自动删除默认的"Sheet1",确保文件只有一个工作表
|
||||||
|
- 如果指定的工作表已存在,会直接使用,不会重复创建
|
||||||
|
|
||||||
## 最佳实践
|
## 最佳实践
|
||||||
|
|
||||||
@@ -419,6 +448,10 @@ func main() {
|
|||||||
3. **使用格式化函数**:对于日期时间、状态等字段,使用格式化函数提高可读性
|
3. **使用格式化函数**:对于日期时间、状态等字段,使用格式化函数提高可读性
|
||||||
4. **错误处理**:始终检查导出方法的返回值
|
4. **错误处理**:始终检查导出方法的返回值
|
||||||
5. **HTTP响应**:导出到HTTP响应时,记得设置正确的Content-Type和Content-Disposition头
|
5. **HTTP响应**:导出到HTTP响应时,记得设置正确的Content-Type和Content-Disposition头
|
||||||
|
6. **工作表命名**:
|
||||||
|
- 推荐使用有意义的工作表名称(如"用户列表"、"订单数据"等),提高可读性
|
||||||
|
- 如果不指定工作表名称,会使用默认的"Sheet1"
|
||||||
|
- 工具会自动处理工作表的创建和删除,确保不会产生空sheet
|
||||||
|
|
||||||
## 示例
|
## 示例
|
||||||
|
|
||||||
|
|||||||
@@ -179,7 +179,7 @@ columns := []factory.ExportColumn{
|
|||||||
Header: "创建时间",
|
Header: "创建时间",
|
||||||
Field: "CreatedAt",
|
Field: "CreatedAt",
|
||||||
Width: 20,
|
Width: 20,
|
||||||
Format: excel.FormatDateTimeDefault,
|
Format: excel.AdaptTimeFormatter(tools.FormatDateTime),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
|
|
||||||
"git.toowon.com/jimmy/go-common/excel"
|
"git.toowon.com/jimmy/go-common/excel"
|
||||||
"git.toowon.com/jimmy/go-common/factory"
|
"git.toowon.com/jimmy/go-common/factory"
|
||||||
|
"git.toowon.com/jimmy/go-common/tools"
|
||||||
)
|
)
|
||||||
|
|
||||||
// User 用户结构体示例
|
// User 用户结构体示例
|
||||||
@@ -111,7 +112,7 @@ func example3(fac *factory.Factory) {
|
|||||||
Header: "创建时间",
|
Header: "创建时间",
|
||||||
Field: "CreatedAt",
|
Field: "CreatedAt",
|
||||||
Width: 20,
|
Width: 20,
|
||||||
Format: excel.FormatDateTimeDefault, // 使用便捷的格式化函数
|
Format: excel.AdaptTimeFormatter(tools.FormatDateTime), // 使用适配器直接调用tools函数
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Header: "状态",
|
Header: "状态",
|
||||||
@@ -174,7 +175,7 @@ func (d *UserExportData) GetExportColumns() []excel.ExportColumn {
|
|||||||
Header: "创建时间",
|
Header: "创建时间",
|
||||||
Field: "CreatedAt",
|
Field: "CreatedAt",
|
||||||
Width: 20,
|
Width: 20,
|
||||||
Format: excel.FormatDateTimeDefault,
|
Format: excel.AdaptTimeFormatter(tools.FormatDateTime),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Header: "状态",
|
Header: "状态",
|
||||||
@@ -230,4 +231,3 @@ func (w *mockResponseWriter) Write(data []byte) (int, error) {
|
|||||||
func (w *mockResponseWriter) WriteHeader(statusCode int) {
|
func (w *mockResponseWriter) WriteHeader(statusCode int) {
|
||||||
// 模拟实现
|
// 模拟实现
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"git.toowon.com/jimmy/go-common/tools"
|
||||||
"github.com/xuri/excelize/v2"
|
"github.com/xuri/excelize/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -94,11 +95,17 @@ func (e *Excel) ExportToWriter(w io.Writer, sheetName string, columns []ExportCo
|
|||||||
sheetName = "Sheet1"
|
sheetName = "Sheet1"
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除默认工作表(如果存在)
|
// 检查工作表是否已存在
|
||||||
index, err := e.file.GetSheetIndex("Sheet1")
|
sheetIndex, err := e.file.GetSheetIndex(sheetName)
|
||||||
if err == nil && index > 0 {
|
if err != nil || sheetIndex == 0 {
|
||||||
|
// 工作表不存在,需要创建
|
||||||
|
// 如果sheetName不是"Sheet1",且默认"Sheet1"存在,则删除它
|
||||||
|
if sheetName != "Sheet1" {
|
||||||
|
defaultIndex, _ := e.file.GetSheetIndex("Sheet1")
|
||||||
|
if defaultIndex > 0 {
|
||||||
e.file.DeleteSheet("Sheet1")
|
e.file.DeleteSheet("Sheet1")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 创建新工作表
|
// 创建新工作表
|
||||||
_, err = e.file.NewSheet(sheetName)
|
_, err = e.file.NewSheet(sheetName)
|
||||||
@@ -106,9 +113,15 @@ func (e *Excel) ExportToWriter(w io.Writer, sheetName string, columns []ExportCo
|
|||||||
return fmt.Errorf("failed to create sheet: %w", err)
|
return fmt.Errorf("failed to create sheet: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 重新获取工作表索引
|
||||||
|
sheetIndex, err = e.file.GetSheetIndex(sheetName)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get sheet index: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 设置活动工作表
|
// 设置活动工作表
|
||||||
sheetIndex, err := e.file.GetSheetIndex(sheetName)
|
if sheetIndex > 0 {
|
||||||
if err == nil && sheetIndex > 0 {
|
|
||||||
e.file.SetActiveSheet(sheetIndex)
|
e.file.SetActiveSheet(sheetIndex)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -210,11 +223,17 @@ func (e *Excel) ExportToFile(filePath string, sheetName string, columns []Export
|
|||||||
sheetName = "Sheet1"
|
sheetName = "Sheet1"
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除默认工作表(如果存在)
|
// 检查工作表是否已存在
|
||||||
index, err := e.file.GetSheetIndex("Sheet1")
|
sheetIndex, err := e.file.GetSheetIndex(sheetName)
|
||||||
if err == nil && index > 0 {
|
if err != nil || sheetIndex == 0 {
|
||||||
|
// 工作表不存在,需要创建
|
||||||
|
// 如果sheetName不是"Sheet1",且默认"Sheet1"存在,则删除它
|
||||||
|
if sheetName != "Sheet1" {
|
||||||
|
defaultIndex, _ := e.file.GetSheetIndex("Sheet1")
|
||||||
|
if defaultIndex > 0 {
|
||||||
e.file.DeleteSheet("Sheet1")
|
e.file.DeleteSheet("Sheet1")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 创建新工作表
|
// 创建新工作表
|
||||||
_, err = e.file.NewSheet(sheetName)
|
_, err = e.file.NewSheet(sheetName)
|
||||||
@@ -222,9 +241,15 @@ func (e *Excel) ExportToFile(filePath string, sheetName string, columns []Export
|
|||||||
return fmt.Errorf("failed to create sheet: %w", err)
|
return fmt.Errorf("failed to create sheet: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 重新获取工作表索引
|
||||||
|
sheetIndex, err = e.file.GetSheetIndex(sheetName)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get sheet index: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 设置活动工作表
|
// 设置活动工作表
|
||||||
sheetIndex, err := e.file.GetSheetIndex(sheetName)
|
if sheetIndex > 0 {
|
||||||
if err == nil && sheetIndex > 0 {
|
|
||||||
e.file.SetActiveSheet(sheetIndex)
|
e.file.SetActiveSheet(sheetIndex)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -451,31 +476,49 @@ func (e *Excel) getColumnMaxWidth(sheetName string, colIndex int, maxRow int) fl
|
|||||||
return maxWidth
|
return maxWidth
|
||||||
}
|
}
|
||||||
|
|
||||||
// FormatDateTime 格式化日期时间(便捷函数)
|
// AdaptTimeFormatter 适配器函数:将tools包的格式化函数转换为Excel Format字段需要的函数类型
|
||||||
// 用于ExportColumn的Format字段
|
// 允许直接使用tools包的任何格式化函数
|
||||||
func FormatDateTime(layout string) func(interface{}) string {
|
//
|
||||||
|
// 示例:
|
||||||
|
//
|
||||||
|
// // 直接使用tools.FormatDate
|
||||||
|
// Format: excel.AdaptTimeFormatter(tools.FormatDate)
|
||||||
|
//
|
||||||
|
// // 使用自定义格式化函数
|
||||||
|
// Format: excel.AdaptTimeFormatter(func(t time.Time) string {
|
||||||
|
// return tools.Format(t, "2006-01-02 15:04:05", "Asia/Shanghai")
|
||||||
|
// })
|
||||||
|
func AdaptTimeFormatter(fn func(time.Time, ...string) string) func(interface{}) string {
|
||||||
return func(value interface{}) string {
|
return func(value interface{}) string {
|
||||||
if t, ok := value.(time.Time); ok {
|
if t, ok := value.(time.Time); ok {
|
||||||
return t.Format(layout)
|
return fn(t)
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FormatDate 格式化日期(便捷函数)
|
// formatDateTime 格式化日期时间(内部便捷函数)
|
||||||
|
// 用于ExportColumn的Format字段
|
||||||
|
// layout: 时间格式,如 "2006-01-02 15:04:05"
|
||||||
|
// timezone: 可选时区,如果为空则使用时间对象本身的时区
|
||||||
|
// 直接调用 tools.Format() 方法
|
||||||
|
func formatDateTime(layout string, timezone ...string) func(interface{}) string {
|
||||||
|
return AdaptTimeFormatter(func(t time.Time, _ ...string) string {
|
||||||
|
return tools.Format(t, layout, timezone...)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// formatDate 格式化日期(内部便捷函数)
|
||||||
// 用于ExportColumn的Format字段,格式:2006-01-02
|
// 用于ExportColumn的Format字段,格式:2006-01-02
|
||||||
func FormatDate(value interface{}) string {
|
// 直接调用 tools.FormatDate() 方法
|
||||||
if t, ok := value.(time.Time); ok {
|
var formatDate = AdaptTimeFormatter(tools.FormatDate)
|
||||||
return t.Format("2006-01-02")
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// FormatDateTimeDefault 格式化日期时间(便捷函数)
|
// formatDateTimeDefault 格式化日期时间(内部便捷函数)
|
||||||
// 用于ExportColumn的Format字段,格式:2006-01-02 15:04:05
|
// 用于ExportColumn的Format字段,格式:2006-01-02 15:04:05
|
||||||
func FormatDateTimeDefault(value interface{}) string {
|
// 直接调用 tools.FormatDateTime() 方法
|
||||||
if t, ok := value.(time.Time); ok {
|
var formatDateTimeDefault = AdaptTimeFormatter(tools.FormatDateTime)
|
||||||
return t.Format("2006-01-02 15:04:05")
|
|
||||||
}
|
// formatTime 格式化时间(内部便捷函数)
|
||||||
return ""
|
// 用于ExportColumn的Format字段,格式:15:04:05
|
||||||
}
|
// 直接调用 tools.FormatTime() 方法
|
||||||
|
var formatTime = AdaptTimeFormatter(tools.FormatTime)
|
||||||
|
|||||||
Reference in New Issue
Block a user