20 个相同内容的 excel 文件想要合并成一个 excel 文件,在网上按照 excel 数据处理方法试了好几次,效果都不太好

想想这是个很简单的活,使用 golang 可以轻松解决

代码打包后的二进制文件如下:

使用方法如下:

  1. 将相同内容的excel放置到同一个目录中,并复制该目录的路径
  2. 双击程序,粘贴路径,回车执行合并
  3. 结果位于excel目录下,名字是merged_output.xlsx

最后,代码部分如下:

package main

import (
	"fmt"
	"log"
	"os"
	"path/filepath"

	"github.com/xuri/excelize/v2"
)

func main() {
	// 让用户输入文件夹路径
	var folderPath string
	fmt.Print("请输入 Excel 文件夹路径: ")
	fmt.Scanln(&folderPath)

	// 获取所有 Excel 文件
	files, err := os.ReadDir(folderPath)
	if err != nil {
		log.Fatalf("无法读取目录: %v", err)
	}

	// 创建一个新的 Excel 文件
	outputFile := excelize.NewFile()
	var header []string // 用于存储第一份文件的列标题
	rowIndex := 1       // 用于写入输出文件的行索引

	// 遍历所有文件
	for _, file := range files {
		// 检查文件扩展名是否为 .xlsx
		if filepath.Ext(file.Name()) == ".xlsx" {
			filePath := filepath.Join(folderPath, file.Name())
			fmt.Printf("处理文件: %s\n", filePath)

			// 打开 Excel 文件
			f, err := excelize.OpenFile(filePath)
			if err != nil {
				log.Printf("无法打开文件 %s: %v", filePath, err)
				continue
			}

			// 获取所有工作表名称
			sheets := f.GetSheetList()
			for _, sheet := range sheets {
				// 读取工作表的所有行
				rows, err := f.GetRows(sheet)
				if err != nil {
					log.Printf("无法读取工作表 %s: %v", sheet, err)
					continue
				}

				// 如果是第一个文件,存储列标题
				if header == nil {
					header = rows[0]
					// 在输出文件中写入列标题
					if err := outputFile.SetSheetRow("Sheet1", fmt.Sprintf("A%d", rowIndex), &header); err != nil {
						log.Printf("写入列标题失败: %v", err)
					}
					rowIndex++ // 更新行索引
				} else {
					// 检查当前文件的列标题是否与第一个文件一致
					if len(rows[0]) != len(header) {
						logErrorAndWait(fmt.Sprintf("文件 %s 的列数与第一个文件不一致,期望 %d 列,实际 %d 列", filePath, len(header), len(rows[0])))
						return
					}
					// 检查列名是否一致
					for i := range header {
						if header[i] != rows[0][i] {
							logErrorAndWait(fmt.Sprintf("文件 %s 的列名与第一个文件不一致,期望 %s,实际 %s", filePath, header[i], rows[0][i]))
							return
						}
					}
				}

				// 将数据写入新的 Excel 文件(跳过列标题)
				for rowIndexInFile, row := range rows {
					if rowIndexInFile == 0 { // 跳过列标题
						continue
					}
					// 写入数据行
					if err := outputFile.SetSheetRow("Sheet1", fmt.Sprintf("A%d", rowIndex), &row); err != nil {
						log.Printf("写入行失败: %v", err)
					}
					rowIndex++ // 更新行索引
				}
			}
			// 关闭打开的文件
			f.Close()
		}
	}

	// 保存合并后的 Excel 文件
	outputPath := filepath.Join(folderPath, "merged_output.xlsx")
	if err := outputFile.SaveAs(outputPath); err != nil {
		log.Fatalf("无法保存合并后的文件: %v", err)
	}

	fmt.Println("合并完成,输出文件为:", outputPath)

	// 等待用户输入以保持窗口打开
	fmt.Print("按回车键退出...")
	fmt.Scanln() // 等待用户输入
}

// logErrorAndWait 用于打印错误信息并等待用户按下回车键
func logErrorAndWait(message string) {
	fmt.Println("错误:", message)
	fmt.Print("按回车键退出...")
	fmt.Scanln() // 等待用户输入
}