Форум » GUI » Работа с Ole из HBWIN » Ответить

Работа с Ole из HBWIN

Andrey: Pasha пишет: [quote]после этого можно перейти на использование класса win_oleAuto из библиотеки hbwin, заменив строку oExcel := CreateObject( "Excel.Application" ) на win_oleCreateObject( "Excel.Application" ) Используя класс win_oleAuto, можно вместо передачи через буфер обмена передавать в Excel всю таблице одним вызовом __oleVariantNew() В принципе передача через буфер обмена фрагментами по 20к тоже работает быстро, но можно и делать это прямой записью. [/quote] Сделал такую конструкцию: [pre2]#xcommand TRY => BEGIN SEQUENCE WITH {|__o| break(__o) } #xcommand CATCH [<!oErr!>] => RECOVER [USING <oErr>] <-oErr-> ..... Try oExcel := win_oleCreateObject( "Excel.Application" ) Catch MsgStop( "Excel not available. [" + win_oleErrorText() + "]", "Error" ) Return Nil End[/pre2] В системе, где не установлен Эксель, не работает !!! Прога вылетает далее на обращении к oExcel:WorkBooks:Add()...: Error BASE/1004 No exported method: WORKBOOKS Called from WORKBOOKS(0) Called from BRW4XLSOLE(74) in module: Tsb4xlsOle.prg Как нужно правильно сделать ?

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

Andrey: Вот есть вариант что предлагал Григорий (только я заменил CreateObject) : [pre2] IF ( oExcel := win_oleCreateObject( "Excel.Application" ) ) == NIL MsgStop( "Excel not available. [" + win_oleErrorText() + "]", "Error" ) RETURN Nil ENDIF[/pre2] Можно его использовать, или по другому надо ?

PSP: Ну, эта конструкция сработает, если будет RTE при вызове win_oleCreateObject. А в твоем случае переменная oExcel получает значение NIL, т.е. никакой RTE не возникает. Проверяй значение oExcel.

PSP: Andrey пишет: Вот есть вариант что предлагал Григорий (только я заменил CreateObject) : Можно его использовать, или по другому надо ? Именно так.


Andrey: PSP пишет: Проверяй значение oExcel. А при отсутствии Экселя переменная oExcel := win_oleCreateObject( "Excel.Application" ) действительно равна NIL !

Dima: Andrey пишет: Можно его использовать, или по другому надо ? Хотя бы как в этой теме Start_Excel (только его надо переделать под твои нужды) http://clipper.borda.ru/?1-4-0-00000876-000-0-0-1373554002

Andrey: PSP пишет: Именно так. СПАСИБО !

Andrey: __oleVariantNew() - это что то .... Таблица из 25000 строк в Эксель экспортируется за 8 сек. Стандартный метод ExcelOle() делает эту операцию за 58 сек.

Andrey: Есть ли возможность перенести код из Экселя:[pre2] cRange := "A" + LTrim(Str(nStart))+":" + Chr( 64 + nColDbf) + LTrim( Str( nLine -1) ) oRange:=oSheet:Range(cRange):Value := __oleVariantNew( WIN_VT_VARIANT, aSet, nIndexaSet, nColDbf ) [/pre2] для Ворда ? Есть ли такой метод в Ворде ?

Pasha: Нет. В ворде есть только методы insertafter/insertbefore, которым можно передать в качестве параметра только текст, а никак не значения типа Variant или массив

Andrey: А как тогда можно ускорить процесс переноса таблицы в Ворд ? Т.е. отказаться от буфера обмена...

Pasha: Думаю, что через буфер обмена как раз и будет самый быстрый способ. Не по ячейкам же заносить текст.

Andrey: А если типа так сделать:[pre2] var range = doc.Paragraphs(doc.Paragraphs.Count).Range; range.Text = "1,data12,data13\n"+ "1,data22,data23\n"+ "1,data32,data33\n"+ .......... "1,data22,data23\n"+ "1,data32,data33\n"; var table = range.ConvertToTable(",",1,3);[/pre2] https://msdn.microsoft.com/ru-ru/vba/word-vba/articles/range-converttotable-method-word Быстрее будет, чем через буфер обмена ?

Pasha: Andrey пишет: Быстрее будет, чем через буфер обмена ? Я не пробовал ни через буфер обмена, ни с помощью этого фокуса. О таком фокусе только что и узнал. Наверное речь тут пойдет уже не о скорости, а о применимости такого метода. Одно дело заполнять уже существующую таблицу с готовым форматированием, и совсем другое - автоматически формировать новую таблицу вызовом метода ConvertToTable. А как же шрифт, выравнивание, границы и прочее ? После автоформирования таблицы еще и задавать необходимые свойства ячеек ? Накладно получится.

Pasha: В word есть такая функция: Преобразовать в таблицу. Это тот же метод ConvertToTable. только с заданием параметров в диалоге. Поиграйся с этой функцией, оцени, насколько она пригодна. На мой взгляд так не очень.

