Сообщений 7 Оценка 10 Оценить |
В одно время у меня возникла необходимость в общении с Excel2000, при чем, объемы данных должны были проходить большие, что привело к появлению этой DLL-ки. При открытии файла все данные, находящиеся в нем загружаются в динамический строковый кэш (при нынешних объемах памяти это не так много) и потом можно работать с ним. К сожалению, форматирование не кэшируется, да и задач таких не ставилось. В результате тестирования программа, работающая с Excel с помощью OLE (COM тоже пробовали) втискивала туда 15000 ячеек за 50 секунд, а через эту DLL-ку за 3. Разница, как говорится, на лице :).
В дополнение к этому, система IntelliSense в BCB 5.0, и без того достаточно медленная, при подключении ATL через директиву #include совсем умирает. Именно поэтому в DLL используются не все функции Excel, а те, которые мне пригодились в реальной работе.
Опять же, работать с числовыми индексами удобнее, чем с адресами ячеек, по крайней мере, мне так кажется.
При работе с разными компиляторами возникают проблемы, например, с lib-ы от VC 6.0 в BCB 5.0 не подключаются, а исходный код каждый раз менять (хотя бы stdafx.h выкидывать, или вставлять обратно), нудно, а так - подключил, и работай.
XlSetColor (char *Cells,XlColorIndex Color); | Установка цвета ячеек |
XlSetCellsBorder (char *Cells, bool H, bool V, bool R, bool L, bool T, bool B, XlLineStyle style=xlContinuous, XlBorderWeight Width=xlThin,XlColorIndex Color=xlColorIndexAutomatic); | Установка границы ячеек |
XlRunExcel(); | Запуск Excel |
XlNewBook(); | Создать новую книгу, выбрать первый лист |
XlOpenBook( const char * FileName); | Открыть книгу, выбрать первый лист |
XlSheetSelect(short Index); | Выбрать лист |
XlCommit(); | Подтвердить изменения |
XlSetMinMaxInt(const int Rows,const int Cols); | Установить область кэширования |
char * XlGetMinMax(); | Получить область кэширования |
void XlSetMinMax ( const char * Val); | Установить диапазон ячеек для кэширования |
const char * XlGetCell(int Row, int Col); | Получить значение ячейки |
void XlPutCell(int Row, int Col, const char * Val); | Установить значение ячейки |
XlSave (); | Сохранить |
XlSaveAs (const char *Val); | Сохранить как |
XlClose (); | Закрыть текущую книгу |
XlCloseExcel (); | Закрыть Excel |
XlSetParams(char* Cells, XlHAlign HorAl=xlHAlignGeneral, XlVAlign VerAl=xlVAlignBottom, bool Warp=false, int Orient=0,bool Ident=false,bool Shrink=false, bool Merge=false); | Установить параметры ячейки |
XlSetColWidth(char *Col,int Width); | Установить ширину столбца |
XlSetRowHeight(char *Row,int Height); | Установить высоту строки |
XlDragVPageBreak(XlDirection Dir=xlToRight , long RegionIdx=1); | Установка горизонтальной границы листа |
Xlbool SetView(XlWindowView View=xlPageBreakPreview); | Установка вида |
XlSetPageOrient(XlPageOrientation Orient=xlLandscape); | Установка ориентации листа |
XlSetColorIndex(char *Cells,long Color=6); | Установка цвета |
XlShow(bool Visibility); | Видимость Excel |
XlPrint(char *Printer); | Печать текущей книги |
LoadLib(char * Path), UnloadLib(); | Загрузка\выгрузка библиотеки |
Везде, где не указано явно – функции возвращают bool, true – если функция успешно завершена.
Пример собран на BCB 5.0 в виде консольного приложения, которое конвертирует любую понятную BDE таблицу в XLS без названий столбцов. Предусмотрена пакетная обработка с указанием в имени файла метасимволов «*» и «?». Далее следуют части кода программы, которые относятся к самой DLL. Естественно, что данная утилита будет работать только при наличии BDE, но к сожалению я не смог ее собрать без Runtime Libraries, так, что ей нужны еще и они.
LoadLib( "exceldll.dll" ); //Загружаем библиотеку из текущего каталога XlRunExcel(); //Запускаем COM сервер while ( !done ) //Цикл перебора файлов для преобразования { XlNewBook(); //Создаем новую книгу int iRowCount = 1; while ( !pBDETable->Eof ) //Цикл прохода по всем записям исходной таблицы { for ( int i = 0;i < pBDETable->Fields->Count;i++ ) //Цикл прохода по всем столбцам //Записывем данных в кэш XlPutCell( iRowCount, i + 1, pBDETable->Fields->Fields[ i ] ->AsString.c_str() ); pBDETable->Next(); iRowCount++; } //… XlCommit(); //Обновляем данные в книге из кэша XlSaveAs( m_FileName ); //Сохраняем книгу XlClose(); //Закрываем книгу } XlCloseExcel(); //Останавливаем COM сервер UnloadLib(); //Выгружаем библиотеку |
Для кэширования используется динамический массив C2DstringArray – одномерный массив CStringArray, второе измерение которого, просто содрано с CArray, в остальном данная библиотека – обертка для Excel и ее можно использовать как пример работы с Excel. Собственно, вот две функции, которые этим занимаются:
extern "C" __declspec( dllexport ) BOOL Commit() { if ( Running ) { try { CString RgnStop, Temp; VARIANT v; long Mrow = Cache.GetRows(), Mcol = Cache.GetCols(); div_t D = div( Mcol - 1, 26 ); D.rem++; if ( D.quot == 0 ) RgnStop = ( char ) ( D.rem + '@' ); else RgnStop = D.quot ? NULL : ( char ) ( D.quot + '@' ) + \ D.rem ? NULL : ( char ) ( D.rem + '@' ); Temp.Format( "%S%i", RgnStop, Mrow ); long Idx[ 2 ]; SAFEARRAYBOUND Bnd[ 2 ]; Bnd[ 0 ].lLbound = 0; Bnd[ 1 ].lLbound = 0; Bnd[ 0 ].cElements = Cache.GetRows(); Bnd[ 1 ].cElements = Cache.GetCols(); COleSafeArray mTArray; mTArray.Create( VT_BSTR, 2, Bnd ); VariantInit( &v ); v.vt = VT_BSTR; //Перенос данных из кэша в промежуточный массив. for ( Idx[ 0 ] = 0;Idx[ 0 ] < ( long ) Bnd[ 0 ].cElements;Idx[ 0 ] ++ ) for ( Idx[ 1 ] = 0;Idx[ 1 ] < ( long ) Bnd[ 1 ].cElements;Idx[ 1 ] ++ ) { v.bstrVal = Cache.Values[ Idx[ 0 ] ] [ Idx[ 1 ] ].AllocSysString(); mTArray.PutElement( Idx, v.bstrVal ); SysFreeString( v.bstrVal ); } ( ( Range ) Sheet.GetRange( COleVariant( "A1" ), COleVariant( Temp ) ) ).SetValue( *mTArray ); //*Cache VariantClear( &v ); //mTArray.Destroy(); } catch ( ... ) { return false; } return true; } else return false; } extern "C" __declspec( dllexport ) void PutCell( int Row, int Col, FAR char * Val ) { if ( Running ) { CString S = Val; int t; //Удаляем все управляющие символы. while ( ( t = S.Find( ( char ) 0xd ) ) != -1 ) S.Delete( t ); while ( ( t = S.Find( ( char ) 0xa ) ) != -1 ) S.Delete( t ); while ( ( t = S.Find( ( char ) 0x9 ) ) != -1 ) S.Delete( t ); S.TrimLeft(); S.TrimRight(); Cache.Values[ Row ][ Col ] = S; } } |
В каталоге Export лежат файлы для подключения. Проверено, что работают в VC 6.0, и BCB 5.0.
Для тех, у кого OfficeXP, может, помогут файлы из архива ExcelExports, хотя, сильно сомневаюсь. Нет в нем документированных tlb-шек, чтобы втянуть функции ATL, однако, собранная библиотека работает и с ним, кажется, и с Office 97 работала, но ручаться не буду.
При использовании функций печати необходимо давать время Excel-у напечатать, иначе программа валится с External Exception. Собственно, при работе с любым MS Office-компонентом надо делать небольшие паузы, чтобы до них доходило то, что от них требуется :). Кстати, не следует забывать, что Excel понимает только 512 символов на ячейку.
Библиотека использовалась при экспорте и печати больших объемов данных. Примеры, к сожалению, очень специфические, например, экспорт из ГИС семантических данных с предварительным пространственным анализом :), однако есть небольшая программка на BCB 5.0, которая печатает большое количество xls файлов, и дает возможность продлить жизнь принтеру – делает передышки на 10 минут: PrintXLS.zip.
Замечания и пожелания приветствуются. mailto:saddam@hotmail.ru
Сообщений 7 Оценка 10 Оценить |