169 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
		
		
			
		
	
	
			169 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| 
								 | 
							
								package helper
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								import (
							 | 
						||
| 
								 | 
							
									"encoding/csv"
							 | 
						||
| 
								 | 
							
									"errors"
							 | 
						||
| 
								 | 
							
									"fmt"
							 | 
						||
| 
								 | 
							
									"log"
							 | 
						||
| 
								 | 
							
									"reflect"
							 | 
						||
| 
								 | 
							
									"strings"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									"github.com/xuri/excelize/v2"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									"github.com/gin-gonic/gin"
							 | 
						||
| 
								 | 
							
								)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								导出csv文件
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  - @fileName 文件名 不带拓展名
							 | 
						||
| 
								 | 
							
								  - @header 文件头
							 | 
						||
| 
								 | 
							
								  - @records 内容
							 | 
						||
| 
								 | 
							
								*/
							 | 
						||
| 
								 | 
							
								func ExportCSV(c *gin.Context, fileName string, header []string, records [][]string) error {
							 | 
						||
| 
								 | 
							
									disposition := fmt.Sprintf("attachment; filename=%s.csv", fileName)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Set headers
							 | 
						||
| 
								 | 
							
									c.Header("Content-Description", "File Transfer")
							 | 
						||
| 
								 | 
							
									c.Header("Content-Disposition", disposition)
							 | 
						||
| 
								 | 
							
									c.Header("Content-Type", "text/csv")
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Create a CSV writer using the response writer
							 | 
						||
| 
								 | 
							
									writer := csv.NewWriter(c.Writer)
							 | 
						||
| 
								 | 
							
									defer writer.Flush()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Write CSV header
							 | 
						||
| 
								 | 
							
									writer.Write(header)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									for _, record := range records {
							 | 
						||
| 
								 | 
							
										writer.Write(record)
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return nil
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								导出excel
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  - @fileName 文件名称
							 | 
						||
| 
								 | 
							
								  - @data 数据源
							 | 
						||
| 
								 | 
							
								  - @ingore 忽略header
							 | 
						||
| 
								 | 
							
								*/
							 | 
						||
| 
								 | 
							
								func ExportExcel[T any](c *gin.Context, fileName string, data []T, ingore []string) error {
							 | 
						||
| 
								 | 
							
									if len(data) == 0 {
							 | 
						||
| 
								 | 
							
										return errors.New("无导出记录")
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									// Create a new Excel file
							 | 
						||
| 
								 | 
							
									f := excelize.NewFile()
							 | 
						||
| 
								 | 
							
									// Use reflection to get the header from struct tags
							 | 
						||
| 
								 | 
							
									t := reflect.TypeOf(data[0])
							 | 
						||
| 
								 | 
							
									headers := []string{}
							 | 
						||
| 
								 | 
							
									for i := 0; i < t.NumField(); i++ {
							 | 
						||
| 
								 | 
							
										field := t.Field(i)
							 | 
						||
| 
								 | 
							
										excelTag := field.Tag.Get("excel")
							 | 
						||
| 
								 | 
							
										if excelTag != "" && !ArrayAny(ingore, excelTag) {
							 | 
						||
| 
								 | 
							
											headers = append(headers, excelTag)
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									// Set headers
							 | 
						||
| 
								 | 
							
									for i, header := range headers {
							 | 
						||
| 
								 | 
							
										col := string('A' + i)
							 | 
						||
| 
								 | 
							
										cell := fmt.Sprintf("%s1", col)
							 | 
						||
| 
								 | 
							
										f.SetCellValue("Sheet1", cell, header)
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Fill rows with data
							 | 
						||
| 
								 | 
							
									for rowIndex, item := range data {
							 | 
						||
| 
								 | 
							
										rowValue := reflect.ValueOf(item)
							 | 
						||
| 
								 | 
							
										rowType := rowValue.Type()
							 | 
						||
| 
								 | 
							
										for colIndex, header := range headers {
							 | 
						||
| 
								 | 
							
											col := string('A' + colIndex)
							 | 
						||
| 
								 | 
							
											cell := fmt.Sprintf("%s%d", col, rowIndex+2)
							 | 
						||
| 
								 | 
							
											var fieldValue reflect.Value
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											for i := 0; i < rowType.NumField(); i++ {
							 | 
						||
| 
								 | 
							
												field := rowType.Field(i)
							 | 
						||
| 
								 | 
							
												if strings.EqualFold(field.Tag.Get("excel"), header) {
							 | 
						||
| 
								 | 
							
													fieldValue = rowValue.Field(i)
							 | 
						||
| 
								 | 
							
													break
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											// Check if the fieldValue is valid before accessing it
							 | 
						||
| 
								 | 
							
											if fieldValue.IsValid() && fieldValue.CanInterface() {
							 | 
						||
| 
								 | 
							
												//f.SetCellValue("Sheet1", cell, fieldValue.Interface())
							 | 
						||
| 
								 | 
							
												value := fieldValue.Interface()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												// Ensure the value is a string, convert it if necessary
							 | 
						||
| 
								 | 
							
												var stringValue string
							 | 
						||
| 
								 | 
							
												if v, ok := value.(string); ok {
							 | 
						||
| 
								 | 
							
													stringValue = v // If it's a string, use it directly
							 | 
						||
| 
								 | 
							
												} else {
							 | 
						||
| 
								 | 
							
													stringValue = fmt.Sprintf("%v", value) // Otherwise, convert to string
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												f.SetCellValue("Sheet1", cell, stringValue)
							 | 
						||
| 
								 | 
							
											} else {
							 | 
						||
| 
								 | 
							
												// Handle the case where fieldValue is invalid or nil
							 | 
						||
| 
								 | 
							
												f.SetCellValue("Sheet1", cell, "")
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									// Set response headers and send the file to the client
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// c.Writer.Header().Set("Content-Disposition", "attachment; filename=test.xlsx")
							 | 
						||
| 
								 | 
							
									// c.Writer.Header().Set("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet; charset=binary")
							 | 
						||
| 
								 | 
							
									// c.Writer.Header().Set("Content-Transfer-Encoding", "binary")
							 | 
						||
| 
								 | 
							
									// c.Writer.Header().Set("Expires", "0")
							 | 
						||
| 
								 | 
							
									// c.Writer.Header().Set("Cache-Control", "must-revalidate")
							 | 
						||
| 
								 | 
							
									// c.Writer.Header().Set("Pragma", "public")
							 | 
						||
| 
								 | 
							
									c.Header("Content-Description", "File Transfer")
							 | 
						||
| 
								 | 
							
									c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=%s.xlsx", fileName))
							 | 
						||
| 
								 | 
							
									c.Header("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
							 | 
						||
| 
								 | 
							
									c.Header("Content-Transfer-Encoding", "binary")
							 | 
						||
| 
								 | 
							
									c.Header("Expires", "0")
							 | 
						||
| 
								 | 
							
									c.Header("Cache-Control", "must-revalidate")
							 | 
						||
| 
								 | 
							
									c.Header("Pragma", "public")
							 | 
						||
| 
								 | 
							
									c.Header("Content-Encoding", "")
							 | 
						||
| 
								 | 
							
									//fmt.Println("c.Writer.Header():", c.Writer.Header())
							 | 
						||
| 
								 | 
							
									if _, err := f.WriteTo(c.Writer); err != nil {
							 | 
						||
| 
								 | 
							
										log.Println("Error writing file:", err)
							 | 
						||
| 
								 | 
							
										return err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									return nil
							 | 
						||
| 
								 | 
							
									//return f.WriteTo(c.Writer)
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								func MapExcelToStruct[T any](rows [][]string, headers []string) ([]T, error) {
							 | 
						||
| 
								 | 
							
									var results []T
							 | 
						||
| 
								 | 
							
									if len(rows) == 0 {
							 | 
						||
| 
								 | 
							
										return results, nil
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									for _, row := range rows {
							 | 
						||
| 
								 | 
							
										var result T
							 | 
						||
| 
								 | 
							
										v := reflect.ValueOf(&result).Elem()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										for i, header := range headers {
							 | 
						||
| 
								 | 
							
											fieldName := ""
							 | 
						||
| 
								 | 
							
											for j := 0; j < v.NumField(); j++ {
							 | 
						||
| 
								 | 
							
												field := v.Type().Field(j)
							 | 
						||
| 
								 | 
							
												tag := field.Tag.Get("excel")
							 | 
						||
| 
								 | 
							
												if strings.EqualFold(tag, header) {
							 | 
						||
| 
								 | 
							
													fieldName = field.Name
							 | 
						||
| 
								 | 
							
													break
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if fieldName != "" && i < len(row) {
							 | 
						||
| 
								 | 
							
												field := v.FieldByName(fieldName)
							 | 
						||
| 
								 | 
							
												if field.IsValid() && field.CanSet() {
							 | 
						||
| 
								 | 
							
													field.Set(reflect.ValueOf(row[i]).Convert(field.Type()))
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										results = append(results, result)
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return results, nil
							 | 
						||
| 
								 | 
							
								}
							 |