Delphi 7, Excel, CreateOleObject
От: Baskak Россия  
Дата: 06.11.15 13:15
Оценка:
Здравствуйте.

Мучаюсь больше полдня, эта тема от меня далека, но вот потребовалось.
Требуется из программы (на Delphi 7) создать документ Excel из шаблона, заполнить, и оставить открытым (отключиться от него).

// uses ComObj;
procedure TForm1.Button1Click(Sender: TObject);
var
  x: OleVariant;
begin
  x := CreateOleObject('Excel.Application');
  x.Visible := true;
  // создание и заполнение документа
  x := Unassigned; // Excel закрывается
end;


Проблема в том, что как только переменная теряет свое значение — Excel автоматически закрывается.
Как сделать чтобы он не закрывался? Может есть свойство какое типа AutoClose, которое нужно := false ?
Отредактировано 06.11.2015 13:18 Baskak . Предыдущая версия .
Re: Delphi 7, Excel, CreateOleObject
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 06.11.15 13:38
Оценка:
Здравствуйте, Baskak, Вы писали:


B>Проблема в том, что как только переменная теряет свое значение — Excel автоматически закрывается.

B>Как сделать чтобы он не закрывался? Может есть свойство какое типа AutoClose, которое нужно := false ?

При достижении ссылок равных нулю Ком сервер уничтожается. Решение держать ссылку в глобальных переменных.
Либо запусти Эксель и попробуй подключиться к нему через GetActiveOleObject
и солнце б утром не вставало, когда бы не было меня
Re[2]: Delphi 7, Excel, CreateOleObject
От: Baskak Россия  
Дата: 06.11.15 13:44
Оценка: +1
Здравствуйте, Serginio1, Вы писали:

S>При достижении ссылок равных нулю Ком сервер уничтожается. Решение держать ссылку в глобальных переменных.

Пользователь может закрыть программу после формирования документа, тут документ и закроется. Нельзя.

S>Либо запусти Эксель и попробуй подключиться к нему через GetActiveOleObject

Некрасиво. Можно не тот Excel подцепить. Да и не факт что его не закроет.
Re[3]: Delphi 7, Excel, CreateOleObject
От: BlackEric http://black-eric.lj.ru
Дата: 06.11.15 14:03
Оценка:
Здравствуйте, Baskak, Вы писали:

S>>При достижении ссылок равных нулю Ком сервер уничтожается. Решение держать ссылку в глобальных переменных.

B>Пользователь может закрыть программу после формирования документа, тут документ и закроется. Нельзя.

S>>Либо запусти Эксель и попробуй подключиться к нему через GetActiveOleObject

B>Некрасиво. Можно не тот Excel подцепить. Да и не факт что его не закроет.

procedure TForm1.Button1Click(Sender: TObject);
var
  dd: TExcelApplication;
begin
  dd := TExcelApplication.Create(nil);
  try
    dd.Workbooks.Add('', 0);
    dd.Visible[0] := true;
  finally
    dd.Disconnect;
    dd.Free;
  end;
end;


Можно так, но это не совсем корректно.
https://github.com/BlackEric001
Re[4]: Delphi 7, Excel, CreateOleObject
От: Baskak Россия  
Дата: 06.11.15 14:13
Оценка:
Здравствуйте, BlackEric, Вы писали:

BE>
BE>procedure TForm1.Button1Click(Sender: TObject);
BE>var
BE>  dd: TExcelApplication;
BE>begin
BE>  dd := TExcelApplication.Create(nil);
BE>  try
BE>    dd.Workbooks.Add('', 0);
BE>    dd.Visible[0] := true;
BE>  finally
BE>    dd.Disconnect;
BE>    dd.Free;
BE>  end;
BE>end;
BE>


BE>Можно так, но это не совсем корректно.


TExcelApplication вместо CreateOleObject?
Другая технология. Есть минусы у нее? Это не привязка к конкретной версии Excel?

Не хотелось бы конечно из-за такой мелочи технологию менять. Неужели проблема не решаема?
Re[5]: Delphi 7, Excel, CreateOleObject
От: BlackEric http://black-eric.lj.ru
Дата: 06.11.15 14:20
Оценка:
Здравствуйте, Baskak, Вы писали:

B>Здравствуйте, BlackEric, Вы писали:


