用OleDB c#读取Excel文件,当被其他进程使用时

我正在尝试每2秒读取一个excel文件,该文件正在被其他RTD应用程序更新。

我能够通过Oledb连接读取此文件,但是当我每2秒钟尝试读取一次时就会出现问题。 在10次尝试中,只能读取4-5次,而在其他尝试中,则会抛出exception。

连接string

Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\nids\shes.xlsm;Extended Properties="Excel 12.0 Macro;HDR=Yes;IMEX=1" 

 //opening connection to excel file using (OleDbConnection connection = new OleDbConnection(constr))//constr = connection string { try { connection.Open(); isconopen = true; } catch { dispatcherTimer2.Start(); connection.Close(); isconopen = false; } // If connection is ok , then query sheet if (isconopen == true) { strcon = "SELECT * FROM [" + dsheet + "]"; using (OleDbDataAdapter adapter = new OleDbDataAdapter(strcon, connection)) { try { adapter.Fill(result); isread = true; adapter.Dispose(); connection.Close(); } catch { isread = false; dispatcherTimer2.Start(); adapter.Dispose(); connection.Close(); } } } //if able to retrieve data then call some other function if (isread == true) { converToCSV(0);// for further processing } 

请帮助我,我正在尝试从最近1个月。 请请请帮助我

可悲的OleDB驱动程序默认情况下会打开文件,然后当别人正在使用,甚至只是阅读时,你不能打开它。

两点考虑:

  • 其他应用程序可能会在几毫秒内完成与文件的工作,所以很高兴再次尝试
  • 驱动程序将始终打开文件locking写入(所以你不能通过OleDB打开它两次),但共享阅读(所以你可以复制它)。

也就是说,我build议你应该在短暂的暂停之后先打开它,如果它仍在使用中(而且你不能再等了),那么你可以复制并打开它。

让我假设你有一个HandlExcelFile()函数的代码:

 void HandleExcelFile(string path) { try { // Function will perform actual work HandleExcelFileCore(path); } catch (Exception) // Be more specific { Thread.Sleep(100); // Arbitrary try { HandleExcelFileCore(path); } catch (Exception) { string tempPath = Path.GetTempFileName(); File.Copy(path, tempPath); try { HandleExcelFileCore(tempPath); } finally { File.Delete(tempPath); } } } } 

代码有点丑陋,所以只要把它作为一个起点来编写你自己的函数。

注意事项:

  • 重试并不是什么坏事,这是解决这类问题的常用方法。 例如,Windowsshell就是这样(对于networking来说更是如此)。
  • 如果应用程序没有closures文件,那么您可以复制(和读取) 数据。 如果你总是需要最新的数据,那么你只有一个select:等待。 如果您可以假设未保存的数据属于之前的时间范围(T – 1,如数字电子时,信号边缘在时钟边缘),那么只要做到这一点,生活愉快。

未经testing的解决scheme:

我没有这样做,所以你必须自己做。 实际上(我最初是错的),你可以打开一个只读连接(通过扩展属性)。 如果这仅适用于连接或文件句柄和连接,则不予以说明。 无论如何,让我们尝试将您的连接string更改为:

 Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\nids\shes.xlsm;Extended Properties="Excel 12.0 Macro;HDR=Yes;IMEX=1;ReadOnly=true" 

刚刚在Extended Properties的末尾添加了ReadOnly=true

其他解决scheme

  • 我想到的唯一替代解决scheme是…手动读取Excel文件(所以你可以打开它只是为了阅读)。 即使在这种情况下,其他应用程序可能没有写入新的数据(所以你会读旧的数据)。
  • 根本不要使用计时器。 将您的devise更改为使用FileSystemWatcher ,只有在通知它被更改后才会读取该文件。
  • 适用时…只是不要使用共享文件作为IPC机制! 那么,你可能无法更改第二个应用程序,所以这可能不是你的情况。
  • 不要使用OleDB来读取Microsoft Excel文件,有许多第三部分免费库,不打开文件与排他锁,例如这一个 。
  • 不要直接从文件读取数据,如果Microsoft Excel实例始终运行,则可以使用COM interop来获取通知。 查看关于COM加载项的一般性文章 ,以了解如何将Office Interop的C#应用​​程序附加到现有的Microsoft Excel实例。

不知道,你为什么要按照自己的方式阅读excel。

你可以尝试LinqToExcel excel阅读,它是一个很好的小库,用于阅读excel文件,如果你需要创buildexcel然后尝试EPPLUS库。 在使用Excels时,我个人发现这些库非常有效

我有类似的问题。 下面的修复程序为我工作

1)不要把你的连接保持在页面上。 而是打开连接读取数据并立即closures连接。

2)如果您在非托pipe应用程序中使用托pipe代码,那么请考虑使用托pipetypes的对象而不是指针(使用gcnew),并使用Stack语义确保在对象超出范围时清除内存。