package main ///* //#cgo LDFLAGS: -ldl // //#include //#include //#include //*/ //import "C" //import ( // "encoding/csv" // "encoding/json" // "fmt" // "github.com/xuri/excelize/v2" // "os" // "path/filepath" // "sort" // "strings" // "sync" // "unsafe" //) // //// ExcelManager 线程安全的Excel文件管理器 //type ExcelManager struct { // mu sync.RWMutex // fileMap map[string]*excelize.File // 存储打开的文件 //} // //// MergeConfig 合并配置 //type MergeConfig struct { // SourceDir string // 源目录 // OutputFile string // 输出文件 // SheetName string // 目标sheet名称 // MergeByColumn bool // 是否按列合并(默认按行) // IncludeHeaders bool // 是否包含表头(仅第一个文件) // SkipEmptyRows bool // 是否跳过空行 // FilePattern string // 文件匹配模式,如 "*.xlsx" // SpecificFiles []string // 指定要合并的文件列表 // SourceSheet string // 源sheet名称(为空则使用第一个sheet) // AddSourceColumn bool // 是否添加源文件列 // AddIndexColumn bool // 是否添加序号列 //} // //// NewExcelManager 创建新的Excel管理器 //func NewExcelManager() *ExcelManager { // return &ExcelManager{ // fileMap: make(map[string]*excelize.File), // } //} // //// ============ 基本Excel操作功能 ============ // //// ReadData 读取Excel数据 //func (em *ExcelManager) ReadData(filename, sheet string) ([][]string, error) { // em.mu.RLock() // defer em.mu.RUnlock() // fmt.Printf("[DEBUG] ReadData开始: file=%s, sheet=%s\n", filename, sheet) // file, err := excelize.OpenFile(filename) // if err != nil { // return nil, err // } // defer file.Close() // rows, err := file.GetRows(sheet) // if err != nil { // return nil, fmt.Errorf("读取sheet %s 失败: %v", sheet, err) // } // fmt.Printf("[DEBUG] 读取的数据:", rows) // return rows, nil //} // //// WriteData 写入数据到指定位置 //func (em *ExcelManager) WriteData(filename, sheet string, data map[string]interface{}) error { // em.mu.Lock() // defer em.mu.Unlock() // // file, err := excelize.OpenFile(filename) // if err != nil { // // 文件不存在,创建新文件 // file = excelize.NewFile() // file.NewSheet(sheet) // } else { // // 确保sheet存在 // index, _ := file.GetSheetIndex(sheet) // if index == -1 { // file.NewSheet(sheet) // } // } // // // 写入数据 // for cell, value := range data { // file.SetCellValue(sheet, cell, value) // } // // // 保存文件 // return file.SaveAs(filename) //} // //// AppendData 追加数据到末尾 //func (em *ExcelManager) AppendData(filename, sheet string, rowData []interface{}) error { // em.mu.Lock() // defer em.mu.Unlock() // // file, err := excelize.OpenFile(filename) // if err != nil { // return err // } // defer func() { // file.SaveAs(filename) // file.Close() // }() // // // 确保sheet存在 // index, _ := file.GetSheetIndex(sheet) // if index == -1 { // file.NewSheet(sheet) // } // // // 获取当前最大行号 // rows, err := file.GetRows(sheet) // if err != nil { // return err // } // // nextRow := len(rows) + 1 // if len(rows) == 0 { // nextRow = 1 // } // // // 写入新行 // for col, value := range rowData { // cell, _ := excelize.CoordinatesToCellName(col+1, nextRow) // file.SetCellValue(sheet, cell, value) // } // // return nil //} // //// SearchByKeyword 搜索包含关键字的单元格 //func (em *ExcelManager) SearchByKeyword(filename, sheet, keyword string) ([]string, error) { // em.mu.RLock() // defer em.mu.RUnlock() // // file, err := excelize.OpenFile(filename) // if err != nil { // return nil, err // } // defer file.Close() // // var results []string // rows, err := file.GetRows(sheet) // if err != nil { // return nil, err // } // // for rowIndex, row := range rows { // for colIndex, cell := range row { // if strings.Contains(cell, keyword) { // cellName, _ := excelize.CoordinatesToCellName(colIndex+1, rowIndex+1) // results = append(results, // fmt.Sprintf("位置: %s, 值: %s", cellName, cell)) // } // } // } // // return results, nil //} // //// SearchRowData 搜索整行包含关键字的行 //func (em *ExcelManager) SearchRowData(filename, sheet, keyword string) ([][]string, error) { // em.mu.RLock() // defer em.mu.RUnlock() // // file, err := excelize.OpenFile(filename) // if err != nil { // return nil, err // } // defer file.Close() // // var results [][]string // rows, err := file.GetRows(sheet) // if err != nil { // return nil, err // } // // for _, row := range rows { // for _, cell := range row { // if strings.Contains(cell, keyword) { // results = append(results, row) // break // } // } // } // // return results, nil //} // //// CreateAndWrite 创建新文件并写入数据 //func (em *ExcelManager) CreateAndWrite(filename, sheet string, data [][]string) error { // em.mu.Lock() // defer em.mu.Unlock() // // // 创建新文件 // file := excelize.NewFile() // defer file.Close() // // // 如果指定sheet不是"Sheet1",则重命名默认sheet // if sheet != "Sheet1" { // file.SetSheetName("Sheet1", sheet) // } // // // 写入数据 // for rowIndex, row := range data { // for colIndex, value := range row { // cell, _ := excelize.CoordinatesToCellName(colIndex+1, rowIndex+1) // file.SetCellValue(sheet, cell, value) // } // } // // // 保存文件 // return file.SaveAs(filename) //} // //// CloseAll 关闭所有文件 //func (em *ExcelManager) CloseAll() error { // em.mu.Lock() // defer em.mu.Unlock() // // var lastErr error // for filename, file := range em.fileMap { // if err := file.Close(); err != nil { // lastErr = err // } // delete(em.fileMap, filename) // } // return lastErr //} // //// ============ Excel合并功能 ============ // //// MergeExcelFiles 合并多个Excel文件(批次合并) //func (em *ExcelManager) MergeExcelFiles(config MergeConfig) error { // em.mu.Lock() // defer em.mu.Unlock() // // // 获取要合并的文件列表 // filesToMerge, err := em.getFilesToMerge(config) // if err != nil { // return err // } // // fmt.Printf("开始合并 %d 个文件:\n", len(filesToMerge)) // for i, file := range filesToMerge { // fmt.Printf(" %d. %s\n", i+1, filepath.Base(file)) // } // // // 创建新的输出文件 // outputFile := excelize.NewFile() // defer outputFile.Close() // // // 删除默认的Sheet1 // outputFile.DeleteSheet("Sheet1") // // // 创建目标sheet并设置为活动sheet // sheetIndex, err := outputFile.NewSheet(config.SheetName) // if err != nil { // return fmt.Errorf("创建sheet失败: %v", err) // } // outputFile.SetActiveSheet(sheetIndex) // // currentRow := 1 // totalRowsMerged := 0 // fileCount := len(filesToMerge) // // // 写入表头(如果需要) // if config.IncludeHeaders && fileCount > 0 { // headers, err := em.readFileHeaders(filesToMerge[0], config.SourceSheet) // if err != nil { // fmt.Printf("警告: 无法读取第一个文件的表头: %v\n", err) // } else { // // 添加额外的列(如果需要) // colOffset := 0 // if config.AddIndexColumn { // headers = append([]string{"序号"}, headers...) // colOffset++ // } // if config.AddSourceColumn { // headers = append([]string{"源文件"}, headers...) // colOffset++ // } // // // 写入表头 // for colIndex, header := range headers { // cellName, _ := excelize.CoordinatesToCellName(colIndex+1, currentRow) // outputFile.SetCellValue(config.SheetName, cellName, header) // } // currentRow++ // fmt.Printf("写入表头: %v\n", headers) // } // } // // // 合并所有文件 // for fileIndex, sourceFile := range filesToMerge { // rowsMerged, err := em.mergeSingleFile(outputFile, config, sourceFile, fileIndex, fileCount, ¤tRow) // if err != nil { // fmt.Printf("警告: 合并文件 %s 时出错: %v,跳过\n", sourceFile, err) // continue // } // totalRowsMerged += rowsMerged // } // // // 保存输出文件 // if err := outputFile.SaveAs(config.OutputFile); err != nil { // return fmt.Errorf("保存合并文件失败: %v", err) // } // // fmt.Printf("合并完成!结果保存在: %s\n", config.OutputFile) // fmt.Printf("统计信息:\n") // fmt.Printf(" - 合并文件数: %d\n", fileCount) // fmt.Printf(" - 合并数据行数: %d\n", totalRowsMerged) // fmt.Printf(" - 输出文件总行数: %d\n", currentRow-1) // // // 验证文件是否正确保存 // if err := em.verifyMergeResult(config.OutputFile, config.SheetName); err != nil { // return fmt.Errorf("合并结果验证失败: %v", err) // } // // return nil //} // //// getFilesToMerge 获取要合并的文件列表 //func (em *ExcelManager) getFilesToMerge(config MergeConfig) ([]string, error) { // var filesToMerge []string // // if len(config.SpecificFiles) > 0 { // filesToMerge = config.SpecificFiles // } else if config.SourceDir != "" { // pattern := "*.xlsx" // if config.FilePattern != "" { // pattern = config.FilePattern // } // // files, err := filepath.Glob(filepath.Join(config.SourceDir, pattern)) // if err != nil { // return nil, fmt.Errorf("查找文件失败: %v", err) // } // filesToMerge = files // } else { // return nil, fmt.Errorf("必须指定SourceDir或SpecificFiles") // } // // if len(filesToMerge) == 0 { // return nil, fmt.Errorf("没有找到要合并的Excel文件") // } // // // 按文件名排序 // sort.Strings(filesToMerge) // return filesToMerge, nil //} // //// readFileHeaders 读取文件的表头 //func (em *ExcelManager) readFileHeaders(filename, sheetName string) ([]string, error) { // srcFile, err := excelize.OpenFile(filename) // if err != nil { // return nil, err // } // defer srcFile.Close() // // sourceSheet := em.getSourceSheet(srcFile, sheetName) // if sourceSheet == "" { // return nil, fmt.Errorf("未找到可用的sheet") // } // // rows, err := srcFile.GetRows(sourceSheet) // if err != nil { // return nil, err // } // // if len(rows) == 0 { // return nil, fmt.Errorf("文件没有数据") // } // // return rows[0], nil //} // //// mergeSingleFile 合并单个文件 //func (em *ExcelManager) mergeSingleFile(outputFile *excelize.File, config MergeConfig, // sourceFile string, fileIndex, fileCount int, currentRow *int) (int, error) { // // fmt.Printf("\n[%d/%d] 正在处理文件: %s\n", fileIndex+1, fileCount, filepath.Base(sourceFile)) // // // 打开源文件 // srcFile, err := excelize.OpenFile(sourceFile) // if err != nil { // return 0, fmt.Errorf("打开文件失败: %v", err) // } // defer srcFile.Close() // // // 确定要读取的sheet // sourceSheet := em.getSourceSheet(srcFile, config.SourceSheet) // if sourceSheet == "" { // return 0, fmt.Errorf("未找到可用的sheet") // } // // // 读取源文件数据 // rows, err := srcFile.GetRows(sourceSheet) // if err != nil { // return 0, fmt.Errorf("读取数据失败: %v", err) // } // // if len(rows) == 0 { // fmt.Printf(" 警告: 文件没有数据,跳过\n") // return 0, nil // } // // fmt.Printf(" 读取到 %d 行数据\n", len(rows)) // // rowsMerged := 0 // // // 处理数据行 // for rowIndex, row := range rows { // // 跳过空行 // if config.SkipEmptyRows && em.isRowEmpty(row) { // continue // } // fmt.Println(rowIndex) // // 处理表头(如果是第一个文件且包含表头,第一行已经处理过了) // if config.IncludeHeaders && rowIndex == 0 { // if fileIndex == 0 { // // 第一个文件的表头已处理,跳过 // continue // } else { // // 后续文件的表头跳过 // continue // } // } // // // 写入数据行 // colOffset := 0 // // // 添加序号列 // if config.AddIndexColumn { // cellName, _ := excelize.CoordinatesToCellName(1, *currentRow) // outputFile.SetCellValue(config.SheetName, cellName, rowsMerged+1) // colOffset++ // } // // // 添加源文件列 // if config.AddSourceColumn { // cellName, _ := excelize.CoordinatesToCellName(1+colOffset, *currentRow) // outputFile.SetCellValue(config.SheetName, cellName, filepath.Base(sourceFile)) // colOffset++ // } // // // 写入原始数据 // for colIndex, cell := range row { // cellName, _ := excelize.CoordinatesToCellName(colIndex+1+colOffset, *currentRow) // outputFile.SetCellValue(config.SheetName, cellName, cell) // } // // rowsMerged++ // *currentRow++ // } // // //// 添加文件分隔信息(如果有数据被合并) // //if rowsMerged > 0 { // // // 添加分隔行 // // separatorCell, _ := excelize.CoordinatesToCellName(1, *currentRow) // // outputFile.SetCellValue(config.SheetName, separatorCell, // // fmt.Sprintf("=== 文件 %d/%d: %s (合并了 %d 行) ===", // // fileIndex+1, fileCount, filepath.Base(sourceFile), rowsMerged)) // // *currentRow++ // //} // // fmt.Printf(" 文件处理完成,合并了 %d 行数据\n", rowsMerged) // return rowsMerged, nil //} // //// getSourceSheet 获取源sheet名称 //func (em *ExcelManager) getSourceSheet(file *excelize.File, preferredSheet string) string { // if preferredSheet != "" { // if index, _ := file.GetSheetIndex(preferredSheet); index != -1 { // return preferredSheet // } // } // // // 返回第一个sheet // sheets := file.GetSheetList() // if len(sheets) > 0 { // return sheets[0] // } // return "" //} // //// verifyMergeResult 验证合并结果 //func (em *ExcelManager) verifyMergeResult(filename, sheet string) error { // file, err := excelize.OpenFile(filename) // if err != nil { // return fmt.Errorf("打开验证文件失败: %v", err) // } // defer file.Close() // // rows, err := file.GetRows(sheet) // if err != nil { // return fmt.Errorf("读取sheet失败: %v", err) // } // // fmt.Printf("\n验证结果:\n") // fmt.Printf(" 文件: %s\n", filename) // fmt.Printf(" Sheet: %s\n", sheet) // fmt.Printf(" 总行数: %d\n", len(rows)) // // if len(rows) == 0 { // return fmt.Errorf("警告: 合并后的文件没有数据!") // } // // // 显示前5行数据 // limit := 5 // if len(rows) < limit { // limit = len(rows) // } // // fmt.Printf(" 前%d行数据预览:\n", limit) // for i := 0; i < limit; i++ { // // 只显示前5列(避免输出过长) // previewCols := 5 // if len(rows[i]) < previewCols { // previewCols = len(rows[i]) // } // fmt.Printf(" 第%d行: %v", i+1, rows[i][:previewCols]) // if len(rows[i]) > previewCols { // fmt.Printf(" ... (+%d列)", len(rows[i])-previewCols) // } // fmt.Println() // } // // return nil //} // //// MergeExcelFilesParallel 并行合并Excel文件(高性能) //func (em *ExcelManager) MergeExcelFilesParallel(config MergeConfig, workers int) error { // em.mu.Lock() // defer em.mu.Unlock() // // // 获取要合并的文件列表 // filesToMerge, err := em.getFilesToMerge(config) // if err != nil { // return err // } // // fmt.Printf("开始并行合并 %d 个文件,使用 %d 个worker:\n", len(filesToMerge), workers) // // // 创建通道和等待组 // fileChan := make(chan fileTask, len(filesToMerge)) // resultChan := make(chan fileResult, len(filesToMerge)) // var wg sync.WaitGroup // // // 启动worker goroutines // for i := 0; i < workers; i++ { // wg.Add(1) // go func(workerID int) { // defer wg.Done() // for task := range fileChan { // fmt.Printf("Worker %d 正在处理: %s (文件 %d/%d)\n", // workerID, filepath.Base(task.filename), task.index+1, task.total) // data := em.readExcelFileParallel(task.filename, config.SourceSheet) // resultChan <- fileResult{ // filename: task.filename, // index: task.index, // data: data, // } // } // }(i) // } // // // 发送文件任务到通道 // for i, file := range filesToMerge { // fileChan <- fileTask{ // filename: file, // index: i, // total: len(filesToMerge), // } // } // close(fileChan) // // // 等待所有worker完成 // go func() { // wg.Wait() // close(resultChan) // }() // // // 收集结果 // var results []fileResult // for result := range resultChan { // results = append(results, result) // } // // // 按文件索引排序 // sort.Slice(results, func(i, j int) bool { // return results[i].index < results[j].index // }) // // // 创建新的输出文件 // outputFile := excelize.NewFile() // defer outputFile.Close() // // // 删除默认的Sheet1 // outputFile.DeleteSheet("Sheet1") // // // 创建目标sheet // sheetIndex, err := outputFile.NewSheet(config.SheetName) // if err != nil { // return fmt.Errorf("创建sheet失败: %v", err) // } // outputFile.SetActiveSheet(sheetIndex) // // // 合并数据 // currentRow := 1 // totalRowsMerged := 0 // // // 写入表头(如果需要) // headersWritten := false // if config.IncludeHeaders && len(results) > 0 { // for _, result := range results { // if result.data.err == nil && len(result.data.rows) > 0 { // headers := result.data.rows[0] // // 添加额外的列 // colOffset := 0 // if config.AddIndexColumn { // headers = append([]string{"序号"}, headers...) // colOffset++ // } // if config.AddSourceColumn { // headers = append([]string{"源文件"}, headers...) // colOffset++ // } // // // 写入表头 // for colIndex, header := range headers { // cellName, _ := excelize.CoordinatesToCellName(colIndex+1, currentRow) // outputFile.SetCellValue(config.SheetName, cellName, header) // } // currentRow++ // headersWritten = true // fmt.Printf("写入表头: %v\n", headers) // break // 只取第一个有效文件的表头 // } // } // } // // // 写入数据 // for _, result := range results { // if result.data.err != nil { // fmt.Printf("警告: 文件 %s 处理失败: %v,跳过\n", result.filename, result.data.err) // continue // } // // if len(result.data.rows) == 0 { // fmt.Printf("警告: 文件 %s 没有数据,跳过\n", result.filename) // continue // } // // rowsMerged := 0 // for rowIndex, row := range result.data.rows { // // 跳过表头(如果已经处理过) // if config.IncludeHeaders && rowIndex == 0 && headersWritten { // continue // } // // // 跳过空行 // if config.SkipEmptyRows && em.isRowEmpty(row) { // continue // } // // // 写入数据行 // colOffset := 0 // // // 添加序号列 // if config.AddIndexColumn { // cellName, _ := excelize.CoordinatesToCellName(1, currentRow) // outputFile.SetCellValue(config.SheetName, cellName, totalRowsMerged+1) // colOffset++ // } // // // 添加源文件列 // if config.AddSourceColumn { // cellName, _ := excelize.CoordinatesToCellName(1+colOffset, currentRow) // outputFile.SetCellValue(config.SheetName, cellName, filepath.Base(result.filename)) // colOffset++ // } // // // 写入原始数据 // for colIndex, cell := range row { // cellName, _ := excelize.CoordinatesToCellName(colIndex+1+colOffset, currentRow) // outputFile.SetCellValue(config.SheetName, cellName, cell) // } // // currentRow++ // rowsMerged++ // totalRowsMerged++ // } // // //// 添加分隔行 // //if rowsMerged > 0 { // // separatorCell, _ := excelize.CoordinatesToCellName(1, currentRow) // // outputFile.SetCellValue(config.SheetName, separatorCell, // // fmt.Sprintf("=== 文件 %d/%d: %s ===", // // result.index+1, len(results), filepath.Base(result.filename))) // // currentRow++ // //} // } // // // 保存输出文件 // if err := outputFile.SaveAs(config.OutputFile); err != nil { // return fmt.Errorf("保存合并文件失败: %v", err) // } // // fmt.Printf("并行合并完成!结果保存在: %s\n", config.OutputFile) // fmt.Printf("统计信息:\n") // fmt.Printf(" - 合并文件数: %d\n", len(results)) // fmt.Printf(" - 合并数据行数: %d\n", totalRowsMerged) // // return em.verifyMergeResult(config.OutputFile, config.SheetName) //} // //// MergeByColumn 按列合并Excel文件 //func (em *ExcelManager) MergeByColumn(config MergeConfig) error { // em.mu.Lock() // defer em.mu.Unlock() // // // 获取要合并的文件列表 // filesToMerge, err := em.getFilesToMerge(config) // if err != nil { // return err // } // // fmt.Printf("开始按列合并 %d 个文件:\n", len(filesToMerge)) // // // 创建新的输出文件 // outputFile := excelize.NewFile() // defer outputFile.Close() // // // 删除默认的Sheet1 // outputFile.DeleteSheet("Sheet1") // // // 创建目标sheet // sheetIndex, err := outputFile.NewSheet(config.SheetName) // if err != nil { // return fmt.Errorf("创建sheet失败: %v", err) // } // outputFile.SetActiveSheet(sheetIndex) // // currentCol := 1 // // // 合并所有文件 // for fileIndex, sourceFile := range filesToMerge { // fmt.Printf("[%d/%d] 正在处理文件: %s\n", fileIndex+1, len(filesToMerge), filepath.Base(sourceFile)) // // // 打开源文件 // srcFile, err := excelize.OpenFile(sourceFile) // if err != nil { // return fmt.Errorf("打开文件 %s 失败: %v", sourceFile, err) // } // defer srcFile.Close() // // // 确定要读取的sheet // sourceSheet := em.getSourceSheet(srcFile, config.SourceSheet) // if sourceSheet == "" { // return fmt.Errorf("未找到可用的sheet") // } // // // 读取源文件数据 // rows, err := srcFile.GetRows(sourceSheet) // if err != nil { // return fmt.Errorf("读取文件 %s 失败: %v,跳过\n", sourceFile, err) // } // // if len(rows) == 0 { // fmt.Printf("警告: 文件 %s 的sheet '%s' 没有数据,跳过\n", sourceFile, sourceSheet) // continue // } // // // 按列写入数据 // for rowIndex, row := range rows { // // 写入当前列的所有行 // for colIndex, cell := range row { // targetRow := rowIndex + 1 // cellName, _ := excelize.CoordinatesToCellName(currentCol+colIndex, targetRow) // outputFile.SetCellValue(config.SheetName, cellName, cell) // } // } // // // 添加文件名称到第一行(作为列标题) // titleCell, _ := excelize.CoordinatesToCellName(currentCol, 1) // outputFile.SetCellValue(config.SheetName, titleCell, filepath.Base(sourceFile)) // // // 移动到下一组列 // if len(rows) > 0 && len(rows[0]) > 0 { // currentCol += len(rows[0]) // } else { // currentCol += 1 // } // } // // // 保存输出文件 // if err := outputFile.SaveAs(config.OutputFile); err != nil { // return fmt.Errorf("保存合并文件失败: %v", err) // } // // fmt.Printf("按列合并完成!结果保存在: %s\n", config.OutputFile) // return nil //} // //// MergeSheetsInSameFile 合并同一文件中的多个sheet //func (em *ExcelManager) MergeSheetsInSameFile(filename, outputFile string, targetSheetName string) error { // em.mu.RLock() // defer em.mu.RUnlock() // // file, err := excelize.OpenFile(filename) // if err != nil { // return err // } // defer file.Close() // // // 获取所有sheet // sheets := file.GetSheetList() // if len(sheets) == 0 { // return fmt.Errorf("文件 %s 中没有sheet", filename) // } // // // 创建新的输出文件 // output := excelize.NewFile() // defer output.Close() // // // 删除默认的Sheet1 // output.DeleteSheet("Sheet1") // // // 创建目标sheet // sheetIndex, err := output.NewSheet(targetSheetName) // if err != nil { // return fmt.Errorf("创建sheet失败: %v", err) // } // output.SetActiveSheet(sheetIndex) // // currentRow := 1 // // for _, sheet := range sheets { // // 读取sheet数据 // rows, err := file.GetRows(sheet) // if err != nil { // fmt.Printf("警告: 读取sheet %s 失败: %v,跳过\n", sheet, err) // continue // } // // if len(rows) == 0 { // continue // } // // // 添加sheet名称作为标题 // titleCell, _ := excelize.CoordinatesToCellName(1, currentRow) // output.SetCellValue(targetSheetName, titleCell, fmt.Sprintf("=== Sheet: %s ===", sheet)) // currentRow++ // // // 写入sheet数据 // for _, row := range rows { // for colIndex, cell := range row { // cellName, _ := excelize.CoordinatesToCellName(colIndex+1, currentRow) // output.SetCellValue(targetSheetName, cellName, cell) // } // currentRow++ // } // // // 添加空行分隔 // currentRow++ // } // // // 保存输出文件 // return output.SaveAs(outputFile) //} // //// ============ 辅助结构和方法 ============ // //// 文件任务结构 //type fileTask struct { // filename string // index int // total int //} // //// 文件结果结构 //type fileResult struct { // filename string // index int // data fileData //} // //// 文件数据结构 //type fileData struct { // rows [][]string // err error //} // //// 并行读取Excel文件 //func (em *ExcelManager) readExcelFileParallel(filename, sheetName string) fileData { // srcFile, err := excelize.OpenFile(filename) // if err != nil { // return fileData{err: err} // } // defer srcFile.Close() // // sourceSheet := em.getSourceSheet(srcFile, sheetName) // if sourceSheet == "" { // return fileData{err: fmt.Errorf("未找到可用的sheet")} // } // // rows, err := srcFile.GetRows(sourceSheet) // return fileData{ // rows: rows, // err: err, // } //} // //// 检查行是否为空 //func (em *ExcelManager) isRowEmpty(row []string) bool { // for _, cell := range row { // if strings.TrimSpace(cell) != "" { // return false // } // } // return true //} // //// 清理测试文件 //func cleanupFiles(file string) { // if _, err := os.Stat(file); err == nil { // os.Remove(file) // fmt.Printf("删除: %s\n", file) // } //} // //// 辅助函数:将数据转换为JSON字符串 //func convertToJSON(data interface{}) string { // // 这里使用简单的转换,实际可以使用 encoding/json 包 // switch v := data.(type) { // case [][]string: // var result []string // for _, row := range v { // result = append(result, strings.Join(row, ",")) // } // return strings.Join(result, "\n") // case []string: // return strings.Join(v, "\n") // default: // return fmt.Sprintf("%v", data) // } //} // //// 将C字符串数组转换为Go字符串切片 //func cStringArrayToStringSlice(cArray **C.char, length int) []string { // if cArray == nil || length == 0 { // return nil // } // // var goStrs []string // for i := 0; i < length; i++ { // ptr := (**C.char)(unsafe.Pointer(uintptr(unsafe.Pointer(cArray)) + uintptr(i)*unsafe.Sizeof(uintptr(0)))) // if *ptr != nil { // goStrs = append(goStrs, C.GoString(*ptr)) // } // } // // return goStrs //} // //// 辅助函数:设置错误信息 //func setError(err string) { // // 这里可以添加日志记录等操作 // fmt.Printf("Excel操作错误: %s\n", err) //} // //func ParseExcelDataToJSON(excelData string) ([]map[string]string, error) { // if excelData == "" { // return nil, fmt.Errorf("Excel数据为空") // } // // // 使用csv解析器解析数据 // reader := csv.NewReader(strings.NewReader(excelData)) // records, err := reader.ReadAll() // if err != nil { // return nil, fmt.Errorf("解析CSV数据失败: %v", err) // } // // if len(records) < 2 { // return nil, fmt.Errorf("数据行数不足") // } // // // 提取表头(第一行) // headers := records[0] // // // 将数据转换为JSON格式 // var jsonData []map[string]string // // // 从第二行开始(跳过表头) // for i := 1; i < len(records); i++ { // row := records[i] // rowData := make(map[string]string) // // // 确保每行的列数与表头一致 // for j := 0; j < len(headers) && j < len(row); j++ { // rowData[headers[j]] = row[j] // } // jsonData = append(jsonData, rowData) // } // // return jsonData, nil //} // //// ============ CGO 导出函数 ============ // //var ( // managerStore sync.Map // nextHandle int64 = 1 // handleMutex sync.Mutex // 添加互斥锁保证线程安全 //) // //// 创建新的Excel管理器并返回指针 //// ////export NewExcelManagerInstance //func NewExcelManagerInstance() C.longlong { // manager := NewExcelManager() // // handleMutex.Lock() // handle := nextHandle // nextHandle++ // handleMutex.Unlock() // // // 将Go对象存储在map中 // managerStore.Store(handle, manager) // // return C.longlong(handle) //} // //// 释放Excel管理器 //// ////export FreeExcelManager //func FreeExcelManager(handle C.longlong) { // h := int64(handle) // // // 从map中删除并清理 // if mgr, ok := managerStore.Load(h); ok { // if manager, ok := mgr.(*ExcelManager); ok { // manager.CloseAll() // } // managerStore.Delete(h) // } //} // //// 读取Excel数据 //// ////export ReadExcelData //func ReadExcelData(handle C.longlong, filename *C.char, sheet *C.char, result **C.char) C.int { // h := int64(handle) // mgr, ok := managerStore.Load(h) // if !ok { // return C.int(-1) // } // manager, ok := mgr.(*ExcelManager) // if !ok { // return C.int(-1) // } // goFilename := C.GoString(filename) // goSheet := C.GoString(sheet) // data, err := manager.ReadData(goFilename, goSheet) // if err != nil { // return C.int(-1) // } // // 将数据转换为JSON字符串 // jsonStr := convertToJSON(data) // // // 将结果转换为JSON格式 // jsonData, err := ParseExcelDataToJSON(jsonStr) // var datas string // if err != nil { // fmt.Printf("转换JSON失败: %v\n", err) // } else { // // 将JSON数据格式化输出 // jsonBytes, err := json.MarshalIndent(jsonData, "", " ") // if err != nil { // fmt.Printf("格式化JSON失败: %v\n", err) // } else { // datas = string(jsonBytes) // } // } // // *result = C.CString(datas) // return C.int(0) //} // //// 批量写入数据到Excel文件 //// ////export WriteBatchData //func WriteBatchData(handle C.longlong, filename *C.char, sheet *C.char, cells *C.char, values *C.char, count C.int) C.int { // h := int64(handle) // mgr, ok := managerStore.Load(h) // if !ok { // return C.int(-1) // } // manager, ok := mgr.(*ExcelManager) // if !ok { // return C.int(-1) // } // goFilename := C.GoString(filename) // goSheet := C.GoString(sheet) // goCells := C.GoString(cells) // goValues := C.GoString(values) // // var cell []string // var value []string // err := json.Unmarshal([]byte(goCells), &cell) // if err != nil { // setError(fmt.Sprintf("解析数据失败: %v,数据: %s", err, goCells)) // return C.int(-1) // } // err = json.Unmarshal([]byte(goValues), &value) // if err != nil { // setError(fmt.Sprintf("解析数据失败: %v,数据: %s", err, goValues)) // return C.int(-1) // } // // 构建数据映射 // data := make(map[string]interface{}) // for i, c := range cell { // data[c] = value[i] // } // err = manager.WriteData(goFilename, goSheet, data) // if err != nil { // fmt.Printf("批量写入数据失败: %v\n", err) // return C.int(-1) // } // return C.int(0) //} // //// 追加数据到Excel文件末尾 //// ////export AppendDataToExcel //func AppendDataToExcel(handle C.longlong, filename *C.char, sheet *C.char, values *C.char, count C.int) C.int { // h := int64(handle) // // mgr, ok := managerStore.Load(h) // if !ok { // return C.int(-1) // } // manager, ok := mgr.(*ExcelManager) // if !ok { // return C.int(-1) // } // goFilename := C.GoString(filename) // goSheet := C.GoString(sheet) // goValues := C.GoString(values) // var value []string // err := json.Unmarshal([]byte(goValues), &value) // if err != nil { // setError(fmt.Sprintf("解析数据失败: %v,数据: %s", err, goValues)) // return C.int(-1) // } // // 转换为interface{}切片 // var rowData []interface{} // for _, val := range value { // rowData = append(rowData, val) // } // err = manager.AppendData(goFilename, goSheet, rowData) // if err != nil { // fmt.Printf("追加数据失败: %v\n", err) // return C.int(-1) // } // return C.int(0) //} // //// 搜索包含关键字的单元格 //// ////export SearchByKeyword //func SearchByKeyword(handle C.longlong, filename *C.char, sheet *C.char, keyword *C.char, result **C.char) C.int { // h := int64(handle) // mgr, ok := managerStore.Load(h) // if !ok { // return C.int(-1) // } // manager, ok := mgr.(*ExcelManager) // if !ok { // return C.int(-1) // } // goFilename := C.GoString(filename) // goSheet := C.GoString(sheet) // goKeyword := C.GoString(keyword) // results, err := manager.SearchByKeyword(goFilename, goSheet, goKeyword) // if err != nil { // return C.int(-1) // } // // 将结果转换为JSON字符串 // jsonStr := convertToJSON(results) // *result = C.CString(jsonStr) // return C.int(0) //} // //// 搜索整行包含关键字的行 //// ////export SearchRowsByKeyword //func SearchRowsByKeyword(handle C.longlong, // filename *C.char, // sheet *C.char, // keyword *C.char, // result **C.char) C.int { // h := int64(handle) // mgr, ok := managerStore.Load(h) // if !ok { // return C.int(-1) // } // manager, ok := mgr.(*ExcelManager) // if !ok { // return C.int(-1) // } // goFilename := C.GoString(filename) // goSheet := C.GoString(sheet) // goKeyword := C.GoString(keyword) // results, err := manager.SearchRowData(goFilename, goSheet, goKeyword) // if err != nil { // return C.int(-1) // } // // 将结果转换为JSON字符串 // jsonStr := convertToJSON(results) // *result = C.CString(jsonStr) // return C.int(0) //} // //// 创建新文件并写入数据 //// ////export CreateAndWriteExcel //func CreateAndWriteExcel(handle C.longlong, filename *C.char, sheet *C.char, rowsData *C.char) C.int { // h := int64(handle) // // // 获取管理器 // mgr, ok := managerStore.Load(h) // if !ok { // setError("Invalid handle") // return C.int(-1) // } // // manager, ok := mgr.(*ExcelManager) // if !ok { // setError("Invalid manager type") // return C.int(-1) // } // goFilename := C.GoString(filename) // goSheet := C.GoString(sheet) // goRowsData := C.GoString(rowsData) // var data [][]string // err2 := json.Unmarshal([]byte(goRowsData), &data) // if err2 != nil { // // 更详细的错误信息 // setError(fmt.Sprintf("解析数据失败: %v, 数据: %s", err2, goRowsData)) // return C.int(-1) // } // // 调用管理器方法 // err := manager.CreateAndWrite(goFilename, goSheet, data) // if err != nil { // setError(fmt.Sprintf("创建并写入文件失败: %v", err)) // return C.int(-1) // } // fmt.Printf("文件创建成功: %s\n", goFilename) // return C.int(0) //} // //// 增强版合并Excel文件(支持指定文件列表) //// ////export MergeExcelFilesEx //func MergeExcelFilesEx(handle C.longlong, // sourceDir *C.char, // specificFiles *C.char, // outputFile *C.char, // sheetName *C.char, // mergeByColumn C.int, // includeHeaders C.int, // skipEmptyRows C.int, // filePattern *C.char, // sourceSheet *C.char, // addSourceColumn C.int, // addIndexColumn C.int) C.int { // h := int64(handle) // mgr, ok := managerStore.Load(h) // if !ok { // return C.int(-1) // } // manager, ok := mgr.(*ExcelManager) // if !ok { // return C.int(-1) // } // // goSpecificFiles := C.GoString(specificFiles) // var data []string // err2 := json.Unmarshal([]byte(goSpecificFiles), &data) // if err2 != nil { // // 更详细的错误信息 // setError(fmt.Sprintf("解析数据失败: %v, 数据: %s", err2, goSpecificFiles)) // return C.int(-1) // } // // 构建配置 // config := MergeConfig{ // SourceDir: C.GoString(sourceDir), // SpecificFiles: data, // OutputFile: C.GoString(outputFile), // SheetName: C.GoString(sheetName), // MergeByColumn: mergeByColumn != 0, // IncludeHeaders: includeHeaders != 0, // SkipEmptyRows: skipEmptyRows != 0, // FilePattern: C.GoString(filePattern), // AddSourceColumn: addSourceColumn != 0, // AddIndexColumn: addIndexColumn != 0, // SourceSheet: C.GoString(sourceSheet), // } // // 根据合并模式调用不同的方法 // var err error // if config.MergeByColumn { // err = manager.MergeByColumn(config) // } else { // err = manager.MergeExcelFiles(config) // } // if err != nil { // fmt.Printf("合并Excel文件失败: %v\n", err) // return C.int(-1) // } // return C.int(0) //} // //// 并行合并Excel文件(增强版) //// ////export MergeExcelFilesParallelEx //func MergeExcelFilesParallelEx(handle C.longlong, // sourceDir *C.char, // specificFiles **C.char, // fileCount C.int, // outputFile *C.char, // sheetName *C.char, // includeHeaders C.int, // skipEmptyRows C.int, // filePattern *C.char, // sourceSheet *C.char, // addSourceColumn C.int, // addIndexColumn C.int, // workers C.int) C.int { // h := int64(handle) // mgr, ok := managerStore.Load(h) // if !ok { // return C.int(-1) // } // manager, ok := mgr.(*ExcelManager) // if !ok { // return C.int(-1) // } // // 构建配置 // config := MergeConfig{ // SourceDir: C.GoString(sourceDir), // OutputFile: C.GoString(outputFile), // SheetName: C.GoString(sheetName), // IncludeHeaders: includeHeaders != 0, // SkipEmptyRows: skipEmptyRows != 0, // FilePattern: C.GoString(filePattern), // AddSourceColumn: addSourceColumn != 0, // AddIndexColumn: addIndexColumn != 0, // SourceSheet: C.GoString(sourceSheet), // } // // // 如果有指定的文件列表,则添加到配置中 // if fileCount > 0 && specificFiles != nil { // config.SpecificFiles = cStringArrayToStringSlice(specificFiles, int(fileCount)) // } // // err := manager.MergeExcelFilesParallel(config, int(workers)) // if err != nil { // fmt.Printf("并行合并Excel文件失败: %v\n", err) // return C.int(-1) // } // // return C.int(0) //} // //// 合并同一文件中的多个sheet //// ////export MergeSheetsInFile //func MergeSheetsInFile(handle C.longlong, // filename *C.char, // outputFile *C.char, // targetSheetName *C.char) C.int { // h := int64(handle) // mgr, ok := managerStore.Load(h) // if !ok { // return C.int(-1) // } // manager, ok := mgr.(*ExcelManager) // if !ok { // return C.int(-1) // } // goFilename := C.GoString(filename) // goOutputFile := C.GoString(outputFile) // goTargetSheet := C.GoString(targetSheetName) // // err := manager.MergeSheetsInSameFile(goFilename, goOutputFile, goTargetSheet) // if err != nil { // fmt.Printf("合并sheet失败: %v\n", err) // return C.int(-1) // } // // return C.int(0) //} // //// 释放C字符串 //// ////export FreeCString //func FreeCString(str *C.char) { // if str != nil { // C.free(unsafe.Pointer(str)) // } //} // ////func main() { //// ////}