powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / TExcelApplication
25 сообщений из 27, страница 1 из 2
TExcelApplication
    #39586578
Здравствуйте!
Решил попробовать работать с Excel при помощи TExcelApplication.
Возникла проблема с выходом из Excel. Если завершать Excel из программы, то всё хорошо, а если показать Excel, закрыть программу, а потом закрыть Excel, то процесс остаётся в памяти. Как правильно освободить переменные/интерфейсы, чтобы сформированный файл остался открытым и после закрытия самого файла процесс убивался?
Делаю примерно так
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
var
  XL: TExcelApplication;
begin
  // запускаем новый экземпляр Excel'я
  XL := TExcelApplication.Create(nil);
  try
    XL.ConnectKind := ckNewInstance;
    XL.Connect; // подключение
    XL.AutoQuit := False; // по умолчанию это свойство True только в unit ExcelXP
    XL.Visible[lcid] := True;
    // здесь работаем с Excel'ем
  finally
    // отсоединяемся
    XL.UserControl := True; // отдадим управление пользователю
    XL.Quit; // закрыть Excel
    XL.Disconnect;
    FreeAndNil(XL);
  end;
...
Рейтинг: 0 / 0
TExcelApplication
    #39586581
Фотография wadman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Михаил Евгеньевич
Код: pascal
1.
FreeAndNil(XL);


Это-то зачем?

Попробуй
Код: pascal
1.
XL := Unassigned;
...
Рейтинг: 0 / 0
TExcelApplication
    #39586582
А ещё вопрос, есть ли смысл в раннем связывании? Или не заморачиваться и сделать через OleObj?
с OleObj я более-менее умею работать. Там уже всё понятно.
...
Рейтинг: 0 / 0
TExcelApplication
    #39586583
wadman,

Это не работает. Так я пробовал.
Код: pascal
1.
XL := Unassigned;


Несоответствие типов Variant и TExcelApplication.
...
Рейтинг: 0 / 0
TExcelApplication
    #39586585
Если сделать
Код: pascal
1.
XL.Disconnect;


то Excel закрывается.
...
Рейтинг: 0 / 0
TExcelApplication
    #39586613
Фотография DarkMaster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Михаил Евгеньевич,

В каком-то FAQ нашел.

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
var
  XL: TExcelApplication;
begin
  // запускаем новый экземпляр Excel'я
  XL := TExcelApplication.Create(nil);
  try

    XL.ConnectKind := ckNewInstance;
    XL.Connect; // подключение
    XL.AutoQuit := False; // по умолчанию это свойство True только в unit ExcelXP
    XL.Visible[lcid] := True;
    // здесь работаем с Excel'ем
  finally
    // отсоединяемся

    XL.UserControl := True; // отдадим управление пользователю
    XL.Quit; // закрыть Excel
    XL.Disconnect;
    FreeAndNil(XL);
  end;
...
Рейтинг: 0 / 0
TExcelApplication
    #39586614
Фотография DarkMaster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DarkMaster,

Тьфу ты, в один и тот же FAQ смотрели :D
...
Рейтинг: 0 / 0
TExcelApplication
    #39586671
Перечитал, что я написал.
У меня просто проект на работе, взял пример из интернета.
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
var
  XL: TExcelApplication;
begin
  // запускаем новый экземпляр Excel'я
  XL := TExcelApplication.Create(nil);
  try
    XL.ConnectKind := ckNewInstance;
    XL.Connect; // подключение
    XL.AutoQuit := False; // по умолчанию это свойство True только в unit ExcelXP
    XL.Visible[lcid] := False;
    // здесь работаем с Excel'ем
    XL.Visible[lcid] := True;
    // Тут нужно как-то отвязаться от Excel, иначе процесс Excel можно будет убить только через диспетчер задач.


Я, конечно, уже придумал "костыль", но не хочу его применять.
...
Рейтинг: 0 / 0
TExcelApplication
    #39586866
Ещё раз здравствуйте!
Ситуация такая: переделал на позднее связывание.
RunExcel:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
 if CheckExcelInstall then
      begin
        exc:=CreateOleObject(ExcelApp);
        exc.ErrorCheckingOptions.BackgroundChecking:=BackgroundChecking;
        exc.ErrorCheckingOptions.InconsistentFormula:=InconsistentFormula;
        exc.ScreenUpdating:=ScreenUpdating;
        exc.DisplayAlerts:=EnableAlerts;
        exc.Visible:=Visible;
        Result:=True;
      end


Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
function StopExcel(var exc:OLEVariant):boolean;
begin
  try
    exc.DisplayAlerts:=False;
    exc.WorkBooks.Close;
    exc.DisplayAlerts:=True;
    exc.ErrorCheckingOptions.BackgroundChecking:=True;
    exc.ErrorCheckingOptions.InconsistentFormula:=True;
    exc.ScreenUpdating:=True;
    exc.Application.quit;
    exc:=Unassigned;
    Result:=True;
  except
    Result:=False;
  end;
