惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

雷峰网
雷峰网
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
大猫的无限游戏
大猫的无限游戏
Google DeepMind News
Google DeepMind News
V
V2EX
T
The Blog of Author Tim Ferriss
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Hugging Face - Blog
Hugging Face - Blog
Stack Overflow Blog
Stack Overflow Blog
I
InfoQ
博客园_首页
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Last Week in AI
Last Week in AI
Recent Announcements
Recent Announcements
Vercel News
Vercel News
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
T
Tailwind CSS Blog
美团技术团队
Martin Fowler
Martin Fowler
宝玉的分享
宝玉的分享
Blog — PlanetScale
Blog — PlanetScale
GbyAI
GbyAI
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
J
Java Code Geeks

博客园 - 青山下

安装大龙虾 OpenClaw出现错误提示的相关解决办法:npm.ps1 进行数字签名。无法在当前系 统上运行该脚本。有关运行脚本和设置执行策略的详细信息 mysql57下载地址 Working with Ace,ace web编辑器,一款可以语法高亮的牛逼编辑器 如果词可能有缩写、近义词或拼写差异,可以使用 字符串相似度算法 18年了,注册18年了,还在做一线开发 hutool工具JSONUtil序列化对象和反序列化到Map的时候,null的值因为JSONNull无法转换而报错 jdk8:alpine没有bash,所以会报:no such file or directory,如何解决? RSA密钥格式转换:java->.net、.net->java dify相关文档 好玩的找不到页面设计:html5 svg太空人404动画模板 C#版本的sha256withRSA 私钥签名,公钥验签 方法,java<->.net通用 nginx负载均衡 C++内存扫描 快速将下划线字段改为驼峰字段 Mybatis-Plus 如何通过sql命令对数据库中的数据重新排序 网页打印的时候,去掉页眉和页脚的方法 调用文心一言画画 2023-12-28前几天很冷,今天不是很冷
合并多个Excel文件,并且保持原表格的数字格式
青山下 · 2025-04-17 · via 博客园 - 青山下

如果你需要合并多个Excel文件,并且保持原表格的数字格式(如日期、货币、百分比等),可以使用 EPPlus(一个强大的.NET Excel操作库)。以下是完整的解决方案,使用C#和EPPlus实现。


方案概述

目标

  • 合并多个Excel文件(.xlsx)到一个文件。
  • 保留原格式(数字、日期、字体、颜色、边框等)。
  • 支持合并多个Sheet(可选)。

技术栈

  • C# + .NET Core(或.NET Framework)
  • EPPlus(开源库,支持Excel 2007+格式)
  • LINQ(用于文件遍历)

步骤 1:安装EPPlus

通过NuGet安装EPPlus:

Install-Package EPPlus -Version 5.8.8

(如果你用的是.NET Core 3.1+,可以直接用 Install-Package EPPlus,最新版已支持跨平台。)


步骤 2:完整代码

using OfficeOpenXml;
using System;
using System.IO;
using System.Linq;

class ExcelMerger
{
    static void Main(string[] args)
    {
        // 设置EPPlus许可证(社区版免费)
        ExcelPackage.LicenseContext = LicenseContext.NonCommercial;

        // 输入文件夹(存放待合并的Excel文件)
        string inputFolder = @"C:\ExcelFiles\";
        // 输出文件(合并后的Excel)
        string outputFile = @"C:\MergedExcel.xlsx";

        // 获取所有Excel文件
        var excelFiles = Directory.GetFiles(inputFolder, "*.xlsx");

        // 创建一个新的Excel包(最终合并的文件)
        using (var mergedPackage = new ExcelPackage(new FileInfo(outputFile)))
        {
            // 遍历每个Excel文件
            foreach (var file in excelFiles)
            {
                using (var sourcePackage = new ExcelPackage(new FileInfo(file)))
                {
                    // 遍历当前Excel的所有Sheet
                    foreach (var sourceSheet in sourcePackage.Workbook.Worksheets)
                    {
                        // 在合并后的Excel中创建同名Sheet(如果已存在则追加数据)
                        string sheetName = sourceSheet.Name;
                        var targetSheet = mergedPackage.Workbook.Worksheets.FirstOrDefault(s => s.Name == sheetName);

                        if (targetSheet == null)
                        {
                            // 如果Sheet不存在,直接复制整个Sheet(保留格式)
                            targetSheet = mergedPackage.Workbook.Worksheets.Add(sheetName, sourceSheet);
                        }
                        else
                        {
                            // 如果Sheet已存在,仅复制数据(保留格式)
                            int targetRow = targetSheet.Dimension?.End.Row ?? 1; // 获取目标Sheet的最后一行
                            int sourceRowCount = sourceSheet.Dimension.Rows;
                            int sourceColCount = sourceSheet.Dimension.Columns;

                            // 复制数据(逐行逐列,保留格式)
                            for (int row = 1; row <= sourceRowCount; row++)
                            {
                                for (int col = 1; col <= sourceColCount; col++)
                                {
                                    // 复制单元格(值 + 格式)
                                    var sourceCell = sourceSheet.Cells[row, col];
                                    var targetCell = targetSheet.Cells[targetRow + row, col];

                                    // 复制值
                                    targetCell.Value = sourceCell.Value;

                                    // 复制样式(数字格式、字体、颜色等)
                                    targetCell.StyleID = sourceCell.StyleID; // 直接复用StyleID更高效
                                }
                            }
                        }
                    }
                }
            }

            // 保存合并后的Excel
            mergedPackage.Save();
            Console.WriteLine($"合并完成!文件已保存到: {outputFile}");
        }
    }
}

关键点解析

1. 保留数字格式

EPPlus通过 StyleID 直接复用原单元格的样式,确保:

  • 日期(yyyy-mm-dd
  • 货币($#,##0.00
  • 百分比(0.00%
  • 自定义格式等 完全保留

2. 合并逻辑

  • 如果Sheet不存在 → 直接复制整个Sheet(Add方法保留格式)。
  • 如果Sheet已存在 → 逐行逐列复制数据,并复制样式。

3. 性能优化

  • 使用 StyleID 而不是逐个设置样式属性,减少内存占用。
  • 按需调整 sourcePackagemergedPackage 的作用域,避免内存泄漏。

测试示例

输入文件1 (File1.xlsx)

A B C
2023-01-01 $100.00 50%
Product Price Qty

输入文件2 (File2.xlsx)

A B C
2023-02-01 $200.00 75%
Service Fee Count

合并后 (MergedExcel.xlsx)

A B C
2023-01-01 $100.00 50%
Product Price Qty
2023-02-01 $200.00 75%
Service Fee Count

格式完全保留!


扩展功能

1. 仅合并特定Sheet

if (sourceSheet.Name == "Sales")  // 只合并名为"Sales"的Sheet
{
    // 合并逻辑
}

2. 处理大数据量

  • 使用 ExcelRange.LoadFromArrays 批量写入数据。
  • 禁用公式计算加速处理:
    mergedPackage.Workbook.CalcMode = ExcelCalcMode.Manual;
    

3. 命令行工具

封装为.exe,支持参数输入:

ExcelMerger.exe -input "C:\Input" -output "C:\Output\Merged.xlsx"

结论

  • 适用场景:需要保留Excel格式的合并任务(如财务报告、数据汇总)。
  • 优势:EPPlus比NPOI更易用,比OpenXML更高效。
  • 你的技术栈:C# + EPPlus完全匹配,无需额外学习。

如果需要进一步优化(如异步处理、更复杂格式),可以继续扩展!