package utils import ( "bytes" "fmt" "github.com/xuri/excelize/v2" ) // ExcelExporter handles Excel file generation type ExcelExporter struct { file *excelize.File sheetName string rowIndex int } // NewExcelExporter creates a new Excel exporter func NewExcelExporter() *ExcelExporter { f := excelize.NewFile() return &ExcelExporter{ file: f, sheetName: "Sheet1", rowIndex: 1, } } // SetSheetName sets the active sheet name func (e *ExcelExporter) SetSheetName(name string) { e.file.SetSheetName("Sheet1", name) e.sheetName = name } // AddRow adds a row of data func (e *ExcelExporter) AddRow(data []string) error { for colIndex, value := range data { cell := fmt.Sprintf("%s%d", getColumnName(colIndex), e.rowIndex) if err := e.file.SetCellValue(e.sheetName, cell, value); err != nil { return err } } e.rowIndex++ return nil } // AddHeader adds a header row with bold style func (e *ExcelExporter) AddHeader(headers []string) error { style, err := e.file.NewStyle(&excelize.Style{ Font: &excelize.Font{ Bold: true, }, Fill: excelize.Fill{ Type: "pattern", Color: []string{"#D3D3D3"}, Pattern: 1, }, }) if err != nil { return err } for colIndex, header := range headers { cell := fmt.Sprintf("%s%d", getColumnName(colIndex), e.rowIndex) if err := e.file.SetCellValue(e.sheetName, cell, header); err != nil { return err } if err := e.file.SetCellStyle(e.sheetName, cell, cell, style); err != nil { return err } } e.rowIndex++ return nil } // AutoSizeColumns auto-sizes columns func (e *ExcelExporter) AutoSizeColumns(columnCount int) { for i := 0; i < columnCount; i++ { col := getColumnName(i) e.file.SetColWidth(e.sheetName, col, col, 15) } } // Output returns the Excel file as bytes func (e *ExcelExporter) Output() (*bytes.Buffer, error) { buf := new(bytes.Buffer) if err := e.file.Write(buf); err != nil { return nil, err } return buf, nil } // getColumnName converts column index to Excel column name (A, B, C, ..., AA, AB, ...) func getColumnName(index int) string { name := "" for index >= 0 { name = string(rune('A'+(index%26))) + name index = index/26 - 1 } return name }