end;



Теперь, если мне надо показать Excel и оставить его пользователю на растерзание, я делаю
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
function ShowExcel(var exc:OLEVariant):boolean;
begin
  result:=true;
  try
    exc.DisplayAlerts:=True;
    exc.ErrorCheckingOptions.BackgroundChecking:=True;
    exc.ErrorCheckingOptions.InconsistentFormula:=True;
    exc.ScreenUpdating:=True;
    exc.visible:=True;
  except
    result:=false;
  end;
end;


и
Код: pascal
1.
Exc:=Unassigned;



И это работает. При закрытии Excel'я пользователем, процесс убивается.
НО!
Теперь непонятки с программным завершением.
Пока я считываю данные в вариантный массив, записываю данные в ячейки всё хорошо.
Как только я записываю данные в Excel из вариантного массива - всё. После вызова StopExcel процесс остаётся в памяти.
Код: pascal
1.
2.
3.
4.
DevInfo:=VarArrayCreate([1,1,1,5],varVariant);
for j := 1 to 5 do
  DevInfo[3,j]:=DiaArr[i,j];
WS.Range[WS.Cells[1,n],WS.Cells[1,n+4]].Value:=DevInfo;
...
Рейтинг: 0 / 0
TExcelApplication
    #39586869
В конце обшибся, на самом деле так:
Код: pascal
1.
2.
3.
4.
DevInfo:=VarArrayCreate([1,1,1,5],varVariant);
for j := 1 to 5 do
  DevInfo[1,j]:=DiaArr[i,j];
WS.Range[WS.Cells[1,n],WS.Cells[1,n+4]].Value:=DevInfo;
...
Рейтинг: 0 / 0
TExcelApplication
    #39586874
Михаил Евгеньевич,

Причем, если сделать
Код: pascal
1.
2.
ShowExcel(excel);
excel:=Unassigned;


То Excel вполне закрывается пользователем.
...
Рейтинг: 0 / 0
TExcelApplication
    #39588011
Проблема решена.
Не используйте это:
Код: pascal
1.
WS.Range[WS.Cells[1,n],WS.Cells[1,n+4]].Value:=DevInfo;



Используйте это:
Код: pascal
1.
WS.Range['A'+inttostr(n)+':A'+inttostr(n+4)].Value:=DevInfo;



Сам пользуюсь модернизированной функцией перевода адресов R1C1 в A1. Взял в инете, добавил рекурсию.

Может кому пригодится:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
function xlRCtoA1(const ARow, ACol: Integer;
  RowAbsolute: Boolean = False;
  ColAbsolute: Boolean = False): String;
const
  A1 = Ord('A') - 1;  // номер "A" минус 1 (65 - 1 = 64)
  AZ = Ord('Z') - A1; // кол-во букв в англ. алфавите (90 - 64 = 26)
var
  t, m: Integer;
  S: String;
begin
  // номер колонки
  t := ACol div AZ; // целая часть
  m := (ACol mod AZ); // остаток?
  if m = 0 then
    Dec(t);
  if t > 0 then
    S := xlRCtoA1(0,t)
  else
    S := '';
  if m = 0 then
    t := AZ
  else
    t := m;
  S := S + Char(A1 + t);
  // весь адрес
  if ColAbsolute then S := '$' + S;
  if RowAbsolute then S := S + '$';
  if ARow>0 then
    S := S + IntToStr(ARow);
  Result := S;
end;
...
Рейтинг: 0 / 0
TExcelApplication
    #39588060
Соколинский Борис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Михаил Евгеньевич,
Не пользуйтесь ни то, ни другое.
Откройте для себя Offset и Resize.
...
Рейтинг: 0 / 0
TExcelApplication
    #39588072
Соколинский Борис,

А с этого момента поподробней.
...
Рейтинг: 0 / 0
TExcelApplication
    #39588075
Соколинский Борис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Михаил ЕвгеньевичА с этого момента поподробней. Подробнее ответит справка.
Примерно:
Код: pascal
1.
WS.Cells[1, n].Resize[1, 4].Value:=DevInfo;
...
Рейтинг: 0 / 0
TExcelApplication
    #39588105
Соколинский Борис,

Ok! Спс. Попробую.
...
Рейтинг: 0 / 0
TExcelApplication
    #39588134
В связи с проблемами вставки диапазона ячеек при позднем связывании опять поднимаю вопрос о завершении процесса EXCEL.EXE после закрытия, запущенного программно, excel'я.

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
var
  XL: TExcelApplication;