BE>>
BE>>procedure TForm1.Button1Click(Sender: TObject);
BE>>var
BE>>  dd: TExcelApplication;
BE>>begin
BE>>  dd := TExcelApplication.Create(nil);
BE>>  try
BE>>    dd.Workbooks.Add('', 0);
BE>>    dd.Visible[0] := true;
BE>>  finally
BE>>    dd.Disconnect;
BE>>    dd.Free;
BE>>  end;
BE>>end;
BE>>


BE>>Можно так, но это не совсем корректно.


B>TExcelApplication вместо CreateOleObject?

B>Другая технология. Есть минусы у нее? Это не привязка к конкретной версии Excel?

B>Не хотелось бы конечно из-за такой мелочи технологию менять. Неужели проблема не решаема?


Технология та же. Это просто обертка из TLB файла. Насколько я понимаю, то здесь будет висеть ссылка
BE>> dd.Workbooks.Add('', 0);
поэтому excel в итоге не закроется, но внешне все ок, хотя при длительной работе конечно могут быть и проблемы.
https://github.com/BlackEric001
Re[3]: Delphi 7, Excel, CreateOleObject
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 06.11.15 14:29
Оценка: 1 (1)
Здравствуйте, Baskak, Вы писали:

B>Здравствуйте, Serginio1, Вы писали:


S>>При достижении ссылок равных нулю Ком сервер уничтожается. Решение держать ссылку в глобальных переменных.

B>Пользователь может закрыть программу после формирования документа, тут документ и закроется. Нельзя.
Можешь сделаль Addref. Правда Эксель не закроется и будет висеть в задачах
Или сохранить файл, закрыть эксель и открыть его как процесс указав в командной строке файл или ..
и солнце б утром не вставало, когда бы не было меня
Отредактировано 06.11.2015 14:34 Serginio1 . Предыдущая версия .
Re[6]: Delphi 7, Excel, CreateOleObject
От: Baskak Россия  
Дата: 06.11.15 14:37
Оценка:
Здравствуйте, BlackEric, Вы писали:


BE>Технология та же. Это просто обертка из TLB файла. Насколько я понимаю, то здесь будет висеть ссылка

BE>>> dd.Workbooks.Add('', 0);
BE>поэтому excel в итоге не закроется, но внешне все ок, хотя при длительной работе конечно могут быть и проблемы.

Технология я так понял что разная — раннее vs позднее связывание. Хотя это не критично конечно.
Переделывать неохота все сделанное под новые классы. И проблем не хочется.

В крайнем случае сохраню документ в файл, и ShellExecute на него натравлю.
Но думаю что должно быть нормальное решение. Поищу еще.
Re[4]: Delphi 7, Excel, CreateOleObject
От: Baskak Россия  
Дата: 06.11.15 14:56
Оценка:
Здравствуйте, Serginio1, Вы писали:

S> Можешь сделаль Addref. Правда Эксель не закроется и будет висеть в задачах

Уже ближе. При потере значения переменной Excel остается. Правда при закрытии программы все равно Excel закрывается.

S>Или сохранить файл, закрыть эксель и открыть его как процесс указав в командной строке файл или ..

Да, ShellExecute. Оставлю как запасной вариант.
Re[5]: Delphi 7, Excel, CreateOleObject
От: BlackEric http://black-eric.lj.ru
Дата: 06.11.15 16:02
Оценка:
Здравствуйте, Baskak, Вы писали:

S>>Или сохранить файл, закрыть эксель и открыть его как процесс указав в командной строке файл или ..

B>Да, ShellExecute. Оставлю как запасной вариант.

Это, наверное, самый правильный вариант.
https://github.com/BlackEric001
Re[6]: Delphi 7, Excel, CreateOleObject
От: glh Россия  
Дата: 07.11.15 20:08
Оценка:
Здравствуйте, BlackEric, Вы писали:

BE>Здравствуйте, Baskak, Вы писали:


S>>>Или сохранить файл, закрыть эксель и открыть его как процесс указав в командной строке файл или ..

B>>Да, ShellExecute. Оставлю как запасной вариант.

BE>Это, наверное, самый правильный вариант.


  НЮ-НЮ
type
  TExcelShowDirty = class(TObject)
  private
    FxlExport: Excel2000.ExcelApplication;
  public
    procedure BeforeDestruction; override;
    procedure xlShowDirty(const FileName: string);
  end;
....
{$region 'TExcelShowDirty'}

