.NET <-> late binding <-> Excel, непонятки
От: Alexey.Velichko  
Дата: 06.07.10 14:42
Оценка:
Всем доброго дня!
Имеется .xls-документ, данные в котором нужно периодически обновлять, для этого использую позднее связывание. Код выглядит примерно следующим образом (упрощенный, но багу воспроизвести позволяет):

public void BugTest()
        {
            object application = null;
            object workbooks = null;
            object workbook = null;
            object worksheets = null;
            object sheet1 = null;

            Type excel = Type.GetTypeFromProgID("Excel.Application");

            CultureInfo ci = new System.Globalization.CultureInfo("en-US");

            try
            {
                application = Activator.CreateInstance(excel);

                application.GetType().InvokeMember("Visible", BindingFlags.SetProperty, null, application, new object[] { true }, ci);

                workbooks = application.GetType().InvokeMember("Workbooks", BindingFlags.GetProperty, null, application, null, ci);

                workbook = workbooks.GetType().InvokeMember("Add", BindingFlags.InvokeMethod, null, workbooks, null, ci);

                worksheets = workbook.GetType().InvokeMember("Worksheets", BindingFlags.GetProperty, null, workbook, null, ci);

                sheet1 = worksheets.GetType().InvokeMember("Item", BindingFlags.GetProperty, null, worksheets, new object[] { 1 }, ci);

                DummyProcess1(sheet1);
                
                application.GetType().InvokeMember("Quit", BindingFlags.InvokeMethod, null, application, null);
            }
            catch (COMException cme)
            {
                MessageBox.Show(cme.Message + Environment.NewLine + cme.Source,"BugTest");
            }
            catch (Exception exx)
            {
                MessageBox.Show(exx.Message,"BugTest");
            }
            finally
            {
                if (sheet1 != null && Marshal.IsComObject(sheet1))
                {
                    Marshal.ReleaseComObject(sheet1);
                    sheet1 = null;
                }

                if (worksheets != null && Marshal.IsComObject(worksheets))
                {
                    Marshal.ReleaseComObject(worksheets);
                    worksheets = null;
                }

                if (workbook != null && Marshal.IsComObject(workbook))
                {
                    Marshal.ReleaseComObject(workbook);
                    workbook = null;
                }

                if (workbooks != null && Marshal.IsComObject(workbooks))
                {
                    Marshal.ReleaseComObject(workbooks);
                    workbooks = null; 
                }

                if (application != null && Marshal.IsComObject(application))
                {
                    Marshal.ReleaseComObject(application);
                    application = null;
                }

            }           
        }

        public void DummyProcess1(object worksheet)
        {
            for (int i = 1; i < 10000; i++)
            {
                object cell = null, cell2 = null;

                try
                {
                    cell = worksheet.GetType().InvokeMember("Range", BindingFlags.GetProperty, null, worksheet, new object[] { "A" + i.ToString() });
                    cell.GetType().InvokeMember("Value", BindingFlags.SetProperty, null, cell, new object[] { "A" + i.ToString() });

                    cell2 = worksheet.GetType().InvokeMember("Range", BindingFlags.GetProperty, null, worksheet, new object[] { "B" + i.ToString() });
                    cell2.GetType().InvokeMember("Value", BindingFlags.SetProperty, null, cell2, new object[] { Guid.NewGuid().ToString() });

                    Thread.Sleep(10);
                }
                catch (COMException cme)
                {
                    MessageBox.Show(cme.Message + Environment.NewLine + cme.Source, "DummyProcess");
                }
                catch (Exception exx)
                {
                    MessageBox.Show(exx.Message,"DummyProcess");
                }
                finally
                {
                    if (cell != null && Marshal.IsComObject(cell))
                    {
                        Marshal.ReleaseComObject(cell);
                        cell = null;
                    }

                    if (cell2 != null && Marshal.IsComObject(cell2))
                    {
                        Marshal.ReleaseComObject(cell2);
                        cell2 = null;
                    }

                }

            }
        }


Т.е. создается новый экземпляр xl, затем создается книга и запускается некий долгий процесс обновления данных.
И вот в чем проблема:


Причем стоит закрыть диалог — и дальнейшие вызовы проходят нормально. Т.е. почему-то после вывода экселем любого диалога, все взаимодействие накрывается тазом, пока диалог не будет закрыт
Есть идеи, как это побороть? Запрещать пользователю открывать другие файлы, пока идет обновление — как-то не айс

Как бы сделать, чтобы любой файл, открываемый в процессе работы этого кода, открывался бы не в "моем" инстансе экселя, а создавался бы новый?
Re: .NET <-> late binding <-> Excel, непонятки
От: Аноним  
Дата: 06.07.10 16:15
Оценка:
Здравствуйте, Alexey.Velichko, Вы писали:

AV>Причем стоит закрыть диалог — и дальнейшие вызовы проходят нормально. Т.е. почему-то после вывода экселем любого диалога, все взаимодействие накрывается тазом, пока диалог не будет закрыт

Если я правильно помню, вот эта строчка отключает много "левых" диалогов:
    excelApp.DisplayAlerts = false;


AV>Есть идеи, как это побороть? Запрещать пользователю открывать другие файлы, пока идет обновление — как-то не айс

Я в свое время остановился на варианте отлавливать конкретно эту ошибку и пробовать обновить документ через какой-то интервал времени.
Re[2]: .NET <-> late binding <-> Excel, непонятки
От: Alexey.Velichko  
Дата: 06.07.10 18:17
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Если я правильно помню, вот эта строчка отключает много "левых" диалогов:

А>
А>    excelApp.DisplayAlerts = false;
А>

Попробовал DisplayAlerts = false на Excel 2007 — прокатило, а на 2003 — не работает... microsoft magic, аднака
Если других идей не подкинут, буду реализовывать ваш вариант с
А>отлавливать конкретно эту ошибку и пробовать обновить документ через какой-то интервал времени.
Спасибо.
Re: .NET <-> late binding <-> Excel, непонятки
От: Аноним  
Дата: 06.07.10 21:26
Оценка:
Попробуйте не открывать диалог, а просто войти в режим редактирования ячейки екселя.
Думаю, что тоже будет ошибка — это моя головная боль с 2000 excel.
Re: .NET <-> NPOI
От: андрей_к Россия  
Дата: 07.07.10 05:19
Оценка:
Здравствуйте, Alexey.Velichko, Вы писали:

Добрый день.
Работа через сom с exсel'ем специФична долгим временем выполнения операций. Если переделать алгоритм работы не критично, я бы посоветовал вам воспользоваться технологией NPOI. Скорость работы возрастает в разы, никоим образом не привязано к наличию excel и перенос алгоритма не займет много времени.

ну и ссылка
Re[2]: .NET <-> NPOI
От: андрей_к Россия  
Дата: 07.07.10 05:21
Оценка:
Да и ни каких повисших процессов Excel, в случае бага.
Re[2]: .NET <-> NPOI
От: Alexey.Velichko  
Дата: 07.07.10 06:43
Оценка:
Здравствуйте, андрей_к, Вы писали:

_>Работа через сom с exсel'ем специФична долгим временем выполнения операций. Если переделать алгоритм работы не критично, я бы посоветовал вам воспользоваться технологией NPOI. Скорость работы возрастает в разы, никоим образом не привязано к наличию excel и перенос алгоритма не займет много времени.


А как у него с макросами? у меня в книги их полно...а также формул и встроенных в листы картинок.
Re[3]: .NET <-> NPOI
От: андрей_к Россия  
Дата: 07.07.10 07:15
Оценка:
Здравствуйте, Alexey.Velichko, Вы писали:

AV>Здравствуйте, андрей_к, Вы писали:


_>>Работа через сom с exсel'ем специФична долгим временем выполнения операций. Если переделать алгоритм работы не критично, я бы посоветовал вам воспользоваться технологией NPOI. Скорость работы возрастает в разы, никоим образом не привязано к наличию excel и перенос алгоритма не займет много времени.


AV>А как у него с макросами? у меня в книги их полно...а также формул и встроенных в листы картинок.


Насчет макросов и картинок ничего конкретного сказать не могу,с ними использовать библиотеку не приходилось.
Формулы работают.
Re[4]: .NET <-> NPOI
От: Alexey.Velichko  
Дата: 07.07.10 09:12
Оценка:
Здравствуйте, андрей_к, Вы писали:

_>Здравствуйте, Alexey.Velichko, Вы писали:


AV>>Здравствуйте, андрей_к, Вы писали:


_>>>Работа через сom с exсel'ем специФична долгим временем выполнения операций. Если переделать алгоритм работы не критично, я бы посоветовал вам воспользоваться технологией NPOI. Скорость работы возрастает в разы, никоим образом не привязано к наличию excel и перенос алгоритма не займет много времени.


AV>>А как у него с макросами? у меня в книги их полно...а также формул и встроенных в листы картинок.


_>Насчет макросов и картинок ничего конкретного сказать не могу,с ними использовать библиотеку не приходилось.

_>Формулы работают.

Ок, спасибо. будем пробовать.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.