Форум » GUI » экспорт в Excel (тормоза) » Ответить

экспорт в Excel (тормоза)

gustow: Не пойму, в чем причина... Объясните, братцы, "тупому" :) ---- делаю экспорт в Excel (база с лекарствами) .... oExcel := TOleAuto():New( "Excel.Application" ) oExcel:Visible := .F. oLibros := oExcel:Get( "WorkBooks" ) oLibro := oLibros:Add() oHoja := oExcel:Get( "ActiveSheet" ) oHoja:Cells:Font:Name := "Arial" oHoja:Cells:Font:Size := 10 row0:=3 pbi:=1 ... do while .not. AFTG_X->(eof()) // AFTG_X - база, из которой экспортирую (лекарства, цены...) // (aftg_fi - массив макросов для выводимых выражений) oHoja:Cells( row0+pbi, 1 ):Value := " " for iii:=1 to 20 do case case iii=9 // цена oHoja:Cells( row0+pbi, iii ):Value := strtran( str(&(aftg_fi[iii]), 11, 2), ".", ",") oHoja:Cells( row0+pbi, iii ):Set( "NumberFormat", "#######0,00" ) oHoja:Cells( row0+pbi, iii ):HorizontalAlignment := XL_RIGHT case iii=11 // сумма oHoja:Cells( row0+pbi, iii ):Value := strtran( &(aftg_fi[iii]), ".", ",") oHoja:Cells( row0+pbi, iii ):Set( "NumberFormat", "##########0,00" ) oHoja:Cells( row0+pbi, iii ):HorizontalAlignment := XL_RIGHT otherwise // все остальные - просто взять значение if valtype(&(aftg_fi[iii]))="C" // если это строка oHoja:Cells( row0+pbi, iii ):Value := trim(&(aftg_fi[iii])) else if iii=3 // "Код ЛС" oHoja:Cells( row0+pbi, iii ):Value := &(aftg_fi[iii]) oHoja:Cells( row0+pbi, iii ):HorizontalAlignment := XL_RIGHT else // другие oHoja:Cells( row0+pbi, iii ):Value := &(aftg_fi[iii]) endif endif endcase if valtype(&(aftg_fi[iii]))="N" // если это число - выравнять вправо oHoja:Cells( row0+pbi, iii ):HorizontalAlignment := XL_RIGHT endif next iii AFTG_X->(dbskip()) pbi++ enddo ... // формируем заголовок таблицы oHoja:Cells( 1, 1 ):Value := "Выборка из БД формуляров МУ" oHoja:Cells( 1, 1 ):Font:Size := 12 oHoja:Cells( 1, 1 ):Font:Bold := .T. oHoja:Range("A1:F1"):Merge() oHoja:Range("A1:F1"):HorizontalAlignment := XL_CENTER oHoja:Columns("A:"+ckmax):AutoFit() // ckmax - max.буква (самой правой из заполняемых граф) в Экселе for iii:=1 to 20 if at( str(iii,3), " 2 4 5 6 12 13 14 15" ) > 0 // устанавливаем ширину колонок: // ФТГ (наим.), МНН, Торг, Форма, ЛПУ, Терр., Основание, Цел.Прог. if oHoja:Columns(chr(asc("A")-1+iii)+":"+chr(asc("A")-1+iii)):ColumnWidth > 20 oHoja:Columns(chr(asc("A")-1+iii)+":"+chr(asc("A")-1+iii)):ColumnWidth := 20 endif endif next iii // центрируем данные по Ед.Изм. oHoja:Range("G"+ltrim(str(row0))+; ":G"+ltrim(str(row0+pbi-1))):HorizontalAlignment := XL_CENTER oHoja:Cells( 2, 1 ):Select() oExcel:Visible := .T. oHoja:End() oLibro:End() oLibros:End() oExcel:End() ..... и вроде всё... Непонятка в том, что на небольших выборках (100-200-400) всё отрабатывает "мухой", а при попытке выкинуть 25-30 тысяч - ОППАНЬКИ... и идём нервно курить минут на ..дцать. Комп шуршит там чего-то, трудится... а процесс "нескончаем" (во всяком случае, за "разумное" время - ну пусть ЕДИНИЦЫ минут! а это "рубилово" идет минут 20-30!!!). На всякий - операционная обстановка: Win98, Office-97 [увы -так НАДО!..], Athlon 2400, оперативки 512 [сам знаю, что мало! но на "обычное экселЕние" хватает выше головы] И - заодно уж - подскажите неразумному: не пойму, как пользовать (для того же форматирования в ячейках, к примеру) экселовские константы (xlRight, xlCenter и пр.)? Пишу, например: oHoja:Cells( row0+pbi, iii ):HorizontalAlignment := oExcel:Constants():xlRight (или что-то типа) - и, естественно, бываю послан... Пришлось вверху писать дифайны вроде #define XL_RIGHT -4152 (понимаю, что глупо ["всё уже украдено до нас!"] - но "с налету" не понял еще, как правильно сделать) TsBrowse'овский Excel2() не выходит использовать (по ряду причин) (хотя потестил - получил тот же "нервный перекур"...) Или это "напряги" Эксела?.. Не может переварить 30 тыс.строк "за раз"? Заранее спасибо! "То ли лыжи погнулись... то ли я..." :)

