Форум по Delphi программированию

Delphi Sources



Вернуться   Форум по Delphi программированию > Все о Delphi > Технологии
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 25.03.2009, 16:31
WinnyThePooh WinnyThePooh вне форума
Прохожий
 
Регистрация: 16.02.2009
Сообщения: 31
Репутация: 10
Вопрос Как "отключиться" от Excel, запущеного как OLE?

Формирую отчет в Excel (в частности, 2000) через OLE-объект. По завершении формирования есть желание отключится от него и от сформированного файла (типа, пусть дальше сам(и) живе(у)т).
Пытаюсь так:
Код:
//Переменная
var
  XLApp: OLEVariant;
//Запускаем Excel
  XLApp:=CreateOleObject('Excel.Application');
//далее - работа
...
//в конце
  XLApp:=UnAssigned;
Ан нет! Пока не закрыта "порождающая" программа, Excel закрывается с ошибками, в памяти остаются болтаться процессы и т.п.
Попытка использовать XLApp.Free выдает ошибку, типа "этот метод низ-з-зя использовать с переменной типа Variant".
Имеется ли принципиальная возможность отцепится от порождающего процесса или проще описать как фичу в документации или посоветуйте - как быть?
Ответить с цитированием
  #2  
Старый 25.03.2009, 16:39
Аватар для Aristarh Dark
Aristarh Dark Aristarh Dark вне форума
Модератор
 
Регистрация: 07.10.2005
Адрес: Москва
Сообщения: 2,906
Версия Delphi: Delphi XE
Репутация: выкл
По умолчанию

Попробуй сделать:
Код:
XLApp:=Disconnect;
//а потом уже
XLApp:=UnAssigned;
__________________
Некоторые программисты настолько ленивы, что сразу пишут рабочий код.

Если вас наказали ни за что - радуйтесь: вы ни в чем не виноваты.
Ответить с цитированием
  #3  
Старый 25.03.2009, 16:55
WinnyThePooh WinnyThePooh вне форума
Прохожий
 
Регистрация: 16.02.2009
Сообщения: 31
Репутация: 10
Печаль Увы, немного не то...

Насколько я понимаю, Disconnect - метод при работе с COM-серверами, здесь же - OLE-объект.
По крайней мере предложенную Вами форму система не воспринимает.
Ответить с цитированием
  #4  
Старый 25.03.2009, 17:25
Аватар для Aristarh Dark
Aristarh Dark Aristarh Dark вне форума
Модератор
 
Регистрация: 07.10.2005
Адрес: Москва
Сообщения: 2,906
Версия Delphi: Delphi XE
Репутация: выкл
По умолчанию

Это потому что я фигню написал, нужно:
Код:
XLApp.Disconnect;
__________________
Некоторые программисты настолько ленивы, что сразу пишут рабочий код.

Если вас наказали ни за что - радуйтесь: вы ни в чем не виноваты.
Ответить с цитированием
  #5  
Старый 25.03.2009, 18:42
WinnyThePooh WinnyThePooh вне форума
Прохожий
 
Регистрация: 16.02.2009
Сообщения: 31
Репутация: 10
По умолчанию увы... не то

Не беспокойтесь, я и так сообразил
Но увы, как я Вам и писал в прежнем ответе: disconnect - метод COM-серверов.
При попытке слепить его к ссылке на объект OLE Automation (а именно его я пытаюсь применить) система выдает:
"Project ... raised exception class EOLEError with message 'Method 'disconnect' not supported by automation obect'". Т.е. метод явно не тот.
Увы, но и COM-серверами мне пока не удалось достичь успеха: пока не загасишь вызывающее приложение, Excel вываливается с ошибкой: "Инструкция по адресу 0х... обратилась к памяти по адресу 0х... Память не может быть 'read'". Причем адреса одинаковы - явно что-то слетает в указателях.
В общем, ж...
Кстати, в доступной литературе как-то тоже описываются случаи принудительного гашения OLE-объектов при закрытии приложений и нигде особо не описывается "отпускание в свободное плавание". Может это таки фича OLE'й и я зря пытаюсь её "исправить"?
Ответить с цитированием
  #6  
Старый 25.03.2009, 21:44
san-46 san-46 вне форума
Активный
 