Andrey: Pasha пишет: Одно дело заполнять уже существующую таблицу с готовым форматированием, и совсем другое - автоматически формировать новую таблицу вызовом метода ConvertToTable. А как же шрифт, выравнивание, границы и прочее ? После автоформирования таблицы еще и задавать необходимые свойства ячеек ? Накладно получится. В Ворд как то это всё хитро работает, без пробы и не поймёшь. Сейчас уже испытал заполнение таблицы:[pre2] ////////// таблица с автоподстройкой по ширине странице (вариант 1) ////////////// oTbl:= oWord:ActiveDocument:Tables:Add(oRange,nRowDbf,nColDbf,wdWord9TableBehavior,wdAutoFitContent)[/pre2] и [pre2] ///////// таблица без автоподстройки по ширине странице (вариант 2) //////////// oTbl:= oWord:ActiveDocument:Tables:Add(oRange,nRowDbf,nColDbf,wdWord8TableBehavior,wdAutoFitFixed)[/pre2] Всё равно потом приходиться менять ширину колонок таблицы. Напрямую - как ширина колонок в таблице Tsbrowse (источник данных) сделать нельзя, так как экспорт в Ворд задаю как правило другим размером шрифта. Из за этого и приходиться пропорционально ставить ширину колонок в Ворде всегда. Эта операция быстрая. Вот что касается переноса шрифтов, цвета из таблицы Tsbrowse (источник данных) в документ Ворда, то это да - операция "тормоз". Пройтись по каждой ячейки таблицы Tsbrowse потом перенести в Ворд - ! А если 10 тыс.записей таблица ? Тушите свет. Но есть вариант ускорения. Испытал уже на Экселе и Ворде. В Экселе вообще это быстро происходит. Таблица из 1000 строк. [pre2]HBOLE.LIB экспорт таблицы через буфер обмена одним шрифтом - 00:00:03 HBOLE.LIB экспорт таблицы и перенос цветов и фонтов каждой ячейки - 00:00:44 HBWIN.LIB экспорт таблицы по 100 строк __oleVariantNew() одним шрифтом - 00:00:00 HBWIN.LIB экспорт таблицы и перенос цветов и фонтов по строкам/блокам - 00:00:06[/pre2] В Ворде чутот помедленнее происходит, да и ещё не доделал...

Pasha: Я в word обычно делаю в бланке таблицу с одной (или несколькими) строками с уже готовым форматированием, а затем добавляю нужное мне количество строк вызовом метода InsertRowsBelow().

Andrey: Сделал тест для Ворда. Таблица из 1000 строк. [pre2]HBOLE.LIB экспорт таблицы через буфер обмена одним шрифтом - 00:00:10 HBOLE.LIB экспорт таблицы и перенос цветов и фонтов каждой ячейки - 00:40:44 [/pre2] Т.е. 40 минут требуется для того чтобы перенести цвета и фонты на таблицу из 1000 строк. Ужас сколько времени.

Pasha: Андрей, я посмотрел ваш пример работы с Excel Маленький совет по оптимизации Такой код: oSheet:Cells( nLine, nColHead ):Value := uData oSheet:Cells( nLine, nColHead ):Font:Name := aFont[ 1 ] oSheet:Cells( nLine, nColHead ):Font:Size := aFont[ 2 ] oSheet:Cells( nLine, nColHead ):Font:Bold := aFont[ 3 ] можно написать немного по другому: oRange := oSheet:Cells( nLine, nColHead ) oRange:Value := uData oFont := oRange:Font oFont:Name := aFont[ 1 ] oFont:Size := aFont[ 2 ] oFont:Bold := aFont[ 3 ] В первом случае будет 4 обращения к oSheet, 4 вызова метода Cells, 4 промежуточных обращения к Range, 3 обращения к Font, и по одному к Value, Name, Size, Bold Во в втором случае - все по одному. Обращение к объектам и вызов методов ole - это межпрограммное взаимодействие, а это самая медленная операция. Различия по скорости при выполнении в первом и втором случае думаю очевидны.

Pasha: Andrey пишет: Т.е. 40 минут требуется для того чтобы перенести цвета и фонты на таблицу из 1000 строк. Ужас сколько времени. Можно же эти действия делать не для каждой ячейки отдельно, а выделить некую область (например, колонку таблицы, одну или несколько), и устанавливать для нее соответствующие свойства. Или установить свойства по умолчанию для всей таблицы, а затем менять свойства только тех ячеек, если их значения отличны от значений по умолчанию. Значения же самих ячеек задавать через вставку из буфера обмена.

Pasha: В сырцах TSBrowse есть такое формирования адреса ячейки для Excel: cRange := Chr( 64 + ::aSuperHead[ nCol, 1 ] - nVar ) + LTrim( Str( nLine ) ) + ":" + ; Chr( 64 + ::aSuperHead[ nCol, 2 ] - nVar ) + LTrim( Str( nLine ) ) В том случае, когда номер колонки больше чем 26, адрес будет неправильный. Я для таких целей использую функцию ниже: Function ExcelAdr(nRow, nCol) Return if(nCol>26,Chr(Int((nCol-1)/26)+64),'')+Chr((nCol-1)%26+65) + LTrim(Str(Int(nRow))) и до кучи еще одну функцию (для адреса диапазона ячеек): Function ExcelAdr2(nRow1, nCol1, nRow2, nCol2) Return ExcelAdr(nRow1, nCol1) + ':' + ExcelAdr(nRow2, nCol2)



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