Excel - чистка связей
работаю с оным через OLE, создаю там с помощью всяких Оле процедур типа open, работаю с Workbooks, WorkSheets, в конце работы делаю SaveAs и для Workbooks вызываю Close, затем для всех переменных делаю .Clear().По идее память должна чиститься, однако появляются( по крайней мере в двухтысячных виндах) бесхозные процессы Excel.exe.При чем каждый раз, ессно, как используется работа с Екселем.И так эти процессы плодятся и плодятся.Подскажите, как их подчищать.
Это я надеюсь мой последний вопрос по Екселю - перехожу на Ворд(шутка)(про Ворд шутка).
С уважением, Я.
Что, никто ничего не знает??Неужели только я с такой проблемой столкнулся?
У меня такое было, правда только когда вследствие ошибки у меня не закрывался Excel. Quit ставить пробовал??? После окончания работы закрывай Excel и очищай все переменные.
А где его ставить? Запость плз кусок кода а?Просто во всех примерах работы с Екселем через ОЛЕ вызывается для Воркбуксов ОЛЕ процедура Close.Я думаю, что как раз Quit мне и не хватает!!!!!
К сожалению Билдера сейчас под рукой нет, поэтому перевожу с Delphi.
Что-то типа этого.
XlApp=createoleobject('Excel.application');
Wbooks=XlApp.OlePropertyGet(workbooks);
Wbooks.Exec(Procedure("Add"));
Wbook=Wbooks.OlePropertyGet("item",1);
XlApp.OlePropertySet("Visible", 1);
...
XlApp.Exec(Procedure("Quit"));
XlApp=Unassigned;
Ексель закрывает - процесс жив. Посмотри плз как у тебя в билдере работает и выложи код!!!!
Я же говорю билдера сейчас нет, на дельфях сляпал - всё работает. Порылся в старых кодах, отрыл следующее:
Если отбросить всё лишнее то:
ExcelApp=CreateOleObject("Excel.Application");
ExcelApp.OlePropertySet("Visible",true);
...
Ну и соответственно закрытие
ExcelApp.OleProcedure("Quit");
Если сделаешь
ExcelApp=unassigned;
то процесс должен пропасть, если не сделаешь,
пропадёт когда закроешь своё приложение.
Variant App;
AnsiString Pass = "C:\\Prixod\\";
AnsiString File = Pass+"p"+Nomer->Text+".xls";
App=Variant::CreateObject("Excel.Application");
App.OlePropertyGet("WorkBooks").OleProcedure("open",File.c_str());
App.OlePropertyGet("WorkBooks",1).OleProcedure("Close");
App.OleProcedure("Quit");
App = Unassigned;
вот так выглядит пример.После этого все закрывается, но процесс живет.
Не работает.увы.может в дельфи и пашет, но под билдерем все равно процессы живут даже после закрытия приложения.
Variant App;
AnsiString Pass = "C:\\Prixod\\";
AnsiString File = Pass+"p"+Nomer->Text+".xls";
App=Variant::CreateObject("Excel.Application");
App.OlePropertyGet("WorkBooks").OleProcedure("open",File.c_str());
App.OlePropertyGet("WorkBooks",1).OleProcedure("Close");
App.OleProcedure("Quit");
App = Unassigned;
вот так выглядит пример.После этого все закрывается, но процесс живет.
Ну не знаю, старые билдеровские коды из которых я это выдёргивал вроде работали без проблем. Тогда если не получается закрыть процесс нормально, то можно его прибить руками. Про это где-то чуть ниже топик был.
Ексель юзается на каждом шагу и каждый раз сканить список процессов и убивать его, тормозить же будет.
А может ты все таки попробуешь а? ))
И код примера выложишь)))
вручную как то оно не прикольно, у меня
Ексель юзается на каждом шагу и каждый раз сканить список процессов и убивать его, тормозить же будет.
А может ты все таки попробуешь а? ))
И код примера выложишь)))
Глюк у тебя какой-то...
Вот тебе пример
здесь ексель создается
void __fastcall TForm1::Button1Click(TObject *Sender)
{
V = Variant::CreateObject("Excel.Application");
}
здесь убивается
void __fastcall TForm1::Button2Click(TObject *Sender)
{
V.OleFunction("Quit");
V = Unassigned;
}
только что проверил. Все работает и убивается
Твой код должен работать точно так же(у тебя и написано тоже самое)
У тебя не Вин98?
Знаешь что .. возми перезагрузи винду, проверь в списке процессов нет ли там ексела, запусти его вручную, потом поделай в нем чего-нить и закрой. А потом опять проверь список процессов на наличие там ексел.
V = Variant::CreateObject("Excel.Application");
не создает процесс EXCEL.exe,
этот процесс создает
App.OlePropertyGet("WorkBooks").OleProcedure("open",File.c_str());
Вот после этого и делаю Quit и Unassigned, однако процесс жив.
Проверь меня.
Позволю себе заметить, что
V = Variant::CreateObject("Excel.Application");
не создает процесс EXCEL.exe,
этот процесс создает
App.OlePropertyGet("WorkBooks").OleProcedure("open",File.c_str());
Вот после этого и делаю Quit и Unassigned, однако процесс жив.
Проверь меня.
Ты не прав.
A что по твоему CreateObject в данном случае создает?
Как раз процесс создает CreateObject(). Правда, если процесс EXCEL.exe уже существует, то новый не создается, а используется существующий.
Вообще как работает этот механизм? При вызове механизма использующего OLE в системе проверяется, существует ли требуемый объект (в данном случае экземпляр ЕКСЕЛ). Если его нет, то он создается (запускается ексел) и внутренний счетчик увеличивается на 1. При каждом новом запросе соединения(многократный вызов CreateObject одного и тогоже объекта Variant не считается новым запросом) значение внутреннего счетчика увеличивается на 1.
А теперь как это удаляется. При разрыве каждого соединия этот внутренний счетчик уменьшается на 1. Как только значение этого счетчика станет равным 0, объект сервера OLE (в нашем случае ЕКСЕЛ) удаляется АВТОМАТИЧЕСКИ системой.
например если есть такой код
V = Variant::CreateObject("Excel.Application");
V.OlePropertyGet("WorkBooks").OleProcedure("open", "test.xls");
V.OlePropertySet("Visible", true);
и следом мы делаем
V = Variant::CreateObject("Excel.Application");
то действительно будет еще одно соединение
и при удалении
V = Unassigned;
или
V.Close();
удалится только последний экземпляр, а один так и останется даже после завершения приложения
V = Variant::CreateObject("Excel.Application");
по крайней мере у меня.
К тому же если ты сделашь
V.OlePropertySet("Visible", true);
ничего не произойдет.
Я думаю, что после КреейтОбжект создается ВНУТРЕННИЙ объект, и только после
V.OlePropertyGet("WorkBooks").OleProcedure("open", "test.xls");
запускается процесс EXCEL.exe
Проверь - вставь в функцию одну строчку
V = Variant::CreateObject("Excel.Application");
а потом загляни в Task Manager - процесса нет,
Проверь - в списке процессов НЕ ПОЯВЛЯЕТСЯ EXCEL.exe после
V = Variant::CreateObject("Excel.Application");
по крайней мере у меня.
К тому же если ты сделашь
V.OlePropertySet("Visible", true);
ничего не произойдет.
Я думаю, что после КреейтОбжект создается ВНУТРЕННИЙ объект, и только после
V.OlePropertyGet("WorkBooks").OleProcedure("open", "test.xls");
запускается процесс EXCEL.exe
Проверь - вставь в функцию одну строчку
V = Variant::CreateObject("Excel.Application");
а потом загляни в Task Manager - процесса нет,
Блин!!!! Наконец я понял где собака порылась...
ты сам запутался и всех запутал.
естественно если написать функцию
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Variant V = Variant::CreateObject("Excel.Application");
}
то после ее вызова в списке процессов ексела не будет!!!!!!!!! Потому что его действительно уже нет. Переменная объявлена локально ведь. В функции ексель создался и сразу убился. Если ты обЪявишь переменную не в теле функции, а в объявлении класса, то ексель создастся и останется в списке процессов.
Естественно что если функция имеет нечто типа
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Variant V = Variant::CreateObject("Excel.Application");
V.OlePropertyGet("WorkBooks").OleProcedure("open", "test.xls");
V.OlePropertySet("Visible", true);
}
то после ее работы на экране останется открытый в экселе файл, хотя через переменную V управлять ты им уже не сможешь
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Variant V = Variant::CreateObject("Excel.Application");
V.OlePropertyGet("WorkBooks").OleProcedure("open", "test.xls");
V.OlePropertySet("Visible", true);
V.OleFunction("Quit");
V = Unassigned;
}
- процесс EXCEL.exe все равно жив(локальность здесь соблюдена - переменная создается в функции и в ней же убивается).Объясни мне, ПОЧЕМУ ПРОЦЕСС ЭТОТ *?:%%:ЫЙ ЖИВЕТ???? )))))))(извини, накопилось).
Добавляем в твою функцию Quit и Unassigned
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Variant V = Variant::CreateObject("Excel.Application");
V.OlePropertyGet("WorkBooks").OleProcedure("open", "test.xls");
V.OlePropertySet("Visible", true);
V.OleFunction("Quit");
V = Unassigned;
}
- процесс EXCEL.exe все равно жив(локальность здесь соблюдена - переменная создается в функции и в ней же убивается).Объясни мне, ПОЧЕМУ ПРОЦЕСС ЭТОТ *?:%%:ЫЙ ЖИВЕТ???? )))))))(извини, накопилось).
Ты будешь смеяться, но нет у меня никакого процесса Ексел после такой функции. Сделай програмку с одной этой функцией и проверь. Если не делать Quit, то действительно остается висеть. Проверил и в XP и в W2000 с Excel97 и Excel2002
процесс может остаться вот в каком случае
void __fastcall TForm1::Button1Click(TObject *Sender)
{
V = Variant::CreateObject("Excel.Application");
V.OlePropertyGet("WorkBooks").OleProcedure("open", "test.xls");
V.OlePropertySet("Visible", true);
}
void __fastcall TForm1::Button1Click(TObject *Sender)
{
V.OleFunction("Quit");
V = Unassigned;
}
если открывать файл одной функцией, а закрывать другой. Тогда, если первую функцию вызвать 2 раза без вызова второй функции, то ексель созданый при первом вызове останется висеть
давно видел ваше сообщение про Excel, все не было времени прочитать, если воспрос остается открыт рекомендую использовать TXLSReadWriteII компонент, он не дает всю функциональность Excel, но почти всю дает и заморочки стремяться к нулю, поищите в нете(в стандартную поставку билдера он не входит). Просто я сам много работаю над вопросом работы с Excel97 под win98 и сталкнулся с проблемой висячих хвостов в памяти, так вот я почти полгода искал ответ и пришел к выводу что для 98 виндов проблема не решаема простыми средствами (утечка памяти происходит где-то внутри виндов и очень глубоко, внутри типа Variant, и это спорно и точное выяснение потребует много времени), может вам данный компонент пригодится, особенно если вам нужно работать с тысячами и более записей на лист excel. Да, чуть не забыл, для 2000 виндов подобной проблемы нет(сам не пробовал, но в группах на гугле borland.cppbuilder.XXX так пишут импортные программеры в один голос), и для билдера все сделано очень грамотно, так что как вариант решения проблемы, поставьте Excel2k и соответствующий набор билдера и все пашет на ура, у меня просто начальный набор данных поставлялся именно в Excel97 и выбирать не приходилось.
Я файл брал старый, сделанный в 97 Екселе, но работаю под 2000 винды и соответсвенно 2002 Ексель. Никаких ошибок при просмотре не выдавал, единственно не закрывал из программы.Я взял, создал новый файл - туда переписал данные и начал работать с новым, все закрывается - без Unassigned. Фуф, еще раз огромное спасибо всем.Отмучался.А то уже совсем шарики за ролики заехали с этим багом!!!!