Регистрация: 25.04.2008
Сообщения: 383
Репутация: 33
По умолчанию

Цитата:
Ан нет! Пока не закрыта "порождающая" программа, Excel закрывается с ошибками, в памяти остаются болтаться процессы и т.п.
Утверждение, не соответствующее действительности. "Порождающая" программа при использовании позднего связывания (как здесь: CreateOleObject) не "держит" COM сервер и никакого влияния после окончания работы на него не оказывает. Поэтому "отключения" от сервера не требуется. Если работа завершилась корректно, то "породившая" процесс программа может спокойно завершаться - Excel (если та же программа его не пристрелила) остается загруженным как отдельное приложение никак не связанное с вызвавшем приложением.

Процессы (Excel) остаются в памяти тогда (и только тогда), если во время вызова методов COM сервера Excel ПРОИСХОДИТ ошибка (неверные типы параметров, не в том месте вызван метод и т.д.; видов ошибок может быть тьма), а на момент ошибки интерфейс Excel скрыт и нет возможности корректно закрыть окно Excel'я.
Специально для таких случаев завершение работы с Excel в блоке except надо применять метод сервера Quit (к примеру, XLApp.Quit)

Если после экспорта из "порождающей" программы при "ручном" закрытии Excel происходит ошибка, то это глюки системы, поскольку (как было выше отмечено) клиентское приложение после окончания работы с COM сервером (корректно или с ошибкой) никак не может на него влиять. Правда, такое может произойти и тогда, когда приложение сделало какое-то количество ошибок при обращении к неверному диапазону ячеек в параметрах методов при экспорте данных.
Присвоение в конце работы вариантной переменной Unаssigned, которая ссылается на COM сервер, необходимо.
__________________
Не забывайте делать резервные копии
Ответить с цитированием
  #7  
Старый 26.03.2009, 11:26
WinnyThePooh WinnyThePooh вне форума
Прохожий
 
Регистрация: 16.02.2009
Сообщения: 31
Репутация: 10
Печаль Не понимаю...

Вот пример кода, аналогичного тому, что я использую:

Код:
unit Unit2;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ComObj, StdCtrls;

type
  TForm2 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    XLApp, XLWB, Sheet, Colum, shRange: OLEvariant;
  end;

var
  Form2: TForm2;
const
  xlCenter: integer= -4108;
  xlTop: integer= -4160;

implementation

{$R *.dfm}

procedure TForm2.Button1Click(Sender: TObject);
begin
   XLApp:=CreateOleObject('Excel.Application');
  XLApp.Visible:=True;
  XLWB:=XLApp.Workbooks.Add;
  XLWB.WorkSheets[1].Name:='Отчет';

  Colum:=XLWB.WorkSheets['Отчет'].Columns;
  Colum.Columns[1].ColumnWidth:=40;
  Colum.Columns[2].ColumnWidth:=20;
  Colum.Columns[3].ColumnWidth:=10;
  Colum.Columns[4].ColumnWidth:=20;

  Colum:=XLWB.WorkSheets['Отчет'].Rows;
  Colum.Rows[1].RowHeight:=80;

  Sheet:=XLWB.WorkSheets['Отчет'];
  Sheet.Cells[1,1]:='ОТЧЕТ';
  Sheet.Cells[1,1].Font.Size:=20;
  Sheet.Cells[1,1].Font.Bold:=True;
  Sheet.Cells[1,1].HorizontalAlignment:=xlCenter;
  Sheet.Cells[1,1].VerticalAlignment:=xlTop;
  shRange:=Sheet.Range['A1:D1'];
  shRange.select;
  shRange.MergeCells := True;

  //Включаем режим Print Prevew
  Sheet.PrintPreview;

  //Отцепляем переменные
  XLWB:=UnAssigned;
  XLApp:=UnAssigned;

end;

end.

Кнопка на форме. По кнопке вызывается Excel, в который транслируются команды ~VBA для формирования отчета.
Все отрабатывает нормально. Лист формируется.
При попытке закрыть Excel БЕЗ предварительного закрытия вызвавшей программы выдается ошибка, описанная мною выше, а потом еще выскакивает message с ещё более "странным" сообщением (см. приложенный jpg).
Что тут может происходить?
Изображения
Тип файла: jpg ExcelErrorMessage01.jpg (38.2 Кбайт, 10 просмотров)
Ответить с цитированием
  #8  
Старый 26.03.2009, 11:53
san-46 san-46 вне форума
Активный
 
Регистрация: 25.04.2008
Сообщения: 383
Репутация: 33
По умолчанию

Приведенный код (один-к-одному, ничего не исправляя) проверил на своей машине. Все работает как и задумано, без ошибок.
После закрытия окна предварительного просмотра, Excel закрывается без ошибок, и без закрытия программы, и после ее закрытия (что, собственно, и подтверждает то о чем я говорил раньше).
В коде нет перехвата exceptions, но это дело наживное.
А вот что подразумевается под "транслируются команды ~VBA" - это не понятно. Если приведенный код не весь (а где-то в нем еще есть "трансляция команд..."), то и проверить в чем ошибка не получится.
Если работает только приведенный код, то причину ошибки надо искать на уровне установленного MS Office.

Кстати, переменые (xlCenter, ...) можно не объявлять, а подключить модуль, где они есть (любой из тех, что находятся в папке Ocx\Servers ExcelXP, Excel2000 и пр.)
__________________
Не забывайте делать резервные копии
Ответить с цитированием
  #9  
Старый 26.03.2009, 18:16
WinnyThePooh WinnyThePooh вне форума
Прохожий
 
Регистрация: 16.02.2009
Сообщения: 31
Репутация: 10
Восклицание про код...

Мой "боевой" код, ест-но, ширше
Но я прислал код макета, использующего те же технологии, который as is сваял и запускал на своей машине с аналогичными бовому результатом...
Что касается установленного офиса - похоже, Вы правы, по крайней мере на паре других машин с другим M$ Office 2007 vs 2000 на первой, таких проблем не наблюдается.
С одной стороны это "радует", с другой стороны - пугает "неуправляемостью" процесса, что, свойственно продуктам некоторых фирм... Т.е. непоняты ПРИЧИНЫ того или иного поведения.
Ответить с цитированием
  #10  
Старый 26.03.2009, 19:45
WinnyThePooh WinnyThePooh вне форума
Прохожий
 
Регистрация: 16.02.2009
Сообщения: 31
Репутация: 10
Восклицание небольшое добавление

...а вот замена Office2000 на Office2003 на машине с ОС W2k (SP4) никак не поменяла раскладец - ошибка вылетает и все тут. Так что, похоже, имеем проблему где-то на уровне ОС и версий OLE-движка (на машинах, где нет ошибки - WinXP). Или я не прав?
Кстати, из странностей поведения связки Delphi-Excel на этой машине (с W2K) хочется еще отметить следующее: потребность в "руссификации" символов для колонтитулов: на других машинах работает &D (дата), &P из &N (станица из страниц), а здесь требуется ставить &Д и &С из &К... Чудеса, да и только... Может кто знает "глобальное" название этих констант, которые не зависит от версий?
Ответить с цитированием
  #11  
Старый 26.03.2009, 20:04
san-46 san-46 вне форума
Активный
 
Регистрация: 25.04.2008
Сообщения: 383
Репутация: 33
По умолчанию

Может и прав. Кто его разберет этого мелкомягкого.
К MS Office 2000 есть пара сервис пак'ов (аж целых два). Помню, что после установки этих обновлений ошибки у меня исчезали. Не точно такие, но как-то очень уж похожие.

Судя по макросам из MS Office 2003 подстановочные константы должны быть на латыни (к примеру, Sheet.PageSetup.LeftHeader = "&P"), но, опять же, поди разберись чего требуется в разных офисных системах.
__________________
Не забывайте делать резервные копии
Ответить с цитированием
  #12  
Старый 26.03.2009, 20:10
WinnyThePooh WinnyThePooh вне форума
Прохожий
 
Регистрация: 16.02.2009
Сообщения: 31
Репутация: 10
По умолчанию про символику Office

по макросам и у меня все на латыни, но после долгих неудачных попыток с нею задумалось прочитать обратно эти константы с листа Excel в Delphi - и с удивлением увидел кириллицу!
Ответить с цитированием
Ответ


Delphi Sources

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 11:15.


 

Сайт

Форум

FAQ

RSS лента

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2023

ВКонтакте   Facebook   Twitter