Ответов - 32, стр: 1 2 All

Pasha: Наверное ничего с этим не поделаешь, Эксель так и работает Я когда-то пытался понять причину, и у меня возникло впечатление, что с каждой следующей Row работа идет медленнее. Т.е, чтобы выбрать строку с большим номером N, мелкософтовский продукт лопатит строки 1 .. N-1 Возможно в более поздних версиях это улучшено Но все рано код надо оптимизировать, введя промежуточные переменные вместо oHoja:Cells( row0+pbi, iii ):Value := strtran( str(&(aftg_fi[iii]), 11, 2), ".", ",") oHoja:Cells( row0+pbi, iii ):Set( "NumberFormat", "#######0,00" ) oHoja:Cells( row0+pbi, iii ):HorizontalAlignment := XL_RIGHT надо oCell := oHoja:Cells( row0+pbi, iii ) oCell:Value := strtran( str(&(aftg_fi[iii]), 11, 2), ".", ",") oCell:NumberFormat := "#######0,00" oCell:HorizontalAlignment := XL_RIGHT Метод Set лучше не использовать, с прямым обращением работает лучше

les: Эта тема уже здесь обсуждалась года два назад. Набери в поиске TOleAuto, почитай. Виноват не Excel, а механизм OLE. Тут ничего не поделаешь. Для себя я решил проблему так: 1. Вывод информации в HTML-файл с расширением .xls программой на основе TB2Html от Jovan Bulajic 2. Вызов Excel с параметром <имя файла>. Работает ГОРАЗДО быстрее чем OLE!

Andrey: les пишет: 1. Вывод информации в HTML-файл с расширением .xls программой на основе TB2Html от Jovan Bulajic А можно поподробнее в этом месте, с примером ? Заранее спасибо.


les: Andrey пишет: А можно поподробнее в этом месте, с примером Извини, поподробнее не могу - давно это было. Бери первоисточник здесь: http://www.the-oasis.net/files/general/tb2html.zip Там есть описалово. И ещё здесь: http://www.pctoledo.com.br/forum/viewtopic.php?p=20287&sid=a58d9a3586d06e9baa844bf150f87d18

gustow: Спасибо за помощь! Буду "копать"... А то начальство захотело непременно "экселить" выборки (ну привыкли они!). Кстати: писал сперва, что "затыкается" на 20-30 тыщах... фигвам! те же "тормоза", оказывается, уже после 1-1,5 тысяч. :((

gustow: сыскал решение проблемы! гонит в Эксел "мухой"! в нижележащем примере (на 1000 строк): через OLE - 32 сек :(( ; через буфер обмена ~2 сек. ===================== /* from comp.lang.xharbour: Yes, cell by cell is still slow. I use the clipboard functions when I have more than a screen full of data. Run the code below and you will see the dramatic difference between cell update versus paste from clipboard method. */ #include "minigui.ch" #include "common.ch" FUNCTION MAIN() LOCAL oExcel, oSheet LOCAL nRow LOCAL nCounter, nStart, nSeconds, nSecOle, nSecClip // oExcel = CREATEOBJECT( "Excel.Application" ) oExcel := TOleAuto():New( "Excel.Application" ) oExcel:WorkBooks:Add() // oSheet := oExcel:ActiveSheet oSheet := oExcel:Get("ActiveSheet") // GAL oExcel:Visible := .T. // GAL (добавил - просто чтоб видеть процесс) nRow := 2 oSheet:Cells( nRow, 1 ):Value = "Counter" oSheet:Cells( nRow, 2 ):Value = "Date" oSheet:Cells( nRow, 3 ):Value = "Row" nCounter := 1 nStart := nCounter // ------------------ Start Cell by Cell method nSeconds := seconds() DO WHILE nCounter < 1000 oSheet:Cells( nCounter+nRow, 1 ):Value := nCounter oSheet:Cells( nCounter+nRow, 2 ):Value := date()-nCounter oSheet:Cells( nCounter+nRow, 3 ):Value := nCounter-1 nCounter++ ENDDO nSecOle := seconds()-nSeconds // ------------------ Stop Cell by Cell oSheet:Cells( 1, 5):Value := "OLE time, sec" oSheet:Cells( 1, 6):Value := nSecOle nRow += nCounter+2 oSheet:Cells( nRow, 1 ):Value := "Counter" oSheet:Cells( nRow, 2 ):Value := "Date" oSheet:Cells( nRow, 3 ):Value := "Row" // ------------------ Start Clipboard method nSeconds := seconds() nCounter := 1 nStart := nCounter cMemo := '' DO WHILE nCounter < 1000 // build record cMemo += ltrim( str( nCounter ) ) cMemo += chr(9)+dtoc( date()-nCounter ) cMemo += chr(9)+ltrim( str( nCounter+nRow-1 ) ) cMemo += chr(10) nCounter++ // update sheet every 1000 records or eof() *IF mod( nCounter, 1000 ) = 0 // .or. eof() IF mod( nCounter, 100 ) = 0 // .or. eof() /* почему-то выдает ошибку ("нет такой ф-и" - хотя RTL.LIB подключается) GTSetClipboard( cMemo ) заменил на CopyToClipboard( cMemo ) */ CopyToClipboard( cMemo ) oSheet:Cells( nRow+nStart, 1 ):Select() oSheet:paste() nStart := nCounter cMemo := '' ENDIF ENDDO nSecClip := seconds()-nSeconds // ------------------ Stop Clipboard method oSheet:Cells( 1, 8):Value := "CLIP time, sec" oSheet:Cells( 1, 9):Value := nSecClip oSheet:Cells( 1, 11):Value := "1000 rows" // ------------------ Results on Screen * ? 'Ole = '+ltrim(str(nSecOle)) * ? 'Clip = '+ltrim(str(nSecClip)) * wait * oSheet:Columns( "A:C" ):AutoFit() oSheet:Columns( "A:I" ):AutoFit() // чтобы форматировало и графы тайминга oSheet:Cells( 1, 1 ):Select() // GAL oExcel:Visible := .T. // добавил для закрытия (не было) oSheet:End() oExcel:End() RETURN( nil ) =====================

Петр: gustow пишет: сыскал решение проблемы! гонит в Эксел "мухой"! В некоторых случаях такое решение может быть небезопасным. Есть еще вариант выгрузки в файл с разделителями ( например CHR(9) ) средствами [x]Harbour и импорт средствами Excel.

Pasha: gustow пишет: И - заодно уж - подскажите неразумному: не пойму, как пользовать (для того же форматирования в ячейках, к примеру) экселовские константы (xlRight, xlCenter и пр.)? Ай хэв файлы word.ch и excel.ch с определениями констант Не помню, откуда он у меня взялся, то ли сам делал, то ли скачал где-то. Давно это было Могу выслать

Andrey: Pasha пишет: Ай хэв файлы word.ch и excel.ch с определениями констант Очень надо ! 30195@mail.ru Заранее благодарен

ММК: Петр пишет: В некоторых случаях такое решение может быть небезопасным. В каких? А то я постоянно его ( клипборд) использую.. aDb_cr := Ra->( dbstruct() ) for nCol := 1 to len( aDb_cr ) aadd( aHd, aDb_cr[ nCol, 1 ] ) next aHd[1]:="Попа" oClip := TClipBoard():New() oExc := TExcels():New() oExc :Font("Arial Cyr") oExc :SetFont("Arial Cyr") m := 1 Ra->( dbgotop() ) do while !Ra->( eof() ) cStr := "" for n := 1 to len( aDb_cr ) cField := aDb_cr[ n, 1 ] cStr1 := Ra->&cField if aDb_cr[ n, 2 ] == "N" cStr1 := alltrim( str( cStr1 ) ) endif cStr += cStr1 + if( n # len( aDb_cr ), chr( 9 ), "" ) next if !empty( cStr ) oClip:SetText( cStr ) oExc:SetPos( "A" + alltrim( str( m ) ) ) oExc:Paste() oClip:Clear() m ++ endif Ra->( dbskip() ) enddo

Петр: ММК пишет: В каких? А то я постоянно его ( клипборд) использую.. И все работает прекрасно? Случай первый: пользователь запустил программу, которая экспортирует таким образом базу обьемом так в 1000000 записей. Поскольку он (пользователь) знает, что подобный процесс довольно длительный, а времени терять не хочется, он запускает Word и что-то там начинает делать с использованием очень распространенного метода Copy-Paste. Случай второй: у пользователя установлена какая-то ну уж очень нужная программа, которая висит в трее и все время проверяет, что там в буфере обмена происходит (переводчик, клавиатурный нинзя или шпион, что-то другое ) и производит какие-то операции над содержимым буфера. Случай третий: у клиента установлена не одна, а целых две ваших (или чужих) программы, которые постоянно его ( клипборд) используют и он их запустил на выполнение одновременно.. И так далее.

ММК: Петр пишет: И все работает прекрасно? Вот черт!! :))) Еслиб я сначало прочитал все , что ниже наверняка бы не работало:))) А может каждая прожка использует свой кусочек памяти для клипборда? Хотя не могу с Вами не согласится - если подумать , вроде так . А, буду ждать пока чё не случится. Ну не все же они сразу будут клипбордом пользоваться:)