begin
  // запускаем новый экземпляр Excel'я
  XL := TExcelApplication.Create(nil);
  try
    XL.ConnectKind := ckNewInstance;
    XL.Connect; // подключение
    XL.AutoQuit := True; // по умолчанию это свойство True только в unit ExcelXP
    XL.Visible[lcid] := True;
    // Тут нужно как-то отвязаться от Excel, иначе процесс Excel можно будет убить только через диспетчер задач.
    //XL.Disconnect закрывает excel
...
Рейтинг: 0 / 0
TExcelApplication
    #39589009
Соколинский Борис,

Подскажите, пожалуйста, почему
Код: pascal
1.
2.
xlRange:=WS.Range[sAddress].Offset[6,0];
xlRange:=xlRange.Offset[0,3];



Не идентично
Код: pascal
1.
xlRange:=WS.Range[sAddress].Offset[6,3];


В первом случае работает как задумано, т.е. диапазон смещается на 6 вниз и 3 вправо, а во втором случае на 6 вниз и 11 вправо.
...
Рейтинг: 0 / 0
TExcelApplication
    #39589022
Соколинский Борис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Михаил Евгеньевич, не может такого быть.
Проверяй
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
program Project1;
{$APPTYPE CONSOLE}
uses
  SysUtils, comobj, ActiveX;

const sAddress='A1:B2';
var
  XL, R: OleVariant;

begin
  CoInitialize(nil);
  XL:=CreateOleObject('Excel.Application');
  try
    R:= XL.WorkBooks.Add.Sheets[1].Range[sAddress];
    Writeln('One step: ',  R.Offset[6,3].Address);
    Writeln('Two steps: ', R.Offset[6,0].Offset[0,3].Address);
    Writeln('Press enter');
    Readln;
  finally
    XL.quit;
  end;
end.
...
Рейтинг: 0 / 0
TExcelApplication
    #39589023
Михаил Евгеньевич,

sAddress='$A$1'
...
Рейтинг: 0 / 0
TExcelApplication
    #39589028
Может быть дело в объединённых ячейках...
У меня А1:H1 объединены.
...
Рейтинг: 0 / 0
TExcelApplication
    #39589035
Соколинский Борис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Михаил Евгеньевич, так бы сразу и написал.
С объединенными ячейками может быть что угодно, там интуитивная логика почти не работает.
...
Рейтинг: 0 / 0
TExcelApplication
    #39589039
Соколинский Борис,
Спасибо. Буду делать в два шага.
...
Рейтинг: 0 / 0
TExcelApplication
    #39589713
Соколинский Борис,

Таки я не могу разобраться почему Excel не закрывается (Процесс висит в памяти).
Есть две функции:
1. Показывает Excel.
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
function ShowExcel(var exc:Variant):boolean;
begin
  result:=true;
  try
    exc.DisplayAlerts:=True;
    exc.ErrorCheckingOptions.BackgroundChecking:=True;
    exc.ErrorCheckingOptions.InconsistentFormula:=True;
    exc.ScreenUpdating:=True;
    exc.visible:=True;
  except
    result:=false;
  end;
end;


2. Закрывает Excel
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
function StopExcel(var exc:Variant):boolean;
begin
  try
    exc.DisplayAlerts:=False;
    exc.WorkBooks.Close;
    exc.DisplayAlerts:=True;
    exc.ErrorCheckingOptions.BackgroundChecking:=True;
    exc.ErrorCheckingOptions.InconsistentFormula:=True;
    exc.ScreenUpdating:=True;
    exc.Application.quit;
    exc:=Unassigned;
    Result:=True;
  except
    Result:=False;
  end;
end;



Так вот, если после выполнения одних и тех же операций над Excel'ем выполнить
Код: pascal
1.
2.
3.
ShowExcel(excel);
MessageDlg('Внимание!'+#13+'Для повторной обработки закройте полученный файл!',mtWarning,[mbOK],0);
excel:=Unassigned;


То Excel можно закрыть и процесс убивается.
А если сделать
Код: pascal
1.
StopExcel(excel);


то процесс остаётся...

Что я не правильно делаю?
В процедуре работы с Excel'ем все Variant переменные (а они локальные) для полноты эксперимента в конце процедуры "обнуляю" (:=Unassigned)
...
Рейтинг: 0 / 0
TExcelApplication
    #39589719
Соколинский Борис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Михаил Евгеньевич,
Вкратце - проблема в том, что компилятор создает скрытую интерфейсную ссылку.
Оберни CreateOleObject в процедуру с out-параметром.
...
Рейтинг: 0 / 0
25 сообщений из 27, страница 1 из 2
Форумы / Delphi [игнор отключен] [закрыт для гостей] / TExcelApplication
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]