Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1] 2  Все   Вниз
  Печать  
Автор Тема: Выгрузка данных в MS Excel  (Прочитано 47857 раз)
0 Пользователей и 4 Гостей смотрят эту тему.
liones
Постоялец

ru
Offline Offline
Пол: Женский

« : 15-09-2009 02:46 » 

Проблема такая: из бд выгружаются данные в excel.

Код:
ExcelApp := CreateOleObject('Excel.Application');
ExcelApp.Application.EnableEvents := false;
Workbook := ExcelApp.WorkBooks.Open(blankpath+'blank.xls');
.....

В общем, файл формируется, все хорошо. Но, после закрытия файла в диспетчере задач остается процесс Excel. Получается сколько раз формируется файл, столько раз и процесс висит в диспетчере. Как его закрыть?

Записан
zubr
Гость
« Ответ #1 : 15-09-2009 03:25 » 

ExelAppl.Quit;
Записан
liones
Постоялец

ru
Offline Offline
Пол: Женский

« Ответ #2 : 15-09-2009 05:33 » 

Пробовала, excel просто закрывается вместе со всеми открытыми файлами, а надо чтобы пользователь мог просмотреть таблицу, возможно отредактировать.
Записан
zubr
Гость
« Ответ #3 : 15-09-2009 05:57 » 

Ну так закрывай только книгу Workbook.Close
Записан
liones
Постоялец

ru
Offline Offline
Пол: Женский

« Ответ #4 : 15-09-2009 06:21 » 

В том то и дело, что не надо мне закрывать книгу. Надо, чтобы после закрытия бд закрывался процесс excel.

Пробовала вот это:
ExcelApp.Application.Hide;
...
ExcelApp.Application.UnAssigned;
...
ExcelApp.Application:=nil;

Не работает, выдает разные ругательные сообщения.
« Последнее редактирование: 15-09-2009 08:30 от Sel » Записан
sss
Специалист

ru
Offline Offline

« Ответ #5 : 15-09-2009 06:30 » 

liones, читай мануал:

Цитата
In Delphi code, CreateOleObject is called once to create each new single instance of a class.

Тебе надо найти выполняющийся экземпляр в таблице ROT. Что нибудь вроде GetActiveOleObject.
Если не найден выполнять CreateOleObject...
Записан

while (8==8)
x77
Модератор

ro
Offline Offline
Пол: Мужской
меняю стакан шмали на обратный билет с Марса.


« Ответ #6 : 21-09-2009 08:04 » 

В том то и дело, что не надо мне закрывать книгу. Надо, чтобы после закрытия бд закрывался процесс excel.

Пробовала вот это:
ExcelApp.Application.Hide;
...
ExcelApp.Application.UnAssigned;
...
ExcelApp.Application:=nil;

Не работает, выдает разные ругательные сообщения.

в данном случае Application является свойством объекта ExcelApp. от того, что вы обнулите свойство - в лучшем случае, ничего не изменится, в худшем - будет ошибка (если свойство обнуления не допускает. чтобы в диспетчере задач не оставался висеть процесс, надо обнулять сам объект. корректные варианты:

1) ExcelApp := nil; Null; // upd. - x77
2) ExcelApp := Unassigned;
3) Finalize (ExcelApp);

liones, читай мануал:

Цитата
In Delphi code, CreateOleObject is called once to create each new single instance of a class.

Тебе надо найти выполняющийся экземпляр в таблице ROT. Что нибудь вроде GetActiveOleObject.
Если не найден выполнять CreateOleObject...


на GetActiveOleObject проверять действительно стоит, но корректное обнуление всё равно необходимо, иначе в таск-менеджере будет всегда висеть один процесс.
« Последнее редактирование: 21-09-2009 09:17 от x77 » Записан

sss
Специалист

ru
Offline Offline

« Ответ #7 : 21-09-2009 08:33 » 

на GetActiveOleObject проверять действительно стоит, но корректное обнуление всё равно необходимо, иначе в таск-менеджере будет всегда висеть один процесс.

Ничего не понял. Почему плохо, если висит один сервер процесс? Его использовать и надо для множества книг. Кстати. Если вы создаете объект, присваивание ExcelApp := nil  приводит к неявному вызову метода Release() интерфейса IDispacth скрытого реализацией TVariant, что должно закрыть сервер (по идее соцсоревнований). Но почти во всех версиях MSO это действо вылетает с ошибкой для word и excel.  liones об этом и пишет.  А вот если получаете указатель на выполняющийся - это необходимо.

