2013-09-14 1 views
7

Я пытаюсь прочитать файл excel каждые 2 секунды, этот файл обновляется другим приложением RTD.Чтение файла Excel с помощью OleDB C#, когда он используется другим процессом

Я могу прочитать этот файл по Oledb-соединению, но проблема возникает, когда я пытаюсь прочитать его каждые 2 секунды. Из 10 попыток он может читать только 4-5 раз, а при других попытках он выдает исключение.

Строка подключения

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 месяца. Пожалуйста, пожалуйста, пожалуйста, пожалуйста, помогите мне

+3

Ну, что вам нужно? Не можете ли вы просто поймать исключение и ** повторить ** после (предположим) 500 мс? Если это невозможно, вы можете просто сделать копию с File.Copy, затем ** открыть копию **. К сожалению, вы не можете попросить драйвер OleDB обмениваться файлом между экземплярами. –

+0

@ Adriano. Прежде всего, спасибо за то, что вы дали время ur, я делаю то же повторение, но ищу лучший способ. Проблема с копированием файла - данные файла не сохраняются на жестком диске. Этот файл excel открыт на компьютере. Можете ли вы, пожалуйста, поделиться мной кодом/способом, где я могу сохранять/копировать этот файл каждые 2 секунды, а затем читать этот файл –

+0

Я бы обязательно воспользовался предложением @Adriano в своем ответе на использование FileSystemWatcher –

ответ

5

Драйвер Sadly OleDB по умолчанию откроет файл исключительно тогда, когда вы его не откроете, когда он используется кем-то другим, даже для чтения.

Два соображения:

  • Другое приложение может завершить свою работу с файлом в течение миллисекунд, так что это хорошо, чтобы попробовать еще раз
  • Драйвер всегда будет открыт файл заблокирован для записи (так что вы не можете открыть его в два раза через OleDB), но он используется для чтения (так что вы можете его скопировать).

Это говорит о том, что я предлагаю вам сначала попытаться открыть его после короткой паузы, если он все еще используется (и вы не можете ждать больше), тогда вы можете сделать копию и открыть ее.

Позвольте предположить, у вас есть свой код в 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); 
      } 
     } 
    } 
} 

код является немного некрасиво так просто считать его отправной точкой, чтобы написать свою собственную функцию.

соображения:

  • Retry не такая плохая вещь, и это общий способ решения такого рода проблем. Это, например, то, что делает оболочка Windows (и это даже более нормально с сетями).
  • Если приложение не закрыло файл, вы можете копировать (и читать) старые данные. Если вам всегда нужны самые современные данные, у вас есть только один выбор: wait. Если вы можете предположить, что несохраненные данные относятся к предыдущему временному кадру (T-1, как в цифровом электронном, когда край сигнала находится на краю часов), просто сделайте это и живите счастливым.

Непроверено решение:

Я не пробовал это, так что вы должны сделать это самостоятельно. Фактически (изначально я ошибался) вы можете открыть соединение только для чтения (через расширенные свойства). Это не документировано, если это относится только к соединению или как к файлу, так и к соединению. Во всяком случае давайте попробуем изменить строку подключения:

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

Просто добавил ReadOnly=true в конце Extended Properties.

Другие решения:

  • Единственное альтернативное решение, которое приходит на ум, чтобы ... вручную прочитать файл Excel (так что вы можете открыть его только для чтения). Тем не менее, даже в этом случае другое приложение, возможно, не записало новые данные (так что вы будете читать старый).
  • Не используйте таймер вообще. Измените свой дизайн, чтобы использовать FileSystemWatcher, вы будете читать файл только после того, как уведомление будет изменено.
  • Когда это применимо ... просто не используйте общий файл как механизм IPC! Возможно, вы не сможете изменить второе приложение, так что это может быть не ваше дело.
  • Не используйте OleDB для чтения файлов Microsoft Excel, существует множество бесплатных библиотек третьей части, которые не открывают файл с исключительной блокировкой, например this one.
  • Не читайте данные непосредственно из файлов, если экземпляр Microsoft Excel всегда работает, вы можете использовать COM-взаимодействие для получения уведомлений. Проверьте this general article о надстройках COM и this, чтобы узнать, как вы можете прикрепить свое приложение C# с помощью Office Interop к существующему экземпляру Microsoft Excel.
+0

. Спасибо Adriano, FileSystemWatcher может быть лучшим вариантом, но здесь сценарий совершенно другой, этот файл excel обновляется некоторыми DDE (RTD) **, но он не сохраняет файл excel **, а просто обновляет значения в excel-ячейках, которые мы можем видеть/читать вручную. –

+0

Уважаемый Всех из главных hurdle - всякий раз, когда данные обновляются в этом excel, ** он не сохраняется на жестком диске (если мы пытаемся прочитать данные из файлового потока, тогда он дает старые данные, которые могут быть 2 часа и более старые) **, я пробовал 10 секунд путей и обнаружил, что только OleDB способен читать несохраненные данные из файла Excel –

+0

@NidhiSharma Я добавил другое решение, я не тестировал его, но он работал _may_ ... –

1

Не знаете, почему вы хотите прочитать превосходное, как вы это делаете.

Вы можете попробовать LinqToExcel для чтения Excel, его небольшую небольшую библиотеку для чтения файлов excel, также если вам нужно создать excel, тогда попробуйте EPPLUS библиотеки. Эта библиотека, которую я лично нашел действительно эффективной при работе с Excels

0

У меня была аналогичная проблема. Ниже исправлены работы для меня

1) Не держите соединение с листом. Вместо этого открывайте данные для чтения соединения и немедленно закрывайте соединение.

2) Если вы используете управляемый код в неуправляемом приложении, рассмотрите возможность использования объекта управляемого типа вместо указателя (с помощью gcnew) и используйте Stack Semantics, чтобы убедиться, что память очищена, когда объект выходит из области видимости.

Смежные вопросы