diff --git a/excel/excel.go b/excel/excel.go index e60cd646..b342fe8c 100644 --- a/excel/excel.go +++ b/excel/excel.go @@ -17,6 +17,7 @@ type Excel struct { id string path string create int64 + abs string *excelize.File } @@ -29,7 +30,7 @@ func Open(path string, writable bool) (string, error) { excel := &Excel{path: path} // GET DATA ROOT root := config.Conf.DataRoot - path, err := filepath.Abs(filepath.Join(root, path)) + absPath, err := filepath.Abs(filepath.Join(root, path)) if err != nil { return "", err } @@ -37,30 +38,31 @@ func Open(path string, writable bool) (string, error) { if writable { // if the file not exists, create it - if _, err := os.Stat(path); os.IsNotExist(err) { + if _, err := os.Stat(absPath); os.IsNotExist(err) { create := excelize.NewFile() - err := create.SaveAs(path) + err := create.SaveAs(absPath) if err != nil { return "", err } create.Close() } - excelFile, err := excelize.OpenFile(path) + excelFile, err := excelize.OpenFile(absPath) if err != nil { return "", err } id := uuid.NewString() excel.File = excelFile excel.id = id + excel.abs = absPath excel.create = time.Now().Unix() openFiles.Store(id, excel) return id, nil } - file, err := os.Open(path) + file, err := os.Open(absPath) if err != nil { - return "", fmt.Errorf("open file %s failed: %w", path, err) + return "", fmt.Errorf("open file %s failed: %w", absPath, err) } excelFile, err := excelize.OpenReader(file) @@ -71,6 +73,7 @@ func Open(path string, writable bool) (string, error) { id := uuid.NewString() excel.File = excelFile excel.id = id + excel.abs = absPath excel.create = time.Now().Unix() openFiles.Store(id, excel) return id, nil diff --git a/excel/process.go b/excel/process.go index bb616925..7360d88c 100644 --- a/excel/process.go +++ b/excel/process.go @@ -13,15 +13,32 @@ func init() { "save": processSave, "sheets": processSheets, - "read.cell": processReadCell, - "write.cell": processWriteCell, + "read.cell": processReadCell, + "read.row": processReadRow, + "read.column": processReadColumn, + + "write.cell": processWriteCell, + "write.row": processWriteRow, + "write.column": processWriteColumn, + "write.all": processWriteAll, "set.style": processSetStyle, "set.formula": processSetFormula, "set.link": processSetLink, + "set.richtext": processSetRichText, + "set.comment": processSetComment, + "set.rowheight": processSetRowHeight, + "set.columnwidth": processSetColumnWidth, "set.mergecell": processMergeCell, "set.unmergecell": processUnmergeCell, + "each.openrow": processOpenRow, + "each.closerow": processCloseRow, + "each.nextrow": processNextRow, + "each.opencolumn": processOpenColumn, + "each.closecolumn": processCloseColumn, + "each.nextcolumn": processNextColumn, + "convert.columnnametonumber": processColumnNameToNumber, "convert.columnnumbertoname": processColumnNumberToName, "convert.cellnametocoordinates": processCellNameToCoordinates, @@ -64,7 +81,9 @@ func processSave(process *process.Process) interface{} { if err != nil { exception.New("excel.save %s error: %s", 500, handle, err.Error()).Throw() } - err = xls.Save() + + // 使用 SaveAs 方法保存文件到原始路径 + err = xls.SaveAs(xls.abs) if err != nil { exception.New("excel.save %s error: %s", 500, handle, err.Error()).Throw() } @@ -100,6 +119,40 @@ func processReadCell(process *process.Process) interface{} { return value } +// processReadRow process the excel.read.row +func processReadRow(process *process.Process) interface{} { + process.ValidateArgNums(2) + handle := process.ArgsString(0) + sheet := process.ArgsString(1) + + xls, err := Get(handle) + if err != nil { + exception.New("excel.read.row %s error: %s", 500, handle, err.Error()).Throw() + } + rows, err := xls.GetRows(sheet) + if err != nil { + exception.New("excel.read.row %s:%s error: %s", 500, handle, sheet, err.Error()).Throw() + } + return rows +} + +// processReadColumn process the excel.read.column +func processReadColumn(process *process.Process) interface{} { + process.ValidateArgNums(2) + handle := process.ArgsString(0) + sheet := process.ArgsString(1) + + xls, err := Get(handle) + if err != nil { + exception.New("excel.read.column %s error: %s", 500, handle, err.Error()).Throw() + } + cols, err := xls.GetCols(sheet) + if err != nil { + exception.New("excel.read.column %s:%s error: %s", 500, handle, sheet, err.Error()).Throw() + } + return cols +} + // processWriteCell process the excel.write.cell func processWriteCell(process *process.Process) interface{} { process.ValidateArgNums(4) @@ -119,6 +172,126 @@ func processWriteCell(process *process.Process) interface{} { return nil } +// processWriteRow process the excel.write.row +func processWriteRow(process *process.Process) interface{} { + process.ValidateArgNums(4) + handle := process.ArgsString(0) + sheet := process.ArgsString(1) + cell := process.ArgsString(2) + values := process.Args[3] + + xls, err := Get(handle) + if err != nil { + exception.New("excel.write.row %s error: %s", 500, handle, err.Error()).Throw() + } + + // 处理切片值 + var rowValues []interface{} + if arr, ok := values.([]interface{}); ok { + rowValues = arr + } else { + rowValues = []interface{}{values} + } + + // 使用 xls.SetSheetRow 方法,它应该能处理 slice 指针 + err = xls.SetSheetRow(sheet, cell, &rowValues) + if err != nil { + exception.New("excel.write.row %s:%s:%s error: %s", 500, handle, sheet, cell, err.Error()).Throw() + } + return nil +} + +// processWriteColumn process the excel.write.column +func processWriteColumn(process *process.Process) interface{} { + process.ValidateArgNums(4) + handle := process.ArgsString(0) + sheet := process.ArgsString(1) + cell := process.ArgsString(2) + values := process.Args[3] + + xls, err := Get(handle) + if err != nil { + exception.New("excel.write.column %s error: %s", 500, handle, err.Error()).Throw() + } + + // 处理切片值 + var colValues []interface{} + if arr, ok := values.([]interface{}); ok { + colValues = arr + } else { + colValues = []interface{}{values} + } + + // 使用 xls.SetSheetCol 方法,它应该能处理 slice 指针 + err = xls.SetSheetCol(sheet, cell, &colValues) + if err != nil { + exception.New("excel.write.column %s:%s:%s error: %s", 500, handle, sheet, cell, err.Error()).Throw() + } + return nil +} + +// processWriteAll process the excel.write.all +func processWriteAll(process *process.Process) interface{} { + process.ValidateArgNums(4) + handle := process.ArgsString(0) + sheet := process.ArgsString(1) + cell := process.ArgsString(2) + values := process.Args[3] + + xls, err := Get(handle) + if err != nil { + exception.New("excel.write.all %s error: %s", 500, handle, err.Error()).Throw() + } + + // 处理二维切片值 + if arr, ok := values.([]interface{}); ok { + for _, row := range arr { + if rowArr, ok := row.([]interface{}); ok { + // 对于每行,使用 SetSheetRow + err = xls.SetSheetRow(sheet, cell, &rowArr) + if err != nil { + exception.New("excel.write.all %s:%s:%s error: %s", 500, handle, sheet, cell, err.Error()).Throw() + } + + // 移动到下一行 + colIndex, rowIndex, err := excelize.CellNameToCoordinates(cell) + if err != nil { + exception.New("excel.write.all %s:%s:%s error: %s", 500, handle, sheet, cell, err.Error()).Throw() + } + cell, err = excelize.CoordinatesToCellName(colIndex, rowIndex+1) + if err != nil { + exception.New("excel.write.all %s:%s:%s error: %s", 500, handle, sheet, cell, err.Error()).Throw() + } + } else { + // 单元素行 + singleRow := []interface{}{row} + err = xls.SetSheetRow(sheet, cell, &singleRow) + if err != nil { + exception.New("excel.write.all %s:%s:%s error: %s", 500, handle, sheet, cell, err.Error()).Throw() + } + + // 移动到下一行 + colIndex, rowIndex, err := excelize.CellNameToCoordinates(cell) + if err != nil { + exception.New("excel.write.all %s:%s:%s error: %s", 500, handle, sheet, cell, err.Error()).Throw() + } + cell, err = excelize.CoordinatesToCellName(colIndex, rowIndex+1) + if err != nil { + exception.New("excel.write.all %s:%s:%s error: %s", 500, handle, sheet, cell, err.Error()).Throw() + } + } + } + } else { + // 单元素 + singleElement := []interface{}{values} + err = xls.SetSheetRow(sheet, cell, &singleElement) + if err != nil { + exception.New("excel.write.all %s:%s:%s error: %s", 500, handle, sheet, cell, err.Error()).Throw() + } + } + return nil +} + // processSetStyle process the excel.set.style