C#使用ClosedXML时能否以只读方式打开Excel文件?
ClosedXML读取被Excel占用的xlsx文件的实现方案
问题背景
编写基于ClosedXML库的C#程序时,核心逻辑为打开Excel电子表格读取内容,初始实现代码如下:
using ClosedXML.Excel; public void foo() { var workbook = new XLWorkbook("C:\\Users\\me\\testSpreadsheet.xlsx"); // 读取并处理数据 }
测试发现当目标电子表格被其他进程打开占用时,new XLWorkbook()语句会抛出IOException,异常信息如下:
System.IO.IOException: 'The process cannot access the file 'C:\\Users\\me\\testSpreadsheet.xlsx' because it is being used by another process.
该异常符合文件读写的常规逻辑:默认情况下C#程序与Excel进程无法同时持有文件的读写编辑权限。预期需求是:用户可以保持文件打开状态,在Excel中编辑、保存内容,无需关闭电子表格即可正常运行代码读取文件。
曾尝试通过try/catch捕获异常的方案解决该问题,代码如下:
using ClosedXML.Excel; public void foo() { try { var workbook = new XLWorkbook("C:\\Users\\me\\testSpreadsheet.xlsx"); // 读取并处理数据 } catch(System.IO.IOException e) { System.Console.WriteLine("GAH!!! Excel spreadsheet is open!"); System.Console.WriteLine(e); } }
该方案没有任何效果,电子表格处于打开状态时new XLWorkbook()仍然抛出相同IO异常。问题根源是new XLWorkbook()默认以**读写(RW)**权限打开目标文件。查阅ClosedXML官方文档未找到以只读(RO)方式打开文件的相关说明,因此确认可行实现方案,判断是否需要更换其他类库。
可行解决方案
不需要更换类库,问题的核心原因是直接传入文件路径实例化XLWorkbook时,底层默认使用独占读写的模式打开文件,只要手动控制文件流的打开参数,就可以实现被占用状态下的文件读取,实现代码如下:
using ClosedXML.Excel; using System.IO; public void foo() { // 手动配置文件打开模式:只读访问、允许其他进程读写共享 using (var fileStream = new FileStream( path: "C:\\Users\\me\\testSpreadsheet.xlsx", mode: FileMode.Open, access: FileAccess.Read, share: FileShare.ReadWrite)) { using (var workbook = new XLWorkbook(fileStream)) { // 执行数据读取和处理逻辑 } } }
方案说明
FileShare.ReadWrite参数是核心,该配置允许其他进程(包括打开文件的Excel进程)同时对文件持有读写权限,不会触发文件占用的IO异常- 该方式读取的是磁盘上最新保存的文件版本,用户在Excel中未保存的内存编辑内容无法被读取
- 该写法是ClosedXML官方支持的标准流加载方式,不存在版本兼容性问题
- 如果业务场景需要读取用户未保存的Excel内存内容,ClosedXML无法实现,需要改用Excel互操作(Interop)方式实现,常规读取已保存内容的场景下上述方案完全满足需求。
内容的提问来源于stack exchange,提问作者Pete
相关产品推荐
相关产品推荐