procedure TExcelShowDirty.xlShowDirty(const FileName: string);
{
 Этот код не пропускает Avast :-(
  ShellExecute(Application.Handle, 'open', PChar(FileName), nil, nil, SW_SHOWNORMAL);

 Приходиться делать через Ж.
}
var
  unk: IUnknown;
  xl: ExcelApplication;
begin
  FxlExport := nil;// отпускаем предыдущий экземпляр
  try
    {$region 'ActiveObject'}
    try
      GetActiveObject(CLASS_ExcelApplication, nil, unk);
    except
      unk := CoExcelApplication.Create();
    end;
    {$endregion}
    try
      if not Supports(unk, ExcelApplication, xl) then
        Exit;

      FxlExport := xl;
      FxlExport.Workbooks.Add(FileName, lcid);
      // Включаем интерактивность
      FxlExport.EnableEvents := True;
      FxlExport.UserControl := True;
      FxlExport.Interactive[lcid] := True;
      FxlExport.DisplayAlerts[lcid] := True;
      FxlExport.ScreenUpdating[lcid]:= True;
      FxlExport.Visible[lcid] := True;
      if FxlExport.WindowState[lcid] = xlMinimized then
        FxlExport.WindowState[lcid] := xlNormal;
    finally
    { Это и есть Ж - мы не отпускаем экземпляр а оставляем его болтаться в памяти.
      xl := nil;
      unk := nil;
    }
    end;
  except
    //eat exception
  end;
end;

procedure TExcelShowDirty.BeforeDestruction;
begin
  inherited;

  FxlExport := nil;
end;

{$endregion}
Успехов!
C уважением, Алексей.
------------------------------------------------
Хороших %s не бывает — бывает не худший вариант.
delphi excel instance
Re[7]: Delphi 7, Excel, CreateOleObject
От: BlackEric http://black-eric.lj.ru
Дата: 09.11.15 09:38
Оценка:
Здравствуйте, glh, Вы писали:

glh>Здравствуйте, BlackEric, Вы писали:


Avast зажрался, но для начала нужно использовать ShellExecuteEx
https://github.com/BlackEric001
Re: Delphi 7, Excel, CreateOleObject
От: itlab Россия  
Дата: 28.01.16 17:29
Оценка:
Здравствуйте, Baskak, Вы писали:

B>Здравствуйте.


B>Мучаюсь больше полдня, эта тема от меня далека, но вот потребовалось.

B>Требуется из программы (на Delphi 7) создать документ Excel из шаблона, заполнить, и оставить открытым (отключиться от него).

B>
B>// uses ComObj;
B>procedure TForm1.Button1Click(Sender: TObject);
B>var
B>  x: OleVariant;
B>begin
B>  x := CreateOleObject('Excel.Application');
B>  x.Visible := true;
B>  // создание и заполнение документа
B>  x := Unassigned; // Excel закрывается
B>end;
B>


B>Проблема в том, что как только переменная теряет свое значение — Excel автоматически закрывается.

B>Как сделать чтобы он не закрывался? Может есть свойство какое типа AutoClose, которое нужно := false ?

Вот так все будет работать:

x := CreateOleObject('Excel.Application');
try
Workbook := x.WorkBooks.Open(...);

x.Visible := true;
finally
x := Null; // !!!
end;
Re: Delphi 7, Excel, CreateOleObject
От: cyber-bat  
Дата: 26.03.16 22:24
Оценка:
Здравствуйте, Baskak, Вы писали:

B>Здравствуйте.


B>Мучаюсь больше полдня, эта тема от меня далека, но вот потребовалось.

B>Требуется из программы (на Delphi 7) создать документ Excel из шаблона, заполнить, и оставить открытым (отключиться от него).

B>
B>// uses ComObj;
B>procedure TForm1.Button1Click(Sender: TObject);
B>var
B>  x: OleVariant;
B>begin
B>  x := CreateOleObject('Excel.Application');
B>  x.Visible := true;
B>  // создание и заполнение документа
B>  x := Unassigned; // Excel закрывается
B>end;
B>


B>Проблема в том, что как только переменная теряет свое значение — Excel автоматически закрывается.

B>Как сделать чтобы он не закрывался? Может есть свойство какое типа AutoClose, которое нужно := false ?

А попробуйте x присваивать не Unassigned а просто nil, так как это разные значения в данном случае и значение Unassigned присваивается автоматически переменной при ее первой инициализации.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.