Записан

while (8==8)
x77
Модератор

ro
Offline Offline
Пол: Мужской
меняю стакан шмали на обратный билет с Марса.


« Ответ #8 : 21-09-2009 08:47 » 

почти во всех версиях MSO это действо вылетает с ошибкой для word и excel.

хоть одну версию приведите из этих "почти всех" Улыбаюсь

почему плохо, когда висит процесс - я не знаю. потому что не знаю, что делает автор. может, у неё прога, которая работает на терминальном сервере, к которому коннектиться 10-20 юзеров через RDP. иметь двадцать запущенных экселов в памяти - в общем не есть гуд. можно ещё варианты придумать.

но вот именно потому, что я не знаю, что именно делает автор, я тупо отвечаю на её вопрос: как "убрать" процесс из ТаскМенеджера. Улыбаюсь
Записан

sss
Специалист

ru
Offline Offline

« Ответ #9 : 21-09-2009 09:04 » 

MSO 2003 Prof, MSO 2000 Prof, MSO 2003 Std. Речь как раз о том, что бы все запросы отрабатывал один сервер автоматизации. Для этого если его нет, его надо создать. Если для созданного вызвать ExcelApp := nil он будет закрыт. Ну должен был бы быть закрыт - однако это вызывает исключение. При этом хоть сто клиентов RDP - кто то из них должен первым создать этот чёртов сервер и не присваивать ExcelApp := nil...
Записан

while (8==8)
x77
Модератор

ro
Offline Offline
Пол: Мужской
меняю стакан шмали на обратный билет с Марса.


« Ответ #10 : 21-09-2009 09:12 » 

sss, очепятка там у меня. с седьмых дельфей юзается не вариант, а OleVariant, соответственно,

Код:
procedure TForm1.BitBtn1Click(Sender: TObject);
var
  E: OleVariant;
begin
  E := CreateOleObject ('Excel.Application');
  try
    E.Visible := TRUE;
  finally
    E := Null;
  end;
end;

такой код отработает нормально почти с любым офисом.
Записан

zubr
Гость
« Ответ #11 : 21-09-2009 09:25 » 

x77, проверь свой код но в разных кнопках. То есть одной кнопкой открой Excel, а другой закрой.

Согласен с SSS - надо проверять наличие активного сервера. А для закрытия процесса Excel вызывать ExcelApp.Quit.
Записан
zubr
Гость
« Ответ #12 : 21-09-2009 09:28 » 

А нет, извиняюсь, если книги закрыты, то закрывается.
Записан
x77
Модератор

ro
Offline Offline
Пол: Мужской
меняю стакан шмали на обратный билет с Марса.


« Ответ #13 : 21-09-2009 09:30 » 

zubr, а что от этого может измениться?

Код:
var
  E: OleVariant;

procedure TForm1.BitBtn1Click(Sender: TObject);
begin
  E := CreateOleObject ('Excel.Application');
  E.Visible := TRUE;
end;

procedure TForm1.BitBtn2Click(Sender: TObject);
begin
  E := Null;
end;

работает, есс-но.
Записан

x77
Модератор

ro
Offline Offline
Пол: Мужской
меняю стакан шмали на обратный билет с Марса.


« Ответ #14 : 21-09-2009 09:56 » 

Цитата: F1
if the interface returned by CreateOleObject is assigned to a Variant, you can release the interface by assigning the Unassigned constant to that Variant.

Цитата: F1
Finalize simply sets all long strings to empty and all variants and interfaces to Unassigned, thus properly releasing any memory that was referenced by the long strings and variants.

таким образом, присовение Null, Unassigned или вызов Finalize - в случае с вариантом делают одно и то же. почему я предпочитаю именно этот способ, вместо обращения к Excel.Quit, так это потому, что освобождать объект должен тот, кто его создаёт.

если я делаю Excel := Null, я могу проверить Excel на VarIsNull (Excel). если я делаю Excel := Unassigned или Finalize (Excel) - я могу проверить через VarIsEmpty (Excel).

а вот когда вы пишите Excel.Quit - переменная Excel не является пустой, не является "неприсвоенной", и не равна Null. в общем случае вы не сможете по этой переменной определить, жив ли ваш объект. потому что создаёте его вы (Excel := CreateOleObject), а освобождает он себя сам (Excel.Quit).

и это - опасная и порочная практика Ага
Записан

zubr
Гость
« Ответ #15 : 21-09-2009 11:35 » 

x77, дык никто и не спорит, что надо очищать вариантную переменную - сделал Excel.Quit, а затем Excel := Null.
Насчет жив ли объект не поможет и VarIsNull если объект закрыл пользователь.
Записан
x77
Модератор

ro
Offline Offline
Пол: Мужской
меняю стакан шмали на обратный билет с Марса.


« Ответ #16 : 21-09-2009 11:58 » 

ещё как поможет. после Quit - у тебя остаётся висеть процесс. если пользователь закрыл объект (что равносильно Quit) - у тебя тоже остаётся висеть процесс. и VarIsNull покажет, что объект жив. и это правда. и убьётся процесс только с поледующим присвоением null.
Записан

x77
Модератор

ro
Offline Offline
Пол: Мужской
меняю стакан шмали на обратный билет с Марса.


« Ответ #17 : 21-09-2009 12:04 » 

т.е. я имел в виду, когда эксель открывается через сом-интерфейс, программно. в этом случае закрытие экселя не приводит к убитию процесса, ибо в проге остаётся ссылка на ком-объект (которая после закрытия проги станет невалидной).
Записан

Aguilina
Интересующийся

kz
Offline Offline
Пол: Женский

« Ответ #18 : 02-10-2009 07:06 » new

Всем доброго дня!
У меня схожая проблема. Но есть еще кое-что.
Такая задача:
Я написала программу, установила экзешник у пользователей. Всё работает. Но вот в чем неудобство - во время формирования отчета они не могут открыть другие экселевские файлы. Как только пользователи их открывают формируемый отчет ломается. И в итоге в диспетчере остается процесс Excel.
1.   В коде программы написала как выше посоветовал х77:
Excel := CreateOleObject ('Excel.Application');
  try
    Excel.Visible := TRUE;
  finally
    Excel := Null;
  end;
Теперь отчет не ломается при открытии других файлов экзель и в диспетчере не остается процесс EXcel, но отчет формируется в фоновом режиме.
Т.е.  теперь нужно сделать так, чтобы пользователь мог работать(открывать, редактировать,  закрывать) с другими файлами экселя и не имел доступа к отчету во время формирования и в конце диспетчер должен очиститься от процессов Excel(ну эту проблему с помощью вышеуказанного кода вроде решила=)) , за что огромное спасибо!).
       2. Когда делаю Excel.Visible := FALSE;  не дает открыть другие эксель файлы и формирование отчета ломается.
Что еще можно сделать?

Записан
Aguilina
Интересующийся

kz
Offline Offline
Пол: Женский

« Ответ #19 : 05-10-2009 03:28 » 

Доброе утро.

Можно ускорить с ответом пожалуйста. Мне уже завтра окончательный вариант предоставить нужно Жаль(((
Записан
zubr
Гость
« Ответ #20 : 05-10-2009 04:02 » 

Если мне не изменяет память у оффисных приложений есть объект Protection, позволяющий запретить пользователю вносить изменения в определенный документ. Попробуй посмотреть в этом направлении.
Записан
Aguilina
Интересующийся

kz
Offline Offline
Пол: Женский

« Ответ #21 : 05-10-2009 06:11 » 

Если ставить этот объект, то пользователь не сможет редактировать отчет, когда тот будет готов. Можно еще дать ему доступ через пароль, или отключить защиту после формирования. Но как-то это неудобно...
Все-таки желательно, чтоб сам отчет при формировании не открывался, но в то же время пользователь мог открывать другие отчеты. Есть какие нибудь советы по этому вопросу? Поделитесь... =))
В отчет выгружается очень большой объем данных из базы SQL. Поэтому желательно процесс формирования не прерывать.
Использую Delphi 7, SQL Navigator 5.5, Win XP.
Заранее благодарю.
Записан
zubr
Гость
« Ответ #22 : 05-10-2009 07:00 » 

Aguilina, какие проблемы? Перед началом программного формирования отчета устанавливаешь протектион, после окончания формирования отчета программно снимаешь протектион.
Записан
sss
Специалист

ru
Offline Offline

« Ответ #23 : 05-10-2009 08:43 » 

Aguilina, почему нельзя экземпляр, в который выводится отчет, оставить невидимым до окончания вывода?
Записан

while (8==8)
Aguilina
Интересующийся

kz
Offline Offline
Пол: Женский

« Ответ #24 : 05-10-2009 09:50 » 

sss, до этого я его делала невидимым. Но когда открывала другие экселевские файлы, то отчет ломался во время формирования. Т.е. до конца отчет не формировался.
Записан
Aguilina
Интересующийся

kz
Offline Offline
Пол: Женский

« Ответ #25 : 05-10-2009 10:11 » 

zubr, мне перед открытием экселя и после закрытия ставить? Вот краткий вариант кода:

var
.......................
Begin
     Excel:=CreateOleObject('Excel.Application');
     try
      Excel.Visible:=True;
      Excel.Workbooks.Open('C:\DProject\USTF_From_TI\EXCEL\'+trim(FileName.text)+'.xls', False);
      Workbook:=Excel.Workbooks.Item[1];
      Sheet1:=Workbook.Sheets.Item[1];
{-------------------------------------------------------------------}
    for i:=StrToInt(StartEdit.text) to StrToInt(EndEdit.text) do
    begin
    //начинается поиск по одному продукту а
      If BMSearch(1, trim(Sheet1.Cells[i,5].text), 'а')>0 then
       begin
           DataModule1.Query1.SQL.Clear;
           DataModule1.Query1.SQL.Add('select…..');
           DataModule1.Query1.SQL.Add('from…….');
           DataModule1.Query1.SQL.Add('where………');
           DataModule1.Query1.SQL.Add('order by ………..);

           DataModule1.Query1.ExecSQL;
           DataModule1.Query1.Open;
           FillExcel(Sheet1,i,DataModule1.Query1.FieldByName('').AsString,DataModule1.Query1.FieldByName('..').AsString, , , , , , ,); //заполняю эксель
           DataModule1.Query1.Close;
       end;
    //заканчивается поиск по продукту а

   //начинается поиск по одному продукту б
    ..........................................................
    ..........................................................
   //заканчивается поиск по продукту б
  
   // и так продолжается по 15-ти продуктам.

   end;
{-------------------------------------------------------------------}
    xlFileName:='path:\'+trim(FileName.text)+'_1.xls';
    Workbook.SaveAs(FileName:=xlFileName, FileFormat:=xlWorkbookNormal);

    finally
      Excel:=Unassigned;
    end;
    Form1.Close;

end;
« Последнее редактирование: 05-10-2009 10:14 от Aguilina » Записан
Aguilina
Интересующийся

kz
Offline Offline
Пол: Женский

« Ответ #26 : 05-10-2009 10:45 » 

Подскажите плз как протект использовать правильно, чтоб все работало. Ранее не сталкивалась....  Жаль

Пишу так в начале:
  Sheet1:=Workbook.Sheets.Item[1];
  Excel.ActiveSheet.protect('123');
  AllowFormattingCells:=False;

................................

а в конце так:
    
    finally
      Excel:=Unassigned;
    end;

Excel.ActiveSheet.Unprotect('123');

У меня файл открывается, но данные туда не попадают из таблицы, говорит файл защищен. Как же тогда отчет сформируется...?  Не понял
« Последнее редактирование: 05-10-2009 10:48 от Aguilina » Записан
zubr
Гость
« Ответ #27 : 05-10-2009 16:36 » 

Aguilina, внимательнее посмотри описание метода Protect:
procedure Protect(Password: OleVariant; DrawingObjects: OleVariant; Contents: OleVariant;
                      Scenarios: OleVariant; UserInterfaceOnly: OleVariant;
                      AllowFormattingCells: OleVariant; AllowFormattingColumns: OleVariant;
                      AllowFormattingRows: OleVariant; AllowInsertingColumns: OleVariant;
                      AllowInsertingRows: OleVariant; AllowInsertingHyperlinks: OleVariant;
                      AllowDeletingColumns: OleVariant; AllowDeletingRows: OleVariant;
                      AllowSorting: OleVariant; AllowFiltering: OleVariant;
                      AllowUsingPivotTables: OleVariant); safecall;
Попробуй параметр UserInterfaceOnly сделать True.
Записан
zubr
Гость
« Ответ #28 : 05-10-2009 16:38 » 

Вот описание этого параметра в хелпе:
UserInterfaceOnly  True to protect the user interface, but not macros. If this argument is omitted, protection applies both to macros and to the user interface.
Записан
sss
Специалист

ru
Offline Offline

« Ответ #29 : 06-10-2009 00:42 » 

Но когда открывала другие экселевские файлы, то отчет ломался во время формирования. Т.е. до конца отчет не формировался.


Как понять  "открывала другие экселевские файлы" ? Программно или проводником? 
Записан

while (8==8)
Страниц: [1] 2  Все   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines