Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Базы данных и репортинг > Отчет в Excel


Автор: Demo 10.10.2006, 13:29
Здравствуйте, уважаемые программисты!
У меня возникла необходимость данные из DBGrid (которые формируются  при помощи запроса) передать в Excel.
Пишу следующий код, Excel загружается, имя листу присваивается, но почему-то в ячейки вместо данных из Грида вставляются данные, которые были копированы ранее (притом неважно где, в Ворде, блокноте и т.д.).
Помогите, пожалуйста разобраться!
Подскажите, где у меня ошибка?

Код

var i1,i2,i3,i:integer;    bm:TBookmark;       
begin
  DBGrid1.DataSource.DataSet.DisableControls;
   bm:=DBGrid1.DataSource.DataSet.GetBookmark;
   DBGrid1.DataSource.DataSet.First;

  excelApplication:=CreateOleObject('Excel.Application');
  ExcelApplication.visible:=true;
  ExcelApplication.workBooks.add;
  ExcelApplication.workBooks[1].WorkSheets[1].Name:='Отчет';
  ExcelApplication.cells[1,1].value:='Заголовок';

  ExcelApplication.Columns[1].ColumnWidth:=13;
  
  DBGrid1.DataSource.DataSet.Next;
  ExcelApplication.WorkBooks[1].WorkSheets['Отчет'].Paste;

    DBGrid1.DataSource.DataSet.GotoBookmark(bm);
   DBGrid1.DataSource.DataSet.FreeBookmark(bm);
   DBGrid1.DataSource.DataSet.EnableControls;
   Screen.Cursor:=crDefault;

   Application.Restore;

end;


Заранее спасибо!

Автор: Genyaa 10.10.2006, 14:20
  DBGrid1.DataSource.DataSet.Next;
  ExcelApplication.WorkBooks[1].WorkSheets['Отчет'].Paste;

Я не знаток DBGrid, но по сути в Excel метод Paste вставляет данные из ClipBoard (скопированные ранее по Copy или <Ctrl+C>). Что собственно и происходит, как Вы говорите.

По логике вещей, нужно либо сначала скопировать нужные данные из DBGrid в ClipBoard (чего как раз я и не наблюдаю в Вашем коде) и потом использовать Paste, либо использовать другие методы переноса данных (непосредственное присвоение значений ячейкам, например).

Автор: Demo 11.10.2006, 08:44
Данных в DBGride слишком много, поэтому присваивать значения ячейкам нецелесообразно.
А как можно скопировать данные из Грида? Но нужны не все поля из DBGrida, а выборочные!
Помогите, пожалуйста!!!

Автор: Demo 11.10.2006, 09:19
Итак, данные из DBGrida я скопировала. Добавила следующий код:

Код

Memo1:= TMemo.Create(Self);
  Memo1.Visible := false;
  Memo1.Parent :=Form1;
  Memo1.Clear;
  sline := '';

    // добавила информацию для имен колонок
  for col := 0 to DBGrid1.FieldCount-1 do 
    sline := sline + DBGrid1.Fields[col].DisplayLabel + #9; 
  Memo1.Lines.Add(sline);

  // получение данных из Memo
  for row := 0 to DBGrid1.DataSource.DataSet.RecordCount-1 do 
  begin 
    sline := ''; 
    for col := 0 to DBGrid1.FieldCount-1 do 
      sline := sline + DBGrid1.Fields[col].AsString + #9; 
    Memo1.Lines.Add(sline);
    DBGrid1.DataSource.DataSet.Next; 
  end;

   Memo1.SelectAll;
   Memo1.CopyToClipboard;
 ExcelApplication.WorkBooks[1].WorkSheets['Отчет'].Paste;


  Здесь я данные отправляю сначала в Memo, а затем в Excel. Memo используется как промежуточный компонент. 
Но теперь другой вопрос: Как мне выбрать конкретные столбцы из DBGrid? В Excel можно, конечно, потом удалить лишние, но нужно, чтобы туда попадали только нужные данные.

И еще один вопрос: Можно при передаче данных перевернуть таблицу? Так, чтобы столбцы из DBGrid-а стали строками, а строки столбцами?

Автор: Genyaa 11.10.2006, 10:47
Цитата(Demo @  11.10.2006,  10:19 Найти цитируемый пост)
  Здесь я данные отправляю сначала в Memo, а затем в Excel. Memo используется как промежуточный компонент. 
Но теперь другой вопрос: Как мне выбрать конкретные столбцы из DBGrid? 


На этапе "отправления" данных в Мемо нужно перемещать не все столбцы DBGrid, а только нужные. В цикле "отправления" данных проверяйте номера столбцов или их имена на предмет предназначения их к переносу в Excel.


Цитата(Demo @  11.10.2006,  10:19 Найти цитируемый пост)
И еще один вопрос: Можно при передаче данных перевернуть таблицу? Так, чтобы столбцы из DBGrid-а стали строками, а строки столбцами? 


Это зависит от того, в какой последовательности "отправляете данные в Мемо". Если вывернуть циклы "на изнанку" и внешним циклом поставить перебор колонок, а внутренним - перебор строк в DBGrid, то вы скопируете в Мемо уже транспонированную таблицу.

Но можно попробовать воспользоваться методом из Excel - PasteSpecial - этот метод (при верном указании параметров) позволяет сделать транспонирование скопированной таблицы на этапе вставки.

Автор: Demo 27.11.2006, 12:49
Цитата(Genyaa @ 11.10.2006,  10:47)
На этапе "отправления" данных в Мемо нужно перемещать не все столбцы DBGrid, а только нужные. В цикле "отправления" данных проверяйте номера столбцов или их имена на предмет предназначения их к переносу в Excel.

Подскажите, пожалуйста, как это должно выглядеть программно?! Каким образом мне это описать? Например, мне нужны столбцы 2,4,6,7,11?

Автор: mihanik 27.11.2006, 16:45
Модератор: Пожалуйста, один топик - один вопрос.

Понимаю, что вопросы связаны по смыслу, но всё же...

Добавлено @ 16:50 
Кроме того!
Это ближе к Delphi и базы данных...

Посему перемещаю...


Автор: Savek 27.11.2006, 17:04
Использовать Clipboard для экспорта категорически не рекомендуется.
У пользователя там могут быть данные, которые будут утеряны smile 

Автор: Rodman 27.11.2006, 17:09
мож это поможет...
Код

//Пример dbgrid (DBGrid1) имеет всплывающее меню, которое позволяет две опции "Send to Excel" и "Copy"


// ЗАМЕЧАНИЕ: этот метод должен включать COMObj, Excel97 units

// ОБНОВЛЕНИЕ: если Вы используете Delphi 4, то замените xlWBatWorkSheet на 1 (один)


//-----------------------------------------------------------
// если toExcel = false, то экспортируем содержимое dbgrid в Clipboard
// если toExcel = true, то экспортируем содержимое dbgrid в Microsoft Excel
procedure ExportDBGrid(toExcel: Boolean);
var
bm: TBookmark;
col, row: Integer;
sline: String;
mem: TMemo;
ExcelApp: Variant;
begin
Screen.Cursor := crHourglass;
DBGrid1.DataSource.DataSet.DisableControls;
bm := DBGrid1.DataSource.DataSet.GetBookmark;
DBGrid1.DataSource.DataSet.First;

// создаём объект Excel
if toExcel then
begin
ExcelApp := CreateOleObject('Excel.Application');
ExcelApp.WorkBooks.Add(xlWBatWorkSheet);
ExcelApp.WorkBooks[1].WorkSheets[1].Name := 'Grid Data';
end;

// Сперва отправляем данные в memo
// работает быстрее, чем отправлять их напрямую в Excel
mem := TMemo.Create(Self);
mem.Visible := false;
mem.Parent := MainForm;
mem.Clear;
sline := '';

// добавляем информацию для имён колонок
for col := 0 to DBGrid1.FieldCount-1 do
sline := sline + DBGrid1.Fields[col].DisplayLabel + #9;
mem.Lines.Add(sline);

// получаем данные из memo
for row := 0 to DBGrid1.DataSource.DataSet.RecordCount-1 do
begin
sline := '';
for col := 0 to DBGrid1.FieldCount-1 do
sline := sline + DBGrid1.Fields[col].AsString + #9;
mem.Lines.Add(sline);
DBGrid1.DataSource.DataSet.Next;
end;

// копируем данные в clipboard
mem.SelectAll;
mem.CopyToClipboard;

// если необходимо, то отправляем их в Excel
// если нет, то они уже в буфере обмена
if toExcel then
begin
ExcelApp.Workbooks[1].WorkSheets['Grid Data'].Paste;
ExcelApp.Visible := true;
end;

FreeAndNil(ExcelApp);
DBGrid1.DataSource.DataSet.GotoBookmark(bm);
DBGrid1.DataSource.DataSet.FreeBookmark(bm);
DBGrid1.DataSource.DataSet.EnableControls;
Screen.Cursor := crDefault;
end; 


Добавлено @ 17:10 
и http://www.swissdelphicenter.ch/torry/printcode.php?id=1427 почитай

Автор: Akella 28.11.2006, 09:59
я уверен, что вопрос из этой темы http://forum.vingrad.ru/delphi-activex-com-corba-ole.html
Там это уже обсуждалось сотни раз

Добавлено @ 10:02 
Demo, и ещё, DBGrid тут не причём, т.к. DBGrid всего лишь отображает данные из TDataSet`а, с DataSet`ом и работай.

Добавлено @ 10:04 
Demo, вот, смотри, шикарная тема: http://forum.vingrad.ru/topic-84634.html

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)