C++ Builder
| Главная | Уроки | Статьи | FAQ | Форум | Downloads | Литература | Ссылки | RXLib | Диски |

 
Экспорт DBGrid->Excel, Как сделать???
Smart
  Отправлено: 28.05.2006, 16:32


Дежурный стрелочник

Группа: Участник
Сообщений: 35



Здравствуйте, господа!
Потратил пару часов на поиск в инете примера такого экспорта, но увы...
Есть ADOQuery, через DataSource в DBGrid получаю ответ от сервера — таблицу данных.
Вопрос в том, как теперь эту таблицу (все ячейки) переслать в Excel?
Если можно, рабочий пример.
AVC
Отправлено: 29.05.2006, 10:08


Ветеран

Группа: Модератор
Сообщений: 1583



QUOTE

Потратил пару часов на поиск в инете примера такого экспорта, но увы...

Простите, плохо искали. Ответы и готовые решения есть прямо тут. В уроках или в поиске.
Например
Отчет на C++Builder в Excel, Передача данных из DBGrid в Excel
Что быстрее XML, dBase, Excel? (последние посты)
Smart
Отправлено: 29.05.2006, 20:35


Дежурный стрелочник

Группа: Участник
Сообщений: 35



AVC, спасибо большое!
Искал и вправду долго и безуспешно.
Возможная причина неудачных поисков — искал "экспорт", "DBGrid" и "Excel".
Про "передачу данных" не спрашивал...
olegenty
Отправлено: 31.05.2006, 09:28


Ветеран

Группа: Модератор
Сообщений: 2412



экспорт DBGrid в Excel не возможен по определению, DBGrid не содержит данные, а только отображает их. исключение из правил — DBGridEh, имеющий метод экспорта в Excel самого себя с учётом цвета и пр. в соответствии с GetCellParams
Smart
Отправлено: 01.06.2006, 21:19


Дежурный стрелочник

Группа: Участник
Сообщений: 35



К сожалению сцылка, приведенная AVC, практически ничего не прояснила по причине невнятности подобных конструкций:
CODE

CExcelExp::Export(ex, "C1", fdsSignsSIGN->AsString);
CExcelExp::Export(ex, "C2", fdsSignsNAME->AsString);
CExcelExp::Export(ex, "C3", fdsSignsPRINT_SIGN->AsInteger);
CExcelExp::Export(ex, "C4", fdsSignsDESCRIPTION->AsString);


Вроде разобрался, помогли исходники на Паскале, других не нашел sad.gif

Сейчас запощу, мож кому пригодится.
Smart
Отправлено: 01.06.2006, 21:28


Дежурный стрелочник

Группа: Участник
Сообщений: 35



Итак, _реально_ работающий экспорт из DBGrid.
Вот тока не надо про то, что "экспорт DBGrid в Excel невозможен по определению" — все уши прожужжали в форумах вместо конкретных примеров доступа к ячейкам данных. :~E
CODE

Variant XLSAPP;
//===============================================
int f4_ExcelInit(AnsiString File){//Подключение к Excel
try{//Если Excel запущен — подключиться к нему
  XLSAPP=Variant::GetActiveObject("Excel.Application");}
catch (...){//Если Excel не запущен — запустить его
  try{XLSAPP=Variant::CreateObject("Excel.Application");}
  catch (...){
    Application->MessageBox("Невозможно открыть Microsoft Excel."
    "Возможно, Excel не установлен на компьютере.","Ошибка",MB_OK+MB_ICONERROR);}
  }
try{
 if(File!=""){
    XLSAPP.OlePropertyGet("WorkBooks").OleProcedure("Open",File.c_str());}//Открыть документ
 else XLSAPP.OlePropertyGet("WorkBooks").OleProcedure("add");//Создать новый документ
 }
catch (...){
 Application->MessageBox("Ошибка открытия файла Microsoft Excel.",
                         "Ошибка",MB_OK+MB_ICONERROR);return -1;}
return 1;
}
//===============================================
int f4_ExcelVisible(bool i){//Показать/скрыть Excel
if(!XLSAPP.IsEmpty())XLSAPP.OlePropertySet("Visible",i);
return 1;
}
//===============================================
int f4_ExcelSend(int Sheet, int Stolb, int Stroka, AnsiString Str, bool asText=false){//>>>
Variant ExcelSheet,Cur;//Запись данных в Excel (Лист, столбец, строка, "данные",как_текст?)
AnsiString ErrStr;
if(Str=="")return 1;//Не писать "пустоту"
ErrStr="Ошибка при записи: лист "+IntToStr(Sheet)+", столбец "+IntToStr(Stolb)+", строка "+IntToStr(Stroka);
try{ExcelSheet=XLSAPP.OlePropertyGet("WorkSheets",Sheet);}
catch (...){Application->MessageBox(ErrStr.c_str(),
           "Ошибочный номер листа Microsoft Excel",MB_OK+MB_ICONERROR); return -1;}
try{Cur=ExcelSheet.OlePropertyGet("Cells",Stroka,Stolb);
   if(asText)Cur.OlePropertySet("NumberFormat","@");//Форматировать ячейку как текст
   Cur.OlePropertySet("Value",Str.c_str());}
catch (...){Application->MessageBox(ErrStr.c_str(),
           "Ошибка Microsoft Excel",MB_OK+MB_ICONERROR); return -1;}
return 1;
}
//===============================================
int f4_SaveToExcel(){//Экспорт всех ячеек в Excel
TBookmark bm;
int result,col, row;
Screen->Cursor=crHourGlass;
Application->ProcessMessages();
result=f4_ExcelInit("");//Инициализация Excel
if(result==-1){Screen->Cursor=crDefault;return -1;}
Form1->DBGrid1->DataSource->DataSet->DisableControls();
bm=Form1->DBGrid1->DataSource->DataSet->GetBookmark();//Текущая ячейка
Form1->DBGrid1->DataSource->DataSet->First();
for(col=0;col<Form1->DBGrid1->FieldCount;col++){//добавляем имена колонок
 result=f4_ExcelSend(1,col+1,1,Form1->DBGrid1->Fields[col]->DisplayLabel,true);
 if(result==-1){Screen->Cursor=crDefault;return -1;}
 }
Form1->ProgressBar1->Position=0;//Прогрессбар
Form1->ProgressBar1->Max=Form1->DBGrid1->DataSource->DataSet->RecordCount;
for(row=0;row<Form1->DBGrid1->DataSource->DataSet->RecordCount;row++){// получаем данные
 Form1->ProgressBar1->Position=row;//Прогрессбар
 for(col=0;col<Form1->DBGrid1->FieldCount;col++){
   result=f4_ExcelSend(1,col+1,row+2,Form1->DBGrid1->Fields[col]->AsString,true);
   if(result==-1){Screen->Cursor=crDefault;return -1;}
   }
 Form1->DBGrid1->DataSource->DataSet->Next();
 }
Form1->DBGrid1->DataSource->DataSet->GotoBookmark(bm);//Текущая ячейка
Form1->DBGrid1->DataSource->DataSet->FreeBookmark(bm);
Form1->DBGrid1->DataSource->DataSet->EnableControls();
f4_ExcelVisible(true);//Сделать видимым Excel
Form1->ProgressBar1->Position=0;//Прогрессбар
Screen->Cursor=crDefault;
Application->ProcessMessages();
return 1;
}



Отредактировано Smart — 01/06/2006, 21:29
AVC
Отправлено: 02.06.2006, 08:32


Ветеран

Группа: Модератор
Сообщений: 1583



QUOTE (Smart @ 01/06/2006, 20:19)
К сожалению сцылка, приведенная AVC, практически ничего не прояснила по причине невнятности подобных конструкций:
CODE

CExcelExp::Export(ex, "C1", fdsSignsSIGN->AsString);
CExcelExp::Export(ex, "C2", fdsSignsNAME->AsString);
CExcelExp::Export(ex, "C3", fdsSignsPRINT_SIGN->AsInteger);
CExcelExp::Export(ex, "C4", fdsSignsDESCRIPTION->AsString);


Вроде разобрался, помогли исходники на Паскале, других не нашел sad.gif

Сейчас запощу, мож кому пригодится.

Да... Простите, но внимательно читать вы, похоже, так и не научились. smile.gif
В том же посте olegenty от 26/08/2004, 09:01 где и CExcelExp::Export(ex, "C1", fdsSignsSIGN->AsString); но строк на 30 ниже приведено описание и реализация класса CExcelExp. Реализация метода Export тривиальна и, вполне, очевидна.

QUOTE

Вот тока не надо про то, что "экспорт DBGrid в Excel невозможен по определению" — все уши прожужжали в форумах вместо конкретных примеров доступа к ячейкам данных. :~E

Надо. Вы не понимаете принципа. Из ячеек данных DBGrid'а можно экспортировать, причем ценой значительных усилий, содержимое только видимых в настоящий момент строк.
Вы же сами пишете
> for(row=0;rowDBGrid1->DataSource->DataSet->RecordCount;row++){// получаем данные
похоже без понимания происходящего.

PS. Готовое рабочее решение приведено в том же посте olegenty от 26/08/2004, 09:01. А если в нем вынести fdsSignJoins и имя файла в параметры то оно станет просто универсальным (у меня метод с такими параметрами добавлен в класс, аналогичный CExcelExp).

Отредактировано AVC — 02/06/2006, 07:33
Smart
Отправлено: 02.06.2006, 12:17


Дежурный стрелочник

Группа: Участник
Сообщений: 35



Про принципы отображения DBGrid я в курсе, и беру данные через датасет с пониманием происходящего.
Заданный вопрос-то ведь все равно понятен, но во многих форумах получал отповедь о виртуальности грида и больше ничего.
Хочу подчеркнуть, что проблемы с Excel у меня не было, была проблема доступа к ячейкам датасета.
QUOTE

Готовое рабочее решение приведено в том же посте olegenty от 26/08/2004, 09:01.

Оно не готовое. Попробуйте уяснить из приведенного куска, что такое fdsSignsSIGN, fdsSignsNAME, fdsSignsPRINT_SIGN, fdsSignsDESCRIPTION
Я не смог, наверное слабый мозк.

Отредактировано Smart — 02/06/2006, 12:22
avc*
Отправлено: 02.06.2006, 12:40


Не зарегистрирован







QUOTE

Попробуйте уяснить из приведенного куска, что такое fdsSignsSIGN, fdsSignsNAME, fdsSignsPRINT_SIGN, fdsSignsDESCRIPTION

Элементарно.
Мы знаем, что на входе есть выборка (DataSet). Увидев ->AsString и привыкнув работать с dataset'ами я тут же предположил, что это TField или его наследник. Посмотрел в Help'е — действительно на название AsString имеет монополию класс TField (и его наследники). Следовательно неопубликованный кусок кода выглядит примерно так
TField* fdsSignsSIGN;
fdsSignsSIGN = некий_не_интересующий_нас_dataset->FieldByName("не_интересное_имя_поля");
(или FindField, хотя я в этом сомневаюсь)

Smart
Отправлено: 02.06.2006, 12:59


Дежурный стрелочник

Группа: Участник
Сообщений: 35



Ну, для меня это не элементарно...
Но все равно спасибо!

Вернуться в Работа с базами данных в C++Builder