Петр: ММК пишет: А может каждая прожка использует свой кусочек памяти для клипборда? Я не думаю, что мы должны теряться в догадках msdn довольно подробно все излагает. Еше предлагаю по этой ссылке посмотреть как не надо писать программы http://www.flounder.com/badprogram.htm

ММК: Петр пишет: как не надо писать программы :))) Наверное было бы здорово если бы мы прислушивались ко всем советчикам:)) Но не все советы ... Действительно ( и без всяких догадок) клипборд он и есть клипборд, это всем понятно. Но работа с ним дает хороший результат , а все остальное просто надо иметь в виду:))На всякий случай я не жду заполнения всей страницы, oClip:SetText( cStr ) oExc:SetPos( "A" + alltrim( str( m ) ) ) oExc:Paste() oClip:Clear() Никто от ворда не отказался? :)

krutoff: Посмотрите код вывода таблицы в Excel напрямую - может не стоит париться с Ole?

Vlad04: В Делфи есть примеры (вроде не официальные ) по работе с Ехсел. Все аналогично по работе через буфер.Только там стоит еще процедура очистки и все ок. Сам пробовал, вопросов не было

Andrey: Народ, а за время написания этой статьи не появились ли новые возможности БЫСТРОГО перегона DBF для EXCEL ? Появилась нужда 65 000 записей (25-30 столбцов/полей ) перегнать в простую таблицу EXCEL с простым заголовком. В какую сторону копать, чтобы не наткнутся на Статьи на форуме читал....

Vlad04: А способ, который описывает ММК не пробовал? Он должен быть достаточно быстрый (относительно)

santy: Есть класс texcel разработанный Marcelo Torres. Архив находится по ссылке http://www.the-holms.org/xharbour/addon.htm Grid to Excel Class By Marcelo Torres там используется COPYCLIPBOARD.

Andrey: santy пишет: Есть класс texcel разработанный Marcelo Torres. Что-то даже демка не работает ...



полная версия страницы