|
|
Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
|
Опции темы | Поиск в этой теме | Опции просмотра |
#1
|
|||
|
|||
Как "отключиться" от Excel, запущеного как OLE?
Формирую отчет в Excel (в частности, 2000) через OLE-объект. По завершении формирования есть желание отключится от него и от сформированного файла (типа, пусть дальше сам(и) живе(у)т).
Пытаюсь так: Код:
//Переменная var XLApp: OLEVariant; //Запускаем Excel XLApp:=CreateOleObject('Excel.Application'); //далее - работа ... //в конце XLApp:=UnAssigned; Попытка использовать XLApp.Free выдает ошибку, типа "этот метод низ-з-зя использовать с переменной типа Variant". Имеется ли принципиальная возможность отцепится от порождающего процесса или проще описать как фичу в документации или посоветуйте - как быть? |
#2
|
||||
|
||||
Попробуй сделать:
Код:
XLApp:=Disconnect; //а потом уже XLApp:=UnAssigned; Некоторые программисты настолько ленивы, что сразу пишут рабочий код. Если вас наказали ни за что - радуйтесь: вы ни в чем не виноваты. |
#3
|
|||
|
|||
Увы, немного не то...
Насколько я понимаю, Disconnect - метод при работе с COM-серверами, здесь же - OLE-объект.
По крайней мере предложенную Вами форму система не воспринимает. |
#4
|
||||
|
||||
Это потому что я фигню написал, нужно:
Код:
XLApp.Disconnect; Некоторые программисты настолько ленивы, что сразу пишут рабочий код. Если вас наказали ни за что - радуйтесь: вы ни в чем не виноваты. |
#5
|
|||
|
|||
увы... не то
Не беспокойтесь, я и так сообразил
Но увы, как я Вам и писал в прежнем ответе: 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
|
|||
|
|||
Цитата:
Процессы (Excel) остаются в памяти тогда (и только тогда), если во время вызова методов COM сервера Excel ПРОИСХОДИТ ошибка (неверные типы параметров, не в том месте вызван метод и т.д.; видов ошибок может быть тьма), а на момент ошибки интерфейс Excel скрыт и нет возможности корректно закрыть окно Excel'я. Специально для таких случаев завершение работы с Excel в блоке except надо применять метод сервера Quit (к примеру, XLApp.Quit) Если после экспорта из "порождающей" программы при "ручном" закрытии Excel происходит ошибка, то это глюки системы, поскольку (как было выше отмечено) клиентское приложение после окончания работы с COM сервером (корректно или с ошибкой) никак не может на него влиять. Правда, такое может произойти и тогда, когда приложение сделало какое-то количество ошибок при обращении к неверному диапазону ячеек в параметрах методов при экспорте данных. Присвоение в конце работы вариантной переменной Unаssigned, которая ссылается на COM сервер, необходимо. Не забывайте делать резервные копии |
#7
|
|||
|
|||
Не понимаю...
Вот пример кода, аналогичного тому, что я использую:
Код:
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). Что тут может происходить? |
#8
|
|||
|
|||
Приведенный код (один-к-одному, ничего не исправляя) проверил на своей машине. Все работает как и задумано, без ошибок.
После закрытия окна предварительного просмотра, Excel закрывается без ошибок, и без закрытия программы, и после ее закрытия (что, собственно, и подтверждает то о чем я говорил раньше). В коде нет перехвата exceptions, но это дело наживное. А вот что подразумевается под "транслируются команды ~VBA" - это не понятно. Если приведенный код не весь (а где-то в нем еще есть "трансляция команд..."), то и проверить в чем ошибка не получится. Если работает только приведенный код, то причину ошибки надо искать на уровне установленного MS Office. Кстати, переменые (xlCenter, ...) можно не объявлять, а подключить модуль, где они есть (любой из тех, что находятся в папке Ocx\Servers ExcelXP, Excel2000 и пр.) Не забывайте делать резервные копии |
#9
|
|||
|
|||
про код...
Мой "боевой" код, ест-но, ширше
Но я прислал код макета, использующего те же технологии, который as is сваял и запускал на своей машине с аналогичными бовому результатом... Что касается установленного офиса - похоже, Вы правы, по крайней мере на паре других машин с другим M$ Office 2007 vs 2000 на первой, таких проблем не наблюдается. С одной стороны это "радует", с другой стороны - пугает "неуправляемостью" процесса, что, свойственно продуктам некоторых фирм... Т.е. непоняты ПРИЧИНЫ того или иного поведения. |
#10
|
|||
|
|||
небольшое добавление
...а вот замена Office2000 на Office2003 на машине с ОС W2k (SP4) никак не поменяла раскладец - ошибка вылетает и все тут. Так что, похоже, имеем проблему где-то на уровне ОС и версий OLE-движка (на машинах, где нет ошибки - WinXP). Или я не прав?
Кстати, из странностей поведения связки Delphi-Excel на этой машине (с W2K) хочется еще отметить следующее: потребность в "руссификации" символов для колонтитулов: на других машинах работает &D (дата), &P из &N (станица из страниц), а здесь требуется ставить &Д и &С из &К... Чудеса, да и только... Может кто знает "глобальное" название этих констант, которые не зависит от версий? |
#11
|
|||
|
|||
Может и прав. Кто его разберет этого мелкомягкого.
К MS Office 2000 есть пара сервис пак'ов (аж целых два). Помню, что после установки этих обновлений ошибки у меня исчезали. Не точно такие, но как-то очень уж похожие. Судя по макросам из MS Office 2003 подстановочные константы должны быть на латыни (к примеру, Sheet.PageSetup.LeftHeader = "&P"), но, опять же, поди разберись чего требуется в разных офисных системах. Не забывайте делать резервные копии |
#12
|
|||
|
|||
про символику Office
по макросам и у меня все на латыни, но после долгих неудачных попыток с нею задумалось прочитать обратно эти константы с листа Excel в Delphi - и с удивлением увидел кириллицу!
|