本文将深入探讨MudTools.OfficeInterop.Excel如何创建和管理Excel应用程序实例。Excel应用程序是整个Excel自动化的核心,正确管理应用程序实例对于确保程序的稳定性、性能和资源释放至关重要。
目标
- 掌握ExcelFactory类的各种创建方法
- 理解应用程序生命周期管理
- 学习异常处理和资源释放策略
- 掌握多实例管理的最佳实践
关键概念
- Excel应用程序实例:代表Excel程序的运行实例
- 工作簿:Excel文件的基本容器
- 工作表:工作簿中的具体数据表
- COM对象:Excel与.NET通信的底层技术
2.1 ExcelFactory类详解
ExcelFactory类是MudTools.OfficeInterop.Excel库的核心类,提供了多种创建Excel应用程序实例的方法。每种方法都有其特定的应用场景和优缺点。
2.1.1 BlankWorkbook方法
BlankWorkbook()方法是最常用的创建方式,它会启动一个Excel应用程序并创建一个空白工作簿。
csharp
/// <summary>
/// 创建空白工作簿示例
/// 演示如何使用ExcelFactory.BlankWorkbook()方法创建Excel应用程序实例
/// </summary>
static void BlankWorkbookExample()
{
Console.WriteLine("=== 创建空白工作簿示例 ===");
try
{
// 使用BlankWorkbook方法创建Excel应用程序实例
using var excelApp = ExcelFactory.BlankWorkbook();
// 获取活动工作簿
var workbook = excelApp.ActiveWorkbook;
// 获取活动工作表
var worksheet = workbook.ActiveSheetWrap;
// 设置工作表名称
worksheet.Name = "空白工作簿示例";
// 添加标题
worksheet.Range("A1").Value = "Excel应用程序管理 - 空白工作簿示例";
worksheet.Range("A1").Font.Bold = true;
worksheet.Range("A1").Font.Size = 16;
worksheet.Range("A1").Interior.Color = System.Drawing.Color.LightBlue;
// 保存工作簿
string fileName = $"BlankWorkbookExample_{DateTime.Now:yyyyMMddHHmmss}.xlsx";
workbook.SaveAs(fileName);
Console.WriteLine($"✓ 成功创建空白工作簿: {fileName}");
}
catch (Exception ex)
{
Console.WriteLine($"✗ 创建空白工作簿时出错: {ex.Message}");
}
}
方法特点:
- ✅ 自动创建新工作簿
- ✅ 适用于大多数简单场景
- ✅ 代码简洁易用
- ❌ 无法指定特定Excel版本
2.1.2 CreateInstance方法
CreateInstance(string progId)方法允许通过指定ProgID来创建特定版本的Excel实例。
csharp
/// <summary>
/// 通过ProgID创建特定版本实例示例
/// 演示如何使用ExcelFactory.CreateInstance()方法创建特定版本的Excel应用程序实例
/// </summary>
static void CreateInstanceExample()
{
Console.WriteLine("=== 通过ProgID创建特定版本实例示例 ===");
try
{
// 使用CreateInstance方法创建特定版本的Excel应用程序实例
// Excel.Application是Excel的ProgID
using var excelApp = ExcelFactory.CreateInstance("Excel.Application");
// 设置Excel应用程序可见性
excelApp.Visible = true;
// 创建新工作簿
var workbook = excelApp.BlankWorkbook();
// 获取活动工作表
var worksheet = workbook.ActiveSheetWrap;
// 设置工作表名称
worksheet.Name = "特定版本示例";
// 添加示例数据
worksheet.Range("A5").Value = "Excel版本: " + excelApp.Version;
string fileName = $"CreateInstanceExample_{DateTime.Now:yyyyMMddHHmmss}.xlsx";
workbook.SaveAs(fileName);
Console.WriteLine($"✓ 成功创建特定版本实例工作簿: {fileName}");
}
catch (Exception ex)
{
Console.WriteLine($"✗ 通过ProgID创建特定版本实例时出错: {ex.Message}");
}
}
支持的ProgID示例:
"Excel.Application"- 最新版本的Excel"Excel.Application.16"- Excel 2016"Excel.Application.15"- Excel 2013"Excel.Application.14"- Excel 2010
2.1.3 CreateFrom方法
CreateFrom(string templatePath)方法基于现有模板创建新的工作簿。
csharp
/// <summary>
/// 基于模板创建工作簿示例
/// 演示如何使用ExcelFactory.CreateFrom()方法基于模板创建工作簿
/// </summary>
static void CreateFromTemplateExample()
{
Console.WriteLine("=== 基于模板创建工作簿示例 ===");
try
{
// 首先创建一个模板文件
CreateTemplateFile();
// 使用CreateFrom方法基于模板创建工作簿
using var excelApp = ExcelFactory.CreateFrom("Template.xlsx");
// 获取活动工作簿
var workbook = excelApp.ActiveWorkbook;
// 获取活动工作表
var worksheet = workbook.ActiveSheetWrap;
// 填充模板中的数据
worksheet.Range("B2").Value = "张三";
worksheet.Range("B3").Value = "Excel自动化工程师";
worksheet.Range("B4").Value = DateTime.Now.ToString("yyyy-MM-dd");
worksheet.Range("B5").Value = "北京市朝阳区";
string fileName = $"CreateFromTemplateExample_{DateTime.Now:yyyyMMddHHmmss}.xlsx";
workbook.SaveAs(fileName);
Console.WriteLine($"✓ 成功基于模板创建工作簿: {fileName}");
}
catch (Exception ex)
{
Console.WriteLine($"✗ 基于模板创建工作簿时出错: {ex.Message}");
}
}
模板创建示例:
csharp
static void CreateTemplateFile()
{
try
{
// 创建Excel应用程序实例
using var excelApp = ExcelFactory.BlankWorkbook();
// 获取活动工作簿和工作表
var workbook = excelApp.ActiveWorkbook;
var worksheet = workbook.ActiveSheetWrap;
// 设置模板内容
worksheet.Range("A1").Value = "员工信息表";
worksheet.Range("A1").Font.Bold = true;
worksheet.Range("A1").Font.Size = 16;
worksheet.Range("A1").Interior.Color = System.Drawing.Color.LightYellow;
worksheet.Range("A2").Value = "姓名:";
worksheet.Range("A3").Value = "职位:";
worksheet.Range("A4").Value = "入职日期:";
worksheet.Range("A5").Value = "地址:";
// 添加边框
worksheet.Range("A1:B6").Borders.LineStyle = XlLineStyle.xlContinuous;
// 保存为模板文件
workbook.SaveAs("Template.xlsx");
}
catch (Exception ex)
{
Console.WriteLine($"创建模板文件时出错: {ex.Message}");
}
}
2.1.4 Open方法
Open(string filePath)方法用于打开现有的Excel文件。
csharp
/// <summary>
/// 打开现有工作簿示例
/// 演示如何使用ExcelFactory.Open()方法打开现有工作簿
/// </summary>
static void OpenExistingWorkbookExample()
{
Console.WriteLine("=== 打开现有工作簿示例 ===");
try
{
// 首先创建一个要打开的文件
CreateExistingFile();
// 使用Open方法打开现有工作簿
using var excelApp = ExcelFactory.Open("ExistingFile.xlsx");
// 获取活动工作簿
var workbook = excelApp.ActiveWorkbook;
// 获取活动工作表
var worksheet = workbook.ActiveSheetWrap;
// 读取现有数据
var existingValue = worksheet.Range("A1").Value;
Console.WriteLine($"原始数据: {existingValue}");
// 修改数据
worksheet.Range("A3").Value = "这是通过ExcelFactory.Open()方法打开并修改的数据";
worksheet.Range("A4").Value = "修改时间: " + DateTime.Now.ToString();
string fileName = $"OpenExistingWorkbookExample_{DateTime.Now:yyyyMMddHHmmss}.xlsx";
workbook.SaveAs(fileName);
Console.WriteLine($"✓ 成功打开并修改现有工作簿: {fileName}");
}
catch (Exception ex)
{
Console.WriteLine($"✗ 打开现有工作簿时出错: {ex.Message}");
}
}
2.2 应用程序生命周期管理
正确的生命周期管理是Excel自动化开发的关键,不当的管理会导致资源泄漏和程序不稳定。
2.2.1 使用using语句进行资源管理
csharp
// 推荐的使用方式
using var excelApp = ExcelFactory.BlankWorkbook();
var workbook = excelApp.ActiveWorkbook;
// 执行Excel操作
workbook.ActiveSheetWrap.Range("A1").Value = "Hello World";
// 自动释放资源 - using语句结束时
2.2.2 手动资源释放模式
csharp
// 手动资源管理示例
ExcelApplicationWrapper excelApp = null;
try
{
excelApp = ExcelFactory.BlankWorkbook();
// 执行Excel操作
var workbook = excelApp.ActiveWorkbook;
workbook.ActiveSheetWrap.Range("A1").Value = "Hello World";
// 保存文件
workbook.SaveAs("manual_management.xlsx");
}
catch (Exception ex)
{
Console.WriteLine($"操作失败: {ex.Message}");
}
finally
{
// 手动释放资源
excelApp?.Dispose();
}
2.2.3 异常处理策略
csharp
/// <summary>
/// 完整的异常处理示例
/// </summary>
static void SafeExcelOperation()
{
ExcelApplicationWrapper excelApp = null;
try
{
// 创建Excel实例
excelApp = ExcelFactory.BlankWorkbook();
// 设置应用程序属性
excelApp.Visible = false; // 后台运行
excelApp.DisplayAlerts = false; // 禁用警告
// 获取工作簿
var workbook = excelApp.ActiveWorkbook;
var worksheet = workbook.ActiveSheetWrap;
// 执行复杂操作
for (int i = 1; i <= 100; i++)
{
worksheet.Range($"A{i}").Value = $"数据行 {i}";
// 添加进度检查点
if (i % 10 == 0)
{
Console.WriteLine($"已处理 {i} 行数据");
}
}
// 保存结果
workbook.SaveAs("safe_operation_result.xlsx");
Console.WriteLine("✓ 操作成功完成");
}
catch (COMException comEx)
{
Console.WriteLine($"COM异常: {comEx.Message}");
Console.WriteLine($"错误代码: {comEx.ErrorCode}");
}
catch (Exception ex)
{
Console.WriteLine($"一般异常: {ex.Message}");
}
finally
{
// 确保资源释放
try
{
excelApp?.Quit();
excelApp?.Dispose();
}
catch (Exception disposeEx)
{
Console.WriteLine($"资源释放异常: {disposeEx.Message}");
}
}
}
2.3 应用程序属性配置
Excel应用程序提供了丰富的属性来控制其行为,合理配置这些属性可以显著提升程序性能和用户体验。
2.3.1 可见性控制
csharp
/// <summary>
/// 可见性控制示例
/// </summary>
static void VisibilityControlExample()
{
// 前台模式 - 用户可见
using var visibleApp = ExcelFactory.BlankWorkbook();
visibleApp.Visible = true; // 显示Excel窗口
visibleApp.ActiveWorkbook.ActiveSheetWrap.Range("A1").Value = "前台模式";
// 后台模式 - 无界面运行
using var invisibleApp = ExcelFactory.BlankWorkbook();
invisibleApp.Visible = false; // 隐藏Excel窗口
invisibleApp.ActiveWorkbook.ActiveSheetWrap.Range("A1").Value = "后台模式";
Console.WriteLine("两种模式都已完成");
}
2.3.2 警告和提示控制
csharp
/// <summary>
/// 警告控制示例
/// </summary>
static void AlertControlExample()
{
using var excelApp = ExcelFactory.BlankWorkbook();
// 禁用警告(适合批量操作)
excelApp.DisplayAlerts = false;
// 启用警告(适合交互式操作)
// excelApp.DisplayAlerts = true;
var workbook = excelApp.ActiveWorkbook;
var worksheet = workbook.ActiveSheetWrap;
// 尝试覆盖现有文件(在禁用警告时不会弹出确认对话框)
worksheet.Range("A1").Value = "测试数据";
workbook.SaveAs("test_file.xlsx");
Console.WriteLine("文件已保存(禁用警告模式)");
}
2.3.3 屏幕更新控制
csharp
/// <summary>
/// 屏幕更新控制示例(性能优化)
/// </summary>
static void ScreenUpdateControlExample()
{
using var excelApp = ExcelFactory.BlankWorkbook();
var workbook = excelApp.ActiveWorkbook;
var worksheet = workbook.ActiveSheetWrap;
// 禁用屏幕更新(大幅提升性能)
excelApp.ScreenUpdating = false;
try
{
// 执行大量数据填充操作
for (int row = 1; row <= 1000; row++)
{
for (int col = 1; col <= 10; col++)
{
worksheet.Cells[row, col].Value = $"数据 {row}-{col}";
}
}
Console.WriteLine("数据填充完成");
}
finally
{
// 恢复屏幕更新
excelApp.ScreenUpdating = true;
}
workbook.SaveAs("large_data_file.xlsx");
Console.WriteLine("文件已保存");
}
2.4 多实例管理
在企业级应用中,经常需要同时管理多个Excel实例,正确的多实例管理策略至关重要。
2.4.1 独立实例管理
csharp
/// <summary>
/// 多实例独立管理示例
/// </summary>
static void MultiInstanceManagement()
{
// 实例1:处理销售数据
using var salesApp = ExcelFactory.BlankWorkbook();
var salesWorkbook = salesApp.ActiveWorkbook;
var salesSheet = salesWorkbook.ActiveSheetWrap;
salesSheet.Name = "销售数据";
salesSheet.Range("A1").Value = "销售报表";
// 实例2:处理库存数据
using var inventoryApp = ExcelFactory.BlankWorkbook();
var inventoryWorkbook = inventoryApp.ActiveWorkbook;
var inventorySheet = inventoryWorkbook.ActiveSheetWrap;
inventorySheet.Name = "库存数据";
inventorySheet.Range("A1").Value = "库存报表";
// 同时操作两个实例
salesSheet.Range("A2").Value = "销售数据正在处理...";
inventorySheet.Range("A2").Value = "库存数据正在处理...";
// 分别保存
salesWorkbook.SaveAs("sales_report.xlsx");
inventoryWorkbook.SaveAs("inventory_report.xlsx");
Console.WriteLine("多实例操作完成");
}
2.4.2 实例池模式
csharp
/// <summary>
/// Excel实例池管理器
/// </summary>
public class ExcelInstancePool : IDisposable
{
private readonly Queue<ExcelApplicationWrapper> _pool = new();
private readonly int _maxPoolSize;
private readonly object _lockObject = new();
public ExcelInstancePool(int maxPoolSize = 5)
{
_maxPoolSize = maxPoolSize;
}
/// <summary>
/// 从池中获取Excel实例
/// </summary>
public ExcelApplicationWrapper GetInstance()
{
lock (_lockObject)
{
if (_pool.Count > 0)
{
return _pool.Dequeue();
}
if (_pool.Count < _maxPoolSize)
{
return CreateNewInstance();
}
throw new InvalidOperationException("实例池已满");
}
}
/// <summary>
/// 将实例返回到池中
/// </summary>
public void ReturnInstance(ExcelApplicationWrapper instance)
{
lock (_lockObject)
{
if (_pool.Count < _maxPoolSize)
{
_pool.Enqueue(instance);
}
else
{
instance.Dispose();
}
}
}
private ExcelApplicationWrapper CreateNewInstance()
{
var instance = ExcelFactory.BlankWorkbook();
instance.Visible = false;
instance.DisplayAlerts = false;
instance.ScreenUpdating = false;
return instance;
}
public void Dispose()
{
lock (_lockObject)
{
while (_pool.Count > 0)
{
_pool.Dequeue().Dispose();
}
}
}
}
/// <summary>
/// 使用实例池的示例
/// </summary>
static void InstancePoolExample()
{
using var pool = new ExcelInstancePool(3);
// 并行处理多个任务
var tasks = new List<Task>();
for (int i = 1; i <= 5; i++)
{
int taskId = i;
var task = Task.Run(() =>
{
var instance = pool.GetInstance();
try
{
var workbook = instance.ActiveWorkbook;
var worksheet = workbook.ActiveSheetWrap;
worksheet.Range("A1").Value = $"任务 {taskId} 数据";
worksheet.Range("A2").Value = $"处理时间: {DateTime.Now}";
workbook.SaveAs($"task_{taskId}_result.xlsx");
Console.WriteLine($"任务 {taskId} 完成");
}
finally
{
pool.ReturnInstance(instance);
}
});
tasks.Add(task);
}
Task.WaitAll(tasks.ToArray());
Console.WriteLine("所有并行任务完成");
}
2.5 高级应用场景
2.5.1 后台服务应用
csharp
/// <summary>
/// 后台服务示例 - 定时处理Excel文件
/// </summary>
public class ExcelBackgroundService
{
private readonly Timer _timer;
private readonly string _watchDirectory;
public ExcelBackgroundService(string watchDirectory, TimeSpan interval)
{
_watchDirectory = watchDirectory;
_timer = new Timer(ProcessFiles, null, TimeSpan.Zero, interval);
}
private void ProcessFiles(object state)
{
try
{
var excelFiles = Directory.GetFiles(_watchDirectory, "*.xlsx");
foreach (var filePath in excelFiles)
{
ProcessSingleFile(filePath);
}
}
catch (Exception ex)
{
Console.WriteLine($"后台处理出错: {ex.Message}");
}
}
private void ProcessSingleFile(string filePath)
{
using var excelApp = ExcelFactory.Open(filePath);
var workbook = excelApp.ActiveWorkbook;
var worksheet = workbook.ActiveSheetWrap;
// 处理逻辑
var data = worksheet.Range("A1").Value;
Console.WriteLine($"处理文件: {Path.GetFileName(filePath)}, 数据: {data}");
// 保存处理结果
var resultPath = Path.Combine(
Path.GetDirectoryName(filePath) ?? string.Empty,
$"processed_{Path.GetFileName(filePath)}"
);
workbook.SaveAs(resultPath);
}
public void Stop()
{
_timer?.Dispose();
}
}
// 使用示例
static void BackgroundServiceExample()
{
var service = new ExcelBackgroundService(@"C:\ExcelFiles", TimeSpan.FromMinutes(5));
Console.WriteLine("后台服务已启动,按任意键停止...");
Console.ReadKey();
service.Stop();
Console.WriteLine("后台服务已停止");
}
2.5.2 模板应用系统
csharp
/// <summary>
/// 模板应用系统
/// </summary>
public class TemplateApplicationSystem
{
private readonly Dictionary<string, string> _templates;
public TemplateApplicationSystem()
{
_templates = new Dictionary<string, string>
{
{ "invoice", "Templates/invoice_template.xlsx" },
{ "report", "Templates/report_template.xlsx" },
{ "budget", "Templates/budget_template.xlsx" }
};
}
/// <summary>
/// 基于模板生成文档
/// </summary>
public string GenerateDocument(string templateType, Dictionary<string, object> data)
{
if (!_templates.ContainsKey(templateType))
throw new ArgumentException($"模板类型 '{templateType}' 不存在");
var templatePath = _templates[templateType];
using var excelApp = ExcelFactory.CreateFrom(templatePath);
var workbook = excelApp.ActiveWorkbook;
var worksheet = workbook.ActiveSheetWrap;
// 填充模板数据
foreach (var kvp in data)
{
worksheet.Range(kvp.Key).Value = kvp.Value;
}
// 生成输出文件名
var outputFileName = $"{templateType}_{DateTime.Now:yyyyMMddHHmmss}.xlsx";
workbook.SaveAs(outputFileName);
return outputFileName;
}
}
// 使用示例
static void TemplateSystemExample()
{
var system = new TemplateApplicationSystem();
// 生成发票
var invoiceData = new Dictionary<string, object>
{
{ "B2", "INV-2023-001" }, // 发票编号
{ "B3", "张三" }, // 客户姓名
{ "B4", DateTime.Now.Date }, // 发票日期
{ "B5", 1500.50m }, // 金额
{ "B6", "增值税专用发票" } // 发票类型
};
var invoiceFile = system.GenerateDocument("invoice", invoiceData);
Console.WriteLine($"发票已生成: {invoiceFile}");
// 生成报告
var reportData = new Dictionary<string, object>
{
{ "A1", "月度销售报告" },
{ "A2", DateTime.Now.ToString("yyyy年MM月") },
{ "B4", 250000m }, // 销售额
{ "B5", 15 }, // 订单数量
{ "B6", 98.5m } // 完成率
};
var reportFile = system.GenerateDocument("report", reportData);
Console.WriteLine($"报告已生成: {reportFile}");
}
2.5.3 文件版本控制系统
csharp
/// <summary>
/// 文件版本控制系统
/// </summary>
public class FileVersionControlSystem
{
private readonly string _baseDirectory;
public FileVersionControlSystem(string baseDirectory)
{
_baseDirectory = baseDirectory;
EnsureDirectoryExists(_baseDirectory);
}
/// <summary>
/// 创建新版本
/// </summary>
public string CreateNewVersion(string originalFile, string versionComment)
{
if (!File.Exists(originalFile))
throw new FileNotFoundException($"文件不存在: {originalFile}");
var fileName = Path.GetFileNameWithoutExtension(originalFile);
var extension = Path.GetExtension(originalFile);
var timestamp = DateTime.Now.ToString("yyyyMMdd_HHmmss");
var versionFileName = $"{fileName}_v{timestamp}{extension}";
var versionFilePath = Path.Combine(_baseDirectory, versionFileName);
// 复制文件并添加版本信息
File.Copy(originalFile, versionFilePath, true);
// 在版本文件中添加注释
using var excelApp = ExcelFactory.Open(versionFilePath);
var workbook = excelApp.ActiveWorkbook;
var worksheet = workbook.ActiveSheetWrap;
// 在最后一个单元格添加版本信息
var lastCell = worksheet.Cells.SpecialCells(XlCellType.xlCellTypeLastCell);
var versionRow = lastCell.Row + 2;
worksheet.Cells[versionRow, 1].Value = $"版本创建时间: {DateTime.Now}";
worksheet.Cells[versionRow + 1, 1].Value = $"版本注释: {versionComment}";
workbook.Save();
return versionFilePath;
}
/// <summary>
/// 获取文件的所有版本
/// </summary>
public List<string> GetFileVersions(string fileName)
{
var searchPattern = $"{Path.GetFileNameWithoutExtension(fileName)}_v*{Path.GetExtension(fileName)}";
return Directory.GetFiles(_baseDirectory, searchPattern)
.OrderByDescending(f => f)
.ToList();
}
/// <summary>
/// 恢复到指定版本
/// </summary>
public void RestoreToVersion(string targetFile, string versionFile)
{
if (!File.Exists(versionFile))
throw new FileNotFoundException($"版本文件不存在: {versionFile}");
File.Copy(versionFile, targetFile, true);
Console.WriteLine($"已恢复到版本: {Path.GetFileName(versionFile)}");
}
private void EnsureDirectoryExists(string directory)
{
if (!Directory.Exists(directory))
{
Directory.CreateDirectory(directory);
}
}
}
// 使用示例
static void VersionControlExample()
{
var versionSystem = new FileVersionControlSystem(@"C:\ExcelVersions");
// 创建原始文件
using var excelApp = ExcelFactory.BlankWorkbook();
var workbook = excelApp.ActiveWorkbook;
var worksheet = workbook.ActiveSheetWrap;
worksheet.Range("A1").Value = "重要业务数据";
worksheet.Range("A2").Value = "版本1.0";
var originalFile = "business_data.xlsx";
workbook.SaveAs(originalFile);
// 创建多个版本
var version1 = versionSystem.CreateNewVersion(originalFile, "初始版本");
Console.WriteLine($"创建版本1: {Path.GetFileName(version1)}");
// 修改文件
worksheet.Range("A3").Value = "新增数据行";
workbook.Save();
var version2 = versionSystem.CreateNewVersion(originalFile, "添加新数据");
Console.WriteLine($"创建版本2: {Path.GetFileName(version2)}");
// 查看所有版本
var versions = versionSystem.GetFileVersions(originalFile);
Console.WriteLine("所有版本:");
foreach (var version in versions)
{
Console.WriteLine($" {Path.GetFileName(version)}");
}
// 恢复到第一个版本
versionSystem.RestoreToVersion(originalFile, version1);
Console.WriteLine("已恢复到初始版本");
}
2.6 性能优化和最佳实践
2.6.1 性能优化技巧
csharp
/// <summary>
/// 高性能Excel操作示例
/// </summary>
static void HighPerformanceExample()
{
using var excelApp = ExcelFactory.BlankWorkbook();
// 1. 禁用不需要的功能
excelApp.ScreenUpdating = false;
excelApp.DisplayAlerts = false;
excelApp.EnableEvents = false;
excelApp.Calculation = XlCalculation.xlCalculationManual;
var workbook = excelApp.ActiveWorkbook;
var worksheet = workbook.ActiveSheetWrap;
try
{
// 2. 批量操作数据(避免单个单元格操作)
var dataArray = new object[1000, 10];
for (int i = 0; i < 1000; i++)
{
for (int j = 0; j < 10; j++)
{
dataArray[i, j] = $"数据{i + 1}-{j + 1}";
}
}
// 一次性写入大量数据
worksheet.Range("A1:J1000").Value = dataArray;
// 3. 使用数组公式进行计算
worksheet.Range("K1:K1000").FormulaArray = "=LEN(A1:J1)";
Console.WriteLine("高性能操作完成");
}
finally
{
// 4. 恢复设置
excelApp.Calculation = XlCalculation.xlCalculationAutomatic;
excelApp.ScreenUpdating = true;
}
workbook.SaveAs("high_performance.xlsx");
}
2.6.2 内存管理最佳实践
csharp
/// <summary>
/// 内存管理最佳实践示例
/// </summary>
static void MemoryManagementBestPractices()
{
// 1. 及时释放COM对象引用
ExcelApplicationWrapper excelApp = null;
WorkbookWrapper workbook = null;
try
{
excelApp = ExcelFactory.BlankWorkbook();
workbook = excelApp.ActiveWorkbook;
// 执行操作
workbook.ActiveSheetWrap.Range("A1").Value = "测试数据";
// 2. 显式释放不再使用的对象
var tempRange = workbook.ActiveSheetWrap.Range("A1:B10");
tempRange.Value = "临时数据";
// tempRange不再需要时,可以显式释放
System.Runtime.InteropServices.Marshal.ReleaseComObject(tempRange.ComObject);
workbook.SaveAs("memory_managed.xlsx");
}
finally
{
// 3. 按照创建顺序的逆序释放资源
workbook?.Close(false);
excelApp?.Quit();
// 4. 强制垃圾回收(谨慎使用)
GC.Collect();
GC.WaitForPendingFinalizers();
workbook?.Dispose();
excelApp?.Dispose();
}
}
2.6.3 错误处理和恢复
csharp
/// <summary>
/// 健壮的错误处理示例
/// </summary>
static void RobustErrorHandling()
{
int retryCount = 0;
const int maxRetries = 3;
while (retryCount < maxRetries)
{
ExcelApplicationWrapper excelApp = null;
try
{
excelApp = ExcelFactory.BlankWorkbook();
// 模拟可能失败的操作
if (DateTime.Now.Second % 3 == 0) // 模拟随机失败
{
throw new COMException("模拟COM操作失败");
}
// 正常操作
excelApp.ActiveWorkbook.ActiveSheetWrap.Range("A1").Value = "成功操作";
excelApp.ActiveWorkbook.SaveAs("robust_operation.xlsx");
Console.WriteLine("操作成功完成");
break; // 成功,退出循环
}
catch (COMException comEx) when (retryCount < maxRetries - 1)
{
retryCount++;
Console.WriteLine($"COM异常,第{retryCount}次重试: {comEx.Message}");
// 等待一段时间后重试
Thread.Sleep(1000 * retryCount);
}
catch (Exception ex)
{
Console.WriteLine($"操作失败: {ex.Message}");
break;
}
finally
{
excelApp?.Dispose();
}
}
if (retryCount == maxRetries)
{
Console.WriteLine("操作失败,已达到最大重试次数");
}
}
2.7 实际应用案例
2.7.1 多实例管理系统
csharp
/// <summary>
/// 企业级多实例管理系统
/// </summary>
public class EnterpriseExcelInstanceManager
{
private readonly ConcurrentDictionary<string, ExcelInstanceInfo> _instances;
private readonly Timer _cleanupTimer;
public EnterpriseExcelInstanceManager()
{
_instances = new ConcurrentDictionary<string, ExcelInstanceInfo>();
_cleanupTimer = new Timer(CleanupInactiveInstances, null,
TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(5));
}
/// <summary>
/// 获取或创建实例
/// </summary>
public ExcelApplicationWrapper GetInstance(string instanceKey, bool createIfNotExists = true)
{
if (_instances.TryGetValue(instanceKey, out var instanceInfo) &&
instanceInfo.IsActive)
{
instanceInfo.LastAccessTime = DateTime.Now;
return instanceInfo.Instance;
}
if (createIfNotExists)
{
var newInstance = ExcelFactory.BlankWorkbook();
newInstance.Visible = false;
var newInfo = new ExcelInstanceInfo
{
Instance = newInstance,
LastAccessTime = DateTime.Now,
IsActive = true
};
_instances[instanceKey] = newInfo;
return newInstance;
}
throw new InvalidOperationException($"实例 '{instanceKey}' 不存在");
}
/// <summary>
/// 释放实例
/// </summary>
public void ReleaseInstance(string instanceKey)
{
if (_instances.TryRemove(instanceKey, out var instanceInfo))
{
instanceInfo.Instance.Dispose();
}
}
/// <summary>
/// 清理不活跃的实例
/// </summary>
private void CleanupInactiveInstances(object state)
{
var cutoffTime = DateTime.Now.AddMinutes(-10); // 10分钟不活跃
var inactiveKeys = _instances
.Where(kvp => kvp.Value.LastAccessTime < cutoffTime)
.Select(kvp => kvp.Key)
.ToList();
foreach (var key in inactiveKeys)
{
if (_instances.TryRemove(key, out var instanceInfo))
{
instanceInfo.Instance.Dispose();
Console.WriteLine($"清理不活跃实例: {key}");
}
}
}
public void Dispose()
{
_cleanupTimer?.Dispose();
foreach (var instanceInfo in _instances.Values)
{
instanceInfo.Instance.Dispose();
}
_instances.Clear();
}
}
public class ExcelInstanceInfo
{
public ExcelApplicationWrapper Instance { get; set; }
public DateTime LastAccessTime { get; set; }
public bool IsActive { get; set; }
}
// 使用示例
static void EnterpriseManagerExample()
{
using var manager = new EnterpriseExcelInstanceManager();
// 多个业务模块使用不同的实例
var salesInstance = manager.GetInstance("SalesModule");
var inventoryInstance = manager.GetInstance("InventoryModule");
var financeInstance = manager.GetInstance("FinanceModule");
// 各模块独立操作
salesInstance.ActiveWorkbook.ActiveSheetWrap.Range("A1").Value = "销售数据";
inventoryInstance.ActiveWorkbook.ActiveSheetWrap.Range("A1").Value = "库存数据";
financeInstance.ActiveWorkbook.ActiveSheetWrap.Range("A1").Value = "财务数据";
// 保存各自的文件
salesInstance.ActiveWorkbook.SaveAs("sales_data.xlsx");
inventoryInstance.ActiveWorkbook.SaveAs("inventory_data.xlsx");
financeInstance.ActiveWorkbook.SaveAs("finance_data.xlsx");
Console.WriteLine("企业级多实例管理完成");
}
2.7.2 后台服务应用
csharp
/// <summary>
/// 高级后台服务 - 支持任务队列和优先级
/// </summary>
public class AdvancedExcelBackgroundService
{
private readonly PriorityQueue<ExcelTask, int> _taskQueue;
private readonly SemaphoreSlim _semaphore;
private readonly CancellationTokenSource _cancellationTokenSource;
private readonly List<Task> _workerTasks;
public AdvancedExcelBackgroundService(int maxConcurrentTasks = 3)
{
_taskQueue = new PriorityQueue<ExcelTask, int>();
_semaphore = new SemaphoreSlim(maxConcurrentTasks);
_cancellationTokenSource = new CancellationTokenSource();
_workerTasks = new List<Task>();
// 启动工作线程
for (int i = 0; i < maxConcurrentTasks; i++)
{
var workerTask = Task.Run(ProcessTasksAsync);
_workerTasks.Add(workerTask);
}
}
/// <summary>
/// 添加处理任务
/// </summary>
public void AddTask(ExcelTask task, int priority = 0)
{
lock (_taskQueue)
{
_taskQueue.Enqueue(task, priority);
}
}
private async Task ProcessTasksAsync()
{
while (!_cancellationTokenSource.Token.IsCancellationRequested)
{
await _semaphore.WaitAsync(_cancellationTokenSource.Token);
ExcelTask task = null;
lock (_taskQueue)
{
if (_taskQueue.TryDequeue(out task, out _))
{
// 任务出队成功
}
}
if (task != null)
{
try
{
await ExecuteTaskAsync(task);
}
catch (Exception ex)
{
Console.WriteLine($"任务执行失败: {ex.Message}");
}
finally
{
_semaphore.Release();
}
}
else
{
_semaphore.Release();
await Task.Delay(1000); // 队列为空时等待
}
}
}
private async Task ExecuteTaskAsync(ExcelTask task)
{
using var excelApp = ExcelFactory.BlankWorkbook();
excelApp.Visible = false;
var workbook = excelApp.ActiveWorkbook;
var worksheet = workbook.ActiveSheetWrap;
// 执行任务特定的操作
await task.ExecuteAsync(worksheet);
// 保存结果
workbook.SaveAs(task.OutputFileName);
Console.WriteLine($"任务完成: {task.TaskName}");
}
public async Task StopAsync()
{
_cancellationTokenSource.Cancel();
await Task.WhenAll(_workerTasks);
}
}
public abstract class ExcelTask
{
public string TaskName { get; set; }
public string OutputFileName { get; set; }
public abstract Task ExecuteAsync(WorksheetWrapper worksheet);
}
// 具体任务实现
public class DataProcessingTask : ExcelTask
{
public List<string> Data { get; set; }
public override async Task ExecuteAsync(WorksheetWrapper worksheet)
{
// 模拟数据处理
for (int i = 0; i < Data.Count; i++)
{
worksheet.Cells[i + 1, 1].Value = Data[i];
// 模拟耗时操作
await Task.Delay(100);
}
}
}
// 使用示例
static async Task AdvancedBackgroundServiceExample()
{
var service = new AdvancedExcelBackgroundService(2); // 最大并发2个任务
// 添加高优先级任务
var highPriorityTask = new DataProcessingTask
{
TaskName = "紧急数据处理",
OutputFileName = "urgent_data.xlsx",
Data = new List<string> { "紧急数据1", "紧急数据2", "紧急数据3" }
};
service.AddTask(highPriorityTask, 1); // 高优先级
// 添加普通优先级任务
for (int i = 1; i <= 5; i++)
{
var normalTask = new DataProcessingTask
{
TaskName = $"普通任务{i}",
OutputFileName = $"normal_task_{i}.xlsx",
Data = Enumerable.Range(1, 10).Select(n => $"数据{i}-{n}").ToList()
};
service.AddTask(normalTask, 0); // 普通优先级
}
// 等待一段时间让任务执行
await Task.Delay(10000);
// 停止服务
await service.StopAsync();
Console.WriteLine("高级后台服务已停止");
}
2.7.3 模板应用系统增强版
csharp
/// <summary>
/// 增强版模板应用系统 - 支持动态模板和数据验证
/// </summary>
public class EnhancedTemplateApplicationSystem
{
private readonly ITemplateRepository _templateRepository;
private readonly IDataValidator _dataValidator;
public EnhancedTemplateApplicationSystem(ITemplateRepository templateRepository,
IDataValidator dataValidator)
{
_templateRepository = templateRepository;
_dataValidator = dataValidator;
}
/// <summary>
/// 生成文档(带数据验证)
/// </summary>
public async Task<DocumentGenerationResult> GenerateDocumentAsync(
string templateType,
Dictionary<string, object> data,
DocumentGenerationOptions options = null)
{
options ??= new DocumentGenerationOptions();
// 1. 数据验证
var validationResult = await _dataValidator.ValidateAsync(templateType, data);
if (!validationResult.IsValid)
{
return new DocumentGenerationResult
{
Success = false,
ErrorMessage = $"数据验证失败: {validationResult.ErrorMessage}",
ValidationErrors = validationResult.Errors
};
}
// 2. 获取模板
var template = await _templateRepository.GetTemplateAsync(templateType);
if (template == null)
{
return new DocumentGenerationResult
{
Success = false,
ErrorMessage = $"模板 '{templateType}' 不存在"
};
}
// 3. 生成文档
try
{
using var excelApp = ExcelFactory.CreateFrom(template.FilePath);
var workbook = excelApp.ActiveWorkbook;
var worksheet = workbook.ActiveSheetWrap;
// 填充数据
await FillTemplateDataAsync(worksheet, data, options);
// 应用格式
if (options.ApplyFormatting)
{
ApplyDocumentFormatting(worksheet, options.FormattingOptions);
}
// 生成输出文件名
var outputFileName = GenerateOutputFileName(templateType, options);
workbook.SaveAs(outputFileName);
return new DocumentGenerationResult
{
Success = true,
OutputFileName = outputFileName,
GeneratedAt = DateTime.Now
};
}
catch (Exception ex)
{
return new DocumentGenerationResult
{
Success = false,
ErrorMessage = $"文档生成失败: {ex.Message}"
};
}
}
private async Task FillTemplateDataAsync(WorksheetWrapper worksheet,
Dictionary<string, object> data,
DocumentGenerationOptions options)
{
foreach (var kvp in data)
{
var range = worksheet.Range(kvp.Key);
// 支持异步数据转换
var value = await ConvertDataAsync(kvp.Value, options);
range.Value = value;
// 记录修改历史
if (options.TrackChanges)
{
worksheet.Cells[range.Row + 1, range.Column].Value =
$"由系统生成于 {DateTime.Now:yyyy-MM-dd HH:mm:ss}";
}
}
}
private void ApplyDocumentFormatting(WorksheetWrapper worksheet, FormattingOptions formatting)
{
// 应用字体格式
if (formatting.FontSettings != null)
{
worksheet.Cells.Font.Name = formatting.FontSettings.FontName;
worksheet.Cells.Font.Size = formatting.FontSettings.FontSize;
}
// 应用颜色主题
if (formatting.ColorTheme != null)
{
// 实现颜色主题应用逻辑
}
}
private string GenerateOutputFileName(string templateType, DocumentGenerationOptions options)
{
var timestamp = options.UseCustomTimestamp ?
options.CustomTimestamp : DateTime.Now;
return $"{templateType}_{timestamp:yyyyMMddHHmmss}.xlsx";
}
private async Task<object> ConvertDataAsync(object value, DocumentGenerationOptions options)
{
// 实现数据转换逻辑
await Task.CompletedTask;
return value;
}
}
// 支持接口和类
public interface ITemplateRepository
{
Task<TemplateInfo> GetTemplateAsync(string templateType);
Task SaveTemplateAsync(TemplateInfo template);
}
public interface IDataValidator
{
Task<ValidationResult> ValidateAsync(string templateType, Dictionary<string, object> data);
}
public class DocumentGenerationResult
{
public bool Success { get; set; }
public string OutputFileName { get; set; }
public DateTime GeneratedAt { get; set; }
public string ErrorMessage { get; set; }
public List<string> ValidationErrors { get; set; }
}
public class DocumentGenerationOptions
{
public bool ApplyFormatting { get; set; } = true;
public bool TrackChanges { get; set; } = false;
public bool UseCustomTimestamp { get; set; } = false;
public DateTime CustomTimestamp { get; set; }
public FormattingOptions FormattingOptions { get; set; }
}
public class FormattingOptions
{
public FontSettings FontSettings { get; set; }
public ColorTheme ColorTheme { get; set; }
}
public class FontSettings
{
public string FontName { get; set; } = "微软雅黑";
public double FontSize { get; set; } = 11;
}
public class TemplateInfo
{
public string TemplateType { get; set; }
public string FilePath { get; set; }
public DateTime CreatedAt { get; set; }
public string Description { get; set; }
}
public class ValidationResult
{
public bool IsValid { get; set; }
public string ErrorMessage { get; set; }
public List<string> Errors { get; set; }
}
// 使用示例
static async Task EnhancedTemplateSystemExample()
{
// 创建依赖项(简化版)
var templateRepository = new SimpleTemplateRepository();
var dataValidator = new SimpleDataValidator();
var system = new EnhancedTemplateApplicationSystem(templateRepository, dataValidator);
// 生成文档
var options = new DocumentGenerationOptions
{
ApplyFormatting = true,
TrackChanges = true,
FormattingOptions = new FormattingOptions
{
FontSettings = new FontSettings { FontName = "宋体", FontSize = 12 }
}
};
var data = new Dictionary<string, object>
{
{ "B2", "INV-2023-001" },
{ "B3", "张三" },
{ "B4", 1500.50m }
};
var result = await system.GenerateDocumentAsync("invoice", data, options);
if (result.Success)
{
Console.WriteLine($"文档生成成功: {result.OutputFileName}");
}
else
{
Console.WriteLine($"文档生成失败: {result.ErrorMessage}");
}
}
// 简化实现
public class SimpleTemplateRepository : ITemplateRepository
{
public Task<TemplateInfo> GetTemplateAsync(string templateType)
{
var template = new TemplateInfo
{
TemplateType = templateType,
FilePath = $"Templates/{templateType}_template.xlsx",
CreatedAt = DateTime.Now,
Description = $"{templateType} 模板"
};
return Task.FromResult(template);
}
public Task SaveTemplateAsync(TemplateInfo template)
{
return Task.CompletedTask;
}
}
public class SimpleDataValidator : IDataValidator
{
public Task<ValidationResult> ValidateAsync(string templateType, Dictionary<string, object> data)
{
var result = new ValidationResult { IsValid = true, Errors = new List<string>() };
// 简单验证逻辑
if (!data.ContainsKey("B2") || string.IsNullOrEmpty(data["B2"]?.ToString()))
{
result.IsValid = false;
result.Errors.Add("B2字段不能为空");
}
return Task.FromResult(result);
}
}
2.8 总结
本章详细介绍了Excel应用程序的创建与管理,涵盖了从基础创建方法到高级企业级应用的各个方面。通过本章的学习,您应该能够:
- 掌握核心创建方法:熟练使用BlankWorkbook、CreateInstance、CreateFrom、Open等方法
- 理解生命周期管理:正确管理应用程序实例的创建、使用和释放
- 应用性能优化:使用屏幕更新控制、批量操作等技术提升性能
- 实现健壮的错误处理:处理COM异常、实现重试机制
- 构建企业级应用:实现多实例管理、后台服务、模板系统等高级功能
关键要点回顾
- 资源管理:始终使用using语句或正确的try-finally模式
- 性能优化:禁用不需要的Excel功能,使用批量操作
- 错误处理:针对COM异常的特殊处理,实现重试机制
- 多实例策略:根据业务需求选择合适的实例管理方式
相关资源: