
在现代数据驱动的世界中,Excel文件作为一种通用的数据存储和交换格式,在企业运营和日常工作中扮演着举足轻重的作用。无论是报表生成、数据分析还是系统集成,将应用程序中的数据准确、高效地写入Excel文件都是一个普遍且关键的需求。然而,手动操作Excel不仅效率低下,还极易引入人为错误,特别是当数据量庞大或需要频繁更新时。
本文将深入探讨如何利用C#语言,结合一个功能强大且易于使用的库,实现数据的程序化写入Excel文件。我们将从环境搭建开始,逐步讲解如何创建新的Excel文件、写入各种类型的数据、格式化单元格,以及处理现有文件。通过本文的学习,您将掌握C#操作Excel的核心技能,从而极大地提升工作效率并确保数据的一致性。
为什么选择程序化写入Excel?
C#作为.NET平台的核心语言,在文件I/O和数据处理方面拥有强大的能力。将数据程序化写入Excel,相比手动操作,具有显著的优势:
- 自动化与效率提升: 告别繁琐的手动复制粘贴,通过代码实现数据自动导出,尤其适用于周期性报表生成或大量数据处理场景。
- 数据一致性与准确性: 避免人工输入错误,确保数据从源系统到Excel的转换过程保持高度一致性和准确性。
- 批量处理能力: 轻松处理成千上万行数据,几秒钟内完成手动操作可能需要数小时甚至数天的工作。
- 集成与扩展性: 可以将Excel导出功能无缝集成到现有应用程序中,根据业务需求灵活扩展功能,例如生成图表、数据透视表等。
尽管C#提供了基础的文件操作API,但直接操作Excel的二进制格式非常复杂。因此,引入一个专业的第三方库是实现高效Excel操作的最佳实践。
准备工作与环境搭建
在开始编写代码之前,我们需要确保开发环境中已安装必要的库。本文将使用一个高效的库来简化Excel操作。
创建C#项目:
打开Visual Studio,创建一个新的C#控制台应用程序(或您选择的任何C#项目类型)。-
安装NuGet包:
在Visual Studio中,右键点击您的项目,选择“管理NuGet程序包(Manage NuGet Packages...)”。在“浏览”选项卡中,搜索并安装以下包:Install-Package Spire.XLS这个命令会在您的项目中添加所有必要的引用,使您能够开始使用该库提供的功能。
核心操作:将数据写入Excel文件
现在,我们已经准备好环境,可以开始编写代码来操作Excel文件了。
创建新的Excel文件并写入数据
首先,我们将学习如何创建一个全新的Excel工作簿,并向其中写入基本数据和设置单元格格式。
using Spire.Xls;
using System.Drawing; // 用于颜色设置
public class ExcelWriter
{
public static void CreateNewExcel()
{
// 1. 创建一个新的Workbook对象
Workbook workbook = new Workbook();
// 2. 获取第一个工作表(默认会有一个Sheet1)
Worksheet sheet = workbook.Worksheets[0];
sheet.Name = "销售数据"; // 设置工作表名称
// 3. 向单元格写入文本数据
sheet.Range["A1"].Text = "产品名称";
sheet.Range["B1"].Text = "销售数量";
sheet.Range["C1"].Text = "单价";
sheet.Range["D1"].Text = "总金额";
// 4. 向单元格写入数字数据
sheet.Range["A2"].Text = "笔记本电脑";
sheet.Range["B2"].NumberValue = 10;
sheet.Range["C2"].NumberValue = 8999.00;
sheet.Range["D2"].Formula = "=B2*C2"; // 写入公式
sheet.Range["A3"].Text = "智能手机";
sheet.Range["B3"].NumberValue = 25;
sheet.Range["C3"].NumberValue = 4599.50;
sheet.Range["D3"].Formula = "=B3*C3";
// 5. 设置单元格格式
// 设置表头样式
CellStyle headerStyle = workbook.Styles.Add("headerStyle");
headerStyle.Font.IsBold = true;
headerStyle.KnownColor = ExcelColors.LightGreen1;
headerStyle.HorizontalAlignment = HorizontalAlignType.Center;
headerStyle.VerticalAlignment = VerticalAlignType.Center;
sheet.Range["A1:D1"].Style = headerStyle;
// 设置金额列的货币格式
sheet.Range["C2:D3"].Style.NumberFormat = "¥#,##0.00";
// 自动调整列宽以适应内容
sheet.AutoFitColumn(1);
sheet.AutoFitColumn(2);
sheet.AutoFitColumn(3);
sheet.AutoFitColumn(4);
// 6. 保存Excel文件
string filePath = "销售报表_新.xlsx";
workbook.SaveToFile(filePath, ExcelVersion.Version2016);
Console.WriteLine($"Excel文件已保存到: {Path.GetFullPath(filePath)}");
// 7. 释放资源
workbook.Dispose();
}
}
代码解读:
- 我们首先创建
Workbook对象,它代表一个Excel文件。 -
Worksheet对象代表工作簿中的一个工作表。 -
Range["A1"]通过索引器访问特定单元格,可以设置其Text、NumberValue或Formula。 -
CellStyle对象允许我们自定义字体、颜色、对齐方式等。 -
AutoFitColumn方法能自动调整列宽,使内容完全显示。 -
SaveToFile方法用于保存文件,并指定Excel版本。
从集合或数据源写入数据
在实际应用中,数据往往存储在List<T>、DataTable或数据库中。该库提供了便捷的方法来批量导入这些数据。
using Spire.Xls;
using System.Data;
using System.Collections.Generic;
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
public int Stock { get; set; }
}
public class ExcelWriter
{
public static void WriteDataFromCollection()
{
Workbook workbook = new Workbook();
Worksheet sheet = workbook.Worksheets[0];
sheet.Name = "产品列表";
// 准备数据
List<Product> products = new List<Product>
{
new Product { Id = 1, Name = "键盘", Price = 199.00m, Stock = 50 },
new Product { Id = 2, Name = "鼠标", Price = 99.50m, Stock = 120 },
new Product { Id = 3, Name = "显示器", Price = 1299.00m, Stock = 30 }
};
// 将List<T>数据写入Excel,并包含表头
// 第一个参数是数据源,第二个参数表示是否包含列头,
// 第三个和第四个参数表示从Excel的第几行第几列开始写入
sheet.InsertCollection(products, true, 1, 1);
// 如果是DataTable,用法类似
DataTable dataTable = new DataTable("用户信息");
dataTable.Columns.Add("UserID", typeof(int));
dataTable.Columns.Add("UserName", typeof(string));
dataTable.Columns.Add("Email", typeof(string));
dataTable.Rows.Add(101, "张三", "zhangsan@example.com");
dataTable.Rows.Add(102, "李四", "lisi@example.com");
// 将DataTable数据写入Excel,从A5单元格开始
sheet.InsertDataTable(dataTable, true, 5, 1);
// 自动调整所有列宽
sheet.AutoFitColumns();
string filePath = "产品与用户数据.xlsx";
workbook.SaveToFile(filePath, ExcelVersion.Version2016);
Console.WriteLine($"Excel文件已保存到: {Path.GetFullPath(filePath)}");
workbook.Dispose();
}
}
代码解读:
-
InsertCollection方法可以直接将List<T>类型的数据导入到工作表中,极大地简化了循环写入单元格的过程。 -
InsertDataTable方法则用于将DataTable中的数据导入Excel。 - 这两个方法都支持指定是否包含列头以及写入的起始位置。
处理现有Excel文件并追加/修改数据
有时,我们可能需要修改或向一个已存在的Excel文件追加数据,而不是创建一个新文件。
using Spire.Xls;
using System.IO;
public class ExcelWriter
{
public static void UpdateExistingExcel()
{
string existingFilePath = "销售报表_新.xlsx"; // 假设这个文件已经存在
// 检查文件是否存在
if (!File.Exists(existingFilePath))
{
Console.WriteLine($"文件不存在: {Path.GetFullPath(existingFilePath)},请先运行 CreateNewExcel 方法。");
return;
}
// 1. 加载现有的Workbook对象
Workbook workbook = new Workbook();
workbook.LoadFromFile(existingFilePath);
// 2. 获取指定的工作表
Worksheet sheet = workbook.Worksheets["销售数据"]; // 根据名称获取
// 3. 追加新数据行
int lastRow = sheet.LastRow + 1; // 获取当前数据的最后一行,然后加1作为新行的起始行
sheet.Range[$"A{lastRow}"].Text = "无线耳机";
sheet.Range[$"B{lastRow}"].NumberValue = 50;
sheet.Range[$"C{lastRow}"].NumberValue = 399.00;
sheet.Range[$"D{lastRow}"].Formula = $"=B{lastRow}*C{lastRow}";
sheet.Range[$"C{lastRow}:D{lastRow}"].Style.NumberFormat = "¥#,##0.00"; // 重新应用格式
// 4. 修改现有单元格数据
sheet.Range["B2"].NumberValue = 12; // 将笔记本电脑的销售数量从10修改为12
sheet.CalculateAllValue(); // 重新计算所有公式
// 5. 添加超链接和注释
sheet.Range["A" + (lastRow + 2)].Text = "访问官网";
HyperLink hyperlink = sheet.HyperLinks.Add(sheet.Range["A" + (lastRow + 2)]);
hyperlink.Type = HyperLinkType.Url;
hyperlink.Address = "https://www.e-iceblue.com/";
sheet.Range["A" + (lastRow + 3)].Text = "重要提示";
sheet.Range["A" + (lastRow + 3)].Comment.Text = "这是关于新产品的销售提示!";
// 6. 保存修改
workbook.SaveToFile(existingFilePath, ExcelVersion.Version2016);
Console.WriteLine($"Excel文件已更新: {Path.GetFullPath(existingFilePath)}");
workbook.Dispose();
}
}
代码解读:
-
workbook.LoadFromFile(existingFilePath)用于加载现有文件。 -
sheet.LastRow属性可以方便地获取当前工作表中数据所在的最后一行行号。 - 修改单元格数据后,如果存在公式,需要调用
workbook.CalculateAllValue()来重新计算所有公式的结果。 - HyperLink对象和Comment对象可以用来添加超链接和注释。
保存Excel文件
保存文件是操作的最后一步,您可以看到在上述示例中已经多次使用。SaveToFile方法允许您指定文件路径和Excel版本。
// 保存为XLSX格式(推荐)
workbook.SaveToFile("MyReport.xlsx", ExcelVersion.Version2016);
// 保存为XLS格式(兼容旧版Excel)
// workbook.SaveToFile("MyReport.xls", ExcelVersion.Version97to2003);
进阶技巧与注意事项
性能优化: 对于写入大量数据(例如数十万行)的场景,避免频繁地访问单个单元格。优先使用
InsertCollection或InsertDataTable进行批量写入,或者一次性获取一个范围(sheet.Range["A1:Z10000"])并设置其值。-
错误处理: 文件操作可能会遇到各种问题,例如文件被占用、路径不存在等。始终使用
try-catch块来捕获和处理潜在的异常,提高程序的健壮性。try { // Excel操作代码 workbook.SaveToFile(filePath, ExcelVersion.Version2016); } catch (Exception ex) { Console.WriteLine($"保存Excel文件时发生错误: {ex.Message}"); } -
资源释放:
Workbook对象和Worksheet对象会占用内存和文件句柄。为了避免内存泄漏或文件锁,务必在操作完成后调用Dispose()方法来释放资源,或者使用using语句来确保资源被正确释放。该库的Workbook类实现了IDisposable接口,因此可以使用using。using (Workbook workbook = new Workbook()) { // 所有Excel操作 // workbook.SaveToFile(...) } // 在这里workbook会自动Dispose
总结
通过本文的详细教程,我们学习了如何使用C#结合一个高效的第三方库,将数据轻松、准确地写入Excel文件。从创建新文件、写入各种类型的数据,到格式化单元格、批量导入集合数据,再到修改现有文件,我们涵盖了C#开发者在日常工作中可能遇到的核心场景。
程序化写入Excel不仅能够显著提升数据处理的效率,还能确保数据的一致性和准确性,是现代软件开发中不可或缺的技能。现在,您已经掌握了这些基础知识,鼓励您根据自己的项目需求进行实践和扩展,例如生成更复杂的图表、处理多工作表数据等。通过自动化Excel操作,您的应用程序将变得更加强大和灵活,为用户带来更好的体验。