Форум » GUI » TsBrowse в Минигуи (продолжение) » Ответить

TsBrowse в Минигуи (продолжение)

Vlad04: TsBrows определяется в виде строки ПАРМЕТРОВ объекта и их значений К примеру [quote] DEFINE TBROWSE oBrw2 ; AT 60,450 ; ALIAS cAlias ; OF Form1 ; WIDTH 330 ; HEIGHT 340 ; FONT "Verdana" ; SIZE 9 ; ON DBLCLICK CopyRec(); ON GOTFOCUS fModelo_Hab(2) ; AUTOFILTER ; CELLED EDIT; VALUE nRec; GRID [/quote] Здесь я собрал параметры из разных tBrows Можно или нет и какие парметры заменить выражением ( и каким) ? oBrw2:.... oBrw2:....

Ответов - 170, стр: 1 2 3 4 5 6 7 8 9 All

SergKis: Haz пишет метод работает. Я о том что просто не пользуюсь им. Я тоже не пользуюсь, но с тем что работает, не соглашусь. Если фонты по блоку кода - валится, нет footer вывода ... т.е. для того чтобы заработал, надо делать спец. отображение тсб. с изменениями, простенький вывод есть без адо, длл и др. спец.оборудования.

Vlad04: Tsb_seek ИЗ примеров c:\MiniGUI\SAMPLES\Advanced\Tsb_seek\ Сегодня обратил на такую странность в отображении. Если стрелкой прокручивать бровс вниз, то экран заполняется одинаковыми данными, не обновляется.

Andrey: Vlad04 пишет: то экран заполняется одинаковыми данными Наверное залипла последняя запись в таблице. Такое бывает часто. Нужно добавить разрыв в конец таблицы. Был бы подвал в конце таблицы, можно было бы воспользоваться функцией [pre2]oBrw:SetNoHoles() // убрать дырку внизу таблицы[/pre2]


Vlad04: Помогло , без подвала

Vlad04: Но не во всех случаях. Помогло добавить DEFINE TBROWSE Br_zaw AT 10, 1 OF o_test ALIAS "test" WIDTH (zox/2)-10 HEIGHT (zoy-150) ON CHANGE {||inkey(0.03),CorrectionFirstLast( Br_zaw )} CorrectionFirstLast - где то здесь описывается

Andrey: Vlad04 пишет: CorrectionFirstLast Выкинь эту функцию и забудь про неё ! Её дорабатывать нужно, я тоже её использовал, в каких то случаях помогает, в других вообще мешает. Наz советовал её не пользоваться. Делай высоту таблицы на 1-2 пикселя больше чем высота всех отображаемых ячеек. Это SergKis так рекомендует. У меня залипание пропало в таких случаях.

SergKis: Vlad04 пишет Но не во всех случаях если так[pre2] END WINDOW br_f:SetNoHoles(3) br_zaw:SetNoHoles(3) br_f:enabled(.f.) [/pre2]

Vlad04: SergKis br_zaw:SetNoHoles(3) Очень хорошо ! А (3) , что означает ? И вообще, что этот метод делает ?

SergKis: Vlad04 пишет что этот метод делает ? Метод убирает дырку в низу таблицы, распределяя разницу между присутствующими заголовками\подвалами, если их нет, есть только строки, то подправит размер тсб по высоте [pre2] METHOD SetNoHoles( nDelta, lSet ) CLASS TSBrowse LOCAL nH, nK, nHeight, nHole DEFAULT nDelta := 2, lSet := .T. ... [/pre2] nDelta := 2 - поправка для расчетов разницы lSet := .F. - рассчитает величину дырки, вернет из метода не меняя размер

Andrey: Делаю таблицу выбора по базе. Создаю колонки: [pre2] // создать 1-ю колонку ADD COLUMN TO oBrw2 HEADER "Номер"+CRLF+"графы" ; DATA FieldWBlock( "ID", Select() ) ; SIZE nWidth1 PICTURE "@Z 999" ; ALIGN DT_CENTER,DT_CENTER,DT_CENTER // создать 2-ю колонку ADD COLUMN TO oBrw2 HEADER "Наименование"+CRLF+"графы в карточке" ; DATA FieldWBlock( "FHEADER", Select() ) ; SIZE nWidth2 ; ALIGN DT_LEFT,DT_CENTER,DT_LEFT // создать 3-ю колонку ADD COLUMN TO oBrw2 HEADER "Печать"+CRLF+"в таблице" ; DATA FieldWBlock( "VIEW", Select() ) ; SIZE nWidth3 ; CHECKBOX ; // Editing with Check Box ALIGN DT_CENTER, DT_CENTER ; EDITABLE MOVE DT_MOVE_DOWN oBrw2:aColumns[3]:bPrevEdit := {|| CheckField(), TRUE } // проверка до ввода .... // --------- заменяем колонку CHECKBOX на свои картинки --------- oBrw2:aCheck := { LoadImage("CheckT28"), LoadImage("CheckF28") } ....[/pre2] Таблица не простая, для ID=0 делаются заголовки в таблице цветом и запрет на редактирование. Нужно убрать в таблице показ чекбокса по условию ID=0. Как это сделать ? Вот картинка:

Vlad04: if i =3 ADD COLUMN TO Brw_1 DATA {|| iif(Dogovor->Vid > 0,aVidD[Dogovor->Vid],' Нет ' )} .... ... А попробуй при формировании колонки установить условия показа чекбокса от значения ID. Т.е. вместо показа чекбокса можешь вывести пустое место.

Andrey: Vlad04 пишет: А попробуй при формировании колонки установить условия показа чекбокса от значения ID. Т.е. вместо показа чекбокса можешь вывести пустое место. Покажи как: [pre2] ADD COLUMN TO oBrw2 HEADER "Печать"+CRLF+"в таблице" ; DATA FieldWBlock( "VIEW", Select() ) ; [/pre2]

Haz: Andrey пишет: Таблица не простая, для ID=0 делаются заголовки в таблице цветом и запрет на редактирование. Нужно убрать в таблице показ чекбокса по условию ID=0. Как это сделать ? Не меняя класса TBROWSE можно только пытаться по условию ID=0 подменить ::aCheck в блоках ::bOnDrawLine и ::bOnDraw соответственно , а по условию ID <> 0 восстанавливать. Но думаю грязновато работать будет. В смысле работать будет , но с глючком. Оптимально - в классе дописать возможность ::aCheck назначать блок кода и добавить проверки на hb_isBlock( ::aCheck ). тогда картинки чекбокса можно будет менять на лету , в том числе и задавать NIL

Andrey: Haz пишет: Не меняя класса TBROWSE можно только пытаться по условию ID=0 подменить ::aCheck в блоках ::bOnDrawLine и ::bOnDraw соответственно , а по условию ID <> 0 восстанавливать. Но думаю грязновато работать будет. В смысле работать будет , но с глючком. Вот я с этим и бился... Решил сделать по другому:[pre2] LOCAL hImgTrue := LoadImage("CheckT28"), hImgFalse := LoadImage("CheckF28") ..... // создать 3-ю колонку ADD COLUMN TO oBrw2 HEADER "Печать"+CRLF+"в таблице" ; DATA FieldWBlock( "VIEW", Select() ) ; // эту строку наверное можно выкинуть ? SIZE nWidth3 ; NAME VIEW BITMAP ; ALIGN DT_CENTER, DT_CENTER ; EDITABLE MOVE DT_MOVE_DOWN oBrw2:aColumns[3]:bPrevEdit:= {|| CheckField(), FALSE } // проверка до ввода oBrw2:aColumns[3]:uBmpCell := {|| IF( (oBrw2:cAlias)->ID == 0, '' , IF( (oBrw2:cAlias)->VIEW , hImgTrue, hImgFalse ) ) } oBrw2:aColumns[3]:bData := {||Nil} oBrw2:aColumns[3]:cData := '{||Nil}' oBrw2:aColumns[3]:nAlign := nMakeLong( DT_CENTER, DT_CENTER )[/pre2]

Haz: Andrey пишет: Решил сделать по другому: вполне нормальное решение отказаться от чекбокса и использовать подмену ::bData и ::uBmpCell и главное оно универсально

Vlad04: Andrey Покажи как: ADD COLUMN TO Brw_1 DATA {|| iif(Dogovor->Vid <> 0,aVidD[Dogovor->Vid],' Нет ' )} ... Вариант не для ПРЯМОГО РЕДАКТИРОВАНИЯ.

Haz: Vlad04 пишет: Вариант не для ПРЯМОГО РЕДАКТИРОВАНИЯ. Это скорее вариант не прямой выборки. Для редактирования ему как до луны. Но это ни в коем случае не упрёк. Как работает блок выборки_записи, все знают со времен клиппера, и допилить - не вопрос. PS. сам часто использую этот прием, ступор иногда возникает при инкрементальном поиске по таким колонкам

Dima: Haz пишет: Для редактирования ему как до луны Да уж

Andrey: Andrey пишет: oBrw2:aColumns[3]:bPrevEdit:= {|| CheckField(), FALSE } // проверка до ввода Редактировать нужно ТОЛЬКО ТРЕТИЙ столбец. Мышка и Enter в CheckField() прекрасно с этим справляются. Там ещё параллельно в другую базу пишется... [pre2]//////////////////////////////////////////////////////////// STATIC FUNCTION CheckField() LOCAL cAlias := oBrw2:cAlias // "XLS_HEADER" LOCAL nID := M->oBrw2:nAt // номер строки и номер для поиска LOCAL aMenuHead := aStatMenuPrn[nID] // строка массива меню LOCAL lVal, cNameField := "VIEW" IF (cAlias)->ID == 0 // выбор здесь не предусмотрен RETURN .F. ENDIF lVal := (cAlias)->( FIELDGET( FIELDNUM(cNameField) ) ) (cAlias)->( FIELDPUT(FIELDNUM(cNameField), !lVal ) ) DO EVENTS IF (cAlias)->VIEW == .T. // значит нужно добавить запись в БД:XLS_GALKI SELECT("XLS_GALKI") APPEND BLANK XLS_GALKI->FNN := RECNO() XLS_GALKI->FNAME := (cAlias)->FHEADER XLS_GALKI->FALIAS := aMenuHead[2] XLS_GALKI->FPOLE := aMenuHead[3] XLS_GALKI->FPICT := aMenuHead[4] XLS_GALKI->FTYPE := aMenuHead[5] XLS_GALKI->FKOD := aMenuHead[6] XLS_GALKI->FRECNO := nID // номер записи из XLS_HEADER->ID XLS_GALKI->FLETTER := CHR(64 + XLS_GALKI->FNN ) ELSE // значит нужно удалить запись в БД:XLS_GALKI SELECT("XLS_GALKI") LOCATE FOR XLS_GALKI->FRECNO == nID IF FOUND() DELETE PACK ENDIF DO WHILE !EOF() XLS_GALKI->FNN := RECNO() XLS_GALKI->FLETTER := CHR(64 + XLS_GALKI->FNN ) SKIP ENDDO ENDIF oBrw1:Reset() oBrw1:Refresh(.T.) oBrw2:DrawSelect() SELECT(cAlias) RETURN .T.[/pre2]

Vlad04: Haz Такую конструкцию использую только для информационных столбцов, прямое редактирование использую для простых таблиц, типа справочник (1-2 колонки), что сложней - в отдельной форме.

Vlad04: А есть примеры многострочных бровсов ? Вариантов может быть несколько: в одной строке - Поле 1 - Поле 2 или - Часть1(Поле 1) - Часть2(Поле 1)

SergKis: Vlad04 пишет А есть примеры многострочных бровсов ? сделать пример не сложно Tsb_array_2 demo.prg[pre2] STATIC FUNCTION CreateDatos() ... FOR i := 1 TO k aDatos[ i ] := { " ", ; // 1 i, ; // 2 ntoc( i ) + CRLF + "_123", ; // 3 Date() + i, ; // 4 ... [/pre2]

Haz: SergKis пишет: А есть примеры многострочных бровсов ? В примерах есть только вариант с широкими строками , где в ячейке может быть многострочный текст. Такой вариант удобно использовать в виде календарика с событиями , привычно смотрится и можно каждую ячейку развернуть в окно с подробным описанием. Все остальные случаи многострочного бровса можно поделить условно на 2 вида : 1) когда заранее готовятся многострочные данные для скармливания бровсу , это может быть подготовка массива, временной базы или результат SQL запроса к таблице. Получаем многострочность в однострочном бровсе. 2) когда под задачу пишется свой Skipper() и FieldWblock(). Этот путь не простой , но проходимый. Я использую вариант 1 , нет желания и времени возиться с 2 PS дополню вариант 1 предпочтителен еще и тем что позволяет фильтровать ( срывать подразделы )

Vlad04: Haz В примерах есть только вариант с широкими строками , где в ячейке может быть многострочный текст. Такой вариант удобно использовать в виде календарика с событиями , привычно смотрится и можно каждую ячейку развернуть в окно с подробным описанием. О каких примерах конкретно идёт речь ?

Haz: Vlad04 пишет: О каких примерах конкретно идёт речь ? О базовом примере MiniGUI\SAMPLES\Advanced\TsBrowse\demo.exe Menu -> Samples on Windows -> Sample 4 -> колонка Address

Andrey: Всем привет. Использую многострочный Tsbrowse (из 2х строк). Всё работает отлично. При экспорте в Эксель высота строк ставиться почему то как одна строка. И приходиться твблицу в Экселе вручную высоту править... Убийственная работа. Нельзя там в исходниках исправить высоту ячеек, сделать её зависимой от высоты таблицы ячеек ?

Vlad04: в Эксель высота строк ставиться почему то как одна строка. А у Эксель для данного столбца нельзя ли установить свойство - ПЕРЕНОСИТЬ ПО СЛОВАМ. Тогда Эксель будет сам высоту строк править

Andrey: Vlad04 пишет: А у Эксель для данного столбца нельзя ли установить свойство Я там исходник глянул .... и ничего не понял...

Haz: Andrey пишет: Я там исходник глянул .... и ничего не понял... Надо внимательнее глядеть . Вся запись в методе ::Excel2() идет в так называемом двоичном формате BIFF. Этот формат был основным форматом Excel до 2007 года. Дальше используется Open XML , а BIFF поддерживается только с целью совместимости. Именно с форматом BIFF связаны все ограничения Excel до 2007 года ( одно из них это 65535 строк , но есть много других) Так вот про внимательность, Excel в методе заполняется в цикле через вызов BiffRec( opCode , ... ), где этот самый opCode - константа Excel по кодам операций ( в инете ссылок полно ). В самой функции BiffRec() отсутствует обработка кода 8 ( код операции ROWHEIGHT ) и 37 ( код операции DEF_ROWHEIGHT). Видимо автору метода она была не нужна. Но это не мешает ее туда добавить самостоятельно. Функция живет в TSColumn.prg и ее содержимое понятно без каких либо тайных знаний. PS Подарок тем , кому лень искать константы: http://www.purebasic.fr/english/viewtopic.php?p=267584 PPS Добавлю свое мнение, которое может не совпадать со мнгоми форумчанами. Формат BIFF считаю устаревшим, и не уверен что его следует развивать библиотеке. В 2007 микрософт формально его похоронил перейдя на xml. В исходнках harbour есть что то типа xlsxml. Пишу с мобильного и точно не помню. Уверен xml более перспективен как экспорт данных, т. к. микрософт теперь его использует в основе движка. И вот в xml готов поучаствовать. Тестовые примеры выгрузки в Excel из harbour у меня идут отлично и по скорости и по оформлению. Прикрутить класс к Tsbrowse, например как :Excel3() считаю вопросом времени (свободного времени)

Haz: И в новое сообщение тоже PPS Добавлю свое мнение, которое может не совпадать со мнгоми форумчанами. Формат BIFF считаю устаревшим, и не уверен что его следует развивать библиотеке. В 2007 микрософт формально его похоронил перейдя на xml. В исходнках harbour есть что то типа xlsxml. Пишу с мобильного и точно не помню. Уверен xml более перспективен как экспорт данных, т. к. микрософт теперь его использует в основе движка. И вот в xml готов поучаствовать. Тестовые примеры выгрузки в Excel из harbour у меня идут отлично и по скорости и по оформлению. Прикрутить класс к Tsbrowse, например как :Excel3() считаю вопросом времени (свободного времени)

Andrey: Haz пишет: Но это не мешает ее туда добавить самостоятельно. [pre2]* ============================================================================ * FUNCTION BiffRec() Version 9.0 Nov/01/2009 * Excel BIFF record wrappers (Biff2) * ============================================================================ Function BiffRec( nOpCode, uData, nRow, nCol, lBorder, nAlign, nPic, nFont ) ....[/pre2] Блин, да это только для шаманов ....

Haz: Andrey пишет: Блин, да это только для шаманов Шаманом себя не считаю, но проблем не вижу. В понед гляну с компа. И прочитай мое последнее сообщение по поводу BIFF

Andrey: Haz пишет: И вот в xml готов поучаствовать. Тестовые примеры выгрузки в Excel из harbour у меня идут отлично и по скорости и по оформлению. Прикрутить класс к Tsbrowse, например как :Excel3() считаю вопросом времени (свободного времени) Очень хочется иметь этот новый класс в исходниках. Я так же готов поучаствовать в тестировании и настройке этого класса, по мере своей квалификации.

Vlad04: Haz Тестовые примеры выгрузки в Excel из harbour у меня идут отлично Это не OLE и Excel 2007 и выше? Тогда может в начале с примерами ознакомить ? Выгрузка в Tsbrows частный случай.

Vlad04: из Tsbrows

Haz: Vlad04 пишет: Это не OLE и Excel 2007 и выше? Тогда может в начале с примерами ознакомить ? Выгрузка в Tsbrows частный случай. Это не OLE, до 2007 микрософт отстегивал стороннему разработчику за использование xml позже написал свою компоненту. Поддержка xml была и до 2007. Примеры все в исходниках харбура. Знакомся на здоровье, все в свободном доступе. Ссылки на исходники есть в разделе Harbour на этом форуме

Dima: Andrey пишет: Я так же готов поучаствовать в тестировании и настройке этого класса, по мере своей квалификации. +1 Потестю на древнем Excel 2003

Haz: Dima пишет: Потестю на древнем Excel 2003 Так ты уже потестил)

Dima: Haz пишет: Так ты уже потестил) Это было не с Минигуи

Haz: Andrey пишет: Блин, да это только для шаманов .... Глянул с компа. Какие шаманы ??? примитив в 4 строки кода Чтоб ::Excel2 был зависим от высоты строк бровса нужно всего - то 1) перейти по ссылке которую я давал и найти там установку высоты строки по умолчанию увидеть там код команды, ее длину и прочитать про размерность единицы высоты [pre2] DEFHEIGHT.DEF_ROWHEIGHT_RECORD DEFHEIGHT\opcode = 37 DEFHEIGHT\length = 2 [/pre2] 2) Открыть исходник BiffRec() и после команды 36 ( ну чтоб попорядку ) вставить нашу 37 [pre2] Case nOpCode == 37 // DEF_ROWHEIGHT_RECORD record Default nCol := nRow cHead := I2Bin( 37 ) + ; // opCode I2Bin( 2 ) // body length cBody := I2BIN( uData ) [/pre2] 3) Открыть исходник Excel2() и задать высоту строк по умолчанию по высоте строки бровса ( про размерность по ссылке конечно прочитали - поэтому *20, но мне точнее показалось на 15 ) [pre2] FWrite( nHandle, BiffRec( 66, GetACP() ) ) FWrite( nHandle, BiffRec( 12 ) ) FWrite( nHandle, BiffRec( 13 ) ) FWrite( nHandle, BiffRec( 37 , ::nHeightCell * 20) ) [/pre2] PS Кто тут увидел шаманов

Andrey: Haz пишет: PS Кто тут увидел шаманов Да ты шаман ! Можешь у других спросить... Больше тебя и никто и не написал как делать ! Заодно и подскажи как для шапки таблицы такое же сделать ? А то тоже получается всегда в одну строчку !

Haz: Пересобрал библиотеку hbxlsxml.lib под BCC ( в родной с русским есть глюк) и дополнил свой пример Tsb_cursor выгрузкой в Excel по правой кнопке мышь. Это просто пример, как альтернатива BIFF или OLE Цветная раскраска и формулы поддерживается от автора библиотеки. по ссылке готовый пример, исходник примера и библиотека. исходники самой библы в искать харбуре click here

Haz: Andrey пишет: Заодно и подскажи как для шапки таблицы такое же сделать ? А то тоже получается всегда в одну строчку ! можно перед записью строки заголовков задать высоту по заголовку, а потом перед записью данных задать высоту данных

Andrey: Haz пишет: по ссылке готовый пример, исходник примера и библиотека. исходники самой библы в искать харбуре Пример понятен. Наверное всё таки тестовый пример нужно отдельно для этого делать, с разными типами полей. Или прикрутить этот новый экспорт в пример MiniGUI\SAMPLES\Advanced\Tsb_array_3 Желательно ещё бы сразу в примере задать многострочный Tsbrowse для экспорта. Суперхидер и подвал так же необходим в экспорте. А цвета наверное нужно как то задавать отдельным параметром в ЭКСПОРТ, тира 0-черно/белый, 1-цвет передать с Tsbrowse, 2-задать свои отдельные цвета. Это как предложение по цвету.

Haz: Andrey пишет: прикрутить этот новый экспорт в пример MiniGUI\SAMPLES\Advanced\Tsb_array_3 Я продемонстрировал сам механизм использования xmlxls. По которому можно примерно оценить скорость выгрузки 1000 строк и простейшее оформление. Конечно в этом механизме есть и форматы ячеек и формулы и использование цвета, объединения, задавать шрифты и пр. Конечно не все, но многое в нем есть. Сам по себе экспорт бровса в оригинальном виде в Excel, это как полуфабрикат. Выгрузка документа должна быть законченной, включая оформление. Под офомлением я понимаю вид документа, а не слответствие листа в Excel внешнему виду бровса. Оформление должно включать все реквизиты документа, а не только табличку. Сейчас лучшее оформление можно получить через OLE, но скорость оставляет желать лучшего. Понятно что можно выкинуть в олю массив, а потом наряжать лист, так и это не быстро. Наводить красоту можно и через тот же BIFF, но нет библиотеки, а в кодах по спецификации BIFF можно потеряться. В этом плане xmlxls это компромис с хорошей скоростью и возможностью рисовать почти как хочешь. Я на нем сделал несколько отчётов и могу сказать, что это именно альтернатива OLE для рисования на листе Excel. Теперь что касается выгрузки именно бровса в Excel. Встраивать сам класс в исходники TSBROWS скорее всго не рационально т. к. бровс потребует библиотеку xmlxls для сборки. А вот отдельный пример экспорта бровса сделать конечно можно. Подвалы, суперхидеры, шрифты и цвета, это все решаемо. Но делать из какого либо примера винегрет, тоже не вариант. Так что только отдельный и небольшой, чтоб было понятно что где.

Dima: Haz пишет: Встраивать сам класс в исходники TSBROWS скорее всго не рационально т. к. бровс потребует библиотеку xmlxls для сборки. +1

Andrey: Haz пишет: Но делать из какого либо примера винегрет, тоже не вариант. Так что только отдельный и небольшой, чтоб было понятно что где. Хорошо, я тогда сделаю пример таблицы для этого. А там далее уже поможешь... Возвращаюсь к вопросу: Haz пишет: можно перед записью строки заголовков задать высоту по заголовку, а потом перед записью данных задать высоту данных Можно для Григория (чтобы он добавил в библиотеку) дать код для этого ?

Haz: Andrey пишет: Хорошо, я тогда сделаю пример таблицы для этого. А там далее уже поможешь... договорились

Haz: Haz пишет: Можно для Григория (чтобы он добавил в библиотеку) дать код для этого ? Да можно конечно. Тем более, что это и так понятно по коду Excel2 куда что вставлять. Вопрос, а надо ли из простого экспорта, городить копию бровса?

Andrey: Haz пишет: Вопрос, а надо ли из простого экспорта, городить копию бровса? Нет не надо, надо только 2 позиции: 1) Просто если шапка таблицы (а это часто бывает) состоит из нескольких строк, то при экспорте надо учитывать высоту шапки. 2) Если данные таблицы 2-3 строки, то при экспорте тоже учитываем высоту данных таблицы. У меня несколько таблиц есть с такими параметрами, да я думаю и другие порадуются более корректному экспорту.

Haz: Andrey пишет: Нет не надо, надо только 2 позиции: [pre2] В :Excel2() после этого FWrite( nHandle, BiffRec( 66, GetACP() ) ) FWrite( nHandle, BiffRec( 12 ) ) FWrite( nHandle, BiffRec( 13 ) ) Следующую строку убираем ( если кто то ужк успел ее суда добавить ) // FWrite( nHandle, BiffRec( 37 , ::nHeightCell * 15) ) После этого ... If ! Empty( cTitle ) cTitle := StrTran( cTitle, CRLF, Chr( 10 ) ) nAlign := If( Chr( 10 ) $ cTitle, 5, 1 ) FWrite( nHandle, BiffRec( 4, cTitle, 0, 0,, nAlign ) ) nLine := 3 EndIf Добавляем это FWrite( nHandle, BiffRec( 37 , ::nHeightHead * 15) ) А После этого ... If bPrintRow != Nil .and. ! Eval( bPrintRow, nRow ) ::Skip( 1 ) Loop EndIf Добавляем это If nRow == 2 FWrite( nHandle, BiffRec( 37 , ::nHeightCell * 15) ) END [/pre2] Andrey пишет: У меня несколько таблиц есть с такими параметрами, да я думаю и другие порадуются более корректному экспорту. может кто и порадуется , а по мне это просто способ схалявить на выгрузке таблицы. НУ чтоб юзер отстал , или для себя бумажку распечатать надо. такую выгрузку до ума еще доводить и доводить ( к примеру форматы ячеек ставить "процентный" или "финансовый" или как принято в фин отчетности - все отрицательные числа в скобках ) Проще уж сразу выгружать нормально

Haz: для справки; Обнаружил неприятную особенность :aCheck , при задании в качестве картинки хендла картинки из внешней переменной ( в моём случаи PUBLIC ) , повторный вызов TS картинку уже не показывал . Беглый просмотр кода исходников показал что при дестрое TS , так же дестроятся и эти хендлы. Т.е. закрытие бровса убивало PUBLIC переменные с хендлами картинок. Из ситуации вышел без изменения исходников , храня хендлы в самом бровсе через [pre2] __objAddData (oBrw, 'hPic1' ) oBrw:hPic1:= LoadImage("PICTURE1") и oBrw:GetColumn( 'COL1'):aCheck := {oBrw:hPic1, nil } [/pre2]

SergKis: Haz пишет oBrw:GetColumn( 'COL1'):aCheck := {oBrw:hPic1, nil } Почему сразу не делать oBrw:GetColumn( 'COL1'):aCheck := {LoadImage('PICTURE1'), nil } ?

Haz: SergKis пишет: Почему сразу не делать Логично, но не рискнул. При uBmpCell при этом идёт утечка памяти. В aCheck возможно утечка не проявится... тестировать не стал Хотя uBmpCell я вызвал в блоке...

SergKis: Haz пишет При uBmpCell при этом идёт утечка памяти. Как я понимаю, uBmpCell это полностью собственное управление, сам поставил, сам снял\освободил. Остальные свойства доводились "до кондиции"[pre2] If ::aSortBmp != Nil DeleteObject ( ::aSortBmp[ 1 ] ) DeleteObject ( ::aSortBmp[ 2 ] ) EndIf If ::aCheck != Nil DeleteObject ( ::aCheck[ 1 ] ) DeleteObject ( ::aCheck[ 2 ] ) EndIf If Len( ::aColumns ) > 0 For i := 1 To Len( ::aColumns ) If Valtype( ::aColumns[ i ]:aCheck ) == "A" AEval( ::aColumns[ i ]:aCheck, {|hBmp| If( Empty( hBmp ), , DeleteObject( hBmp ) ) } ) EndIf If Valtype( ::aColumns[ i ]:aBitMaps ) == "A" AEval( ::aColumns[ i ]:aBitMaps, {|hBmp| If( Empty( hBmp ), , DeleteObject( hBmp ) ) } ) EndIf Next EndIf [/pre2] Рекомендовал бы, вместо uBmpCell, использовать :aBitMaps с цифровым значением (Tsb_aBitMaps)[pre2] oBrw:GetColumn("FLD1"):aCheck := { LoadImage(".\RES\Print32.png"), NIL } oBrw:GetColumn("FLD2"):aCheck := { LoadImage(".\RES\Save32.png" ), NIL } oBrw:GetColumn("FLD3"):aCheck := { LoadImage(".\RES\Mail32.png" ), NIL } oBrw:GetColumn("FLD4"):aCheck := { LoadImage(".\RES\check1.bmp" ), ; LoadImage(".\RES\check0.bmp") } oBrw:GetColumn("FLD6"):lBitMap := .T. oBrw:GetColumn("FLD6"):aBitMaps := { LoadImage(".\RES\edit_delete.bmp" ), ; LoadImage(".\RES\edit_cancel.bmp" ) } ... oBrw:GetColumn("FLD7"):lBitMap := .T. oBrw:aBitMaps := { LoadImage(".\RES\flag_bel.bmp"), ; LoadImage(".\RES\flag_en.bmp" ), ; LoadImage(".\RES\flag_kaz.bmp"), ; LoadImage(".\RES\flag_ru.bmp" ), ; LoadImage(".\RES\flag_ua.bmp" ) } [/pre2]

Haz: SergKis пишет: Рекомендовал бы, вместо uBmpCell, использовать :aBitMaps Да, согласен спасибо за подсказку. В uBmpCell утечка была именно из-за блока. При каждом DrawLine() инмциализировался новый хендл.

SergKis: SergKis пишет Остальные свойства доводились "до кондиции" Упс. Потерялось однако. В моей версии еще такие строки есть в методе Destroy():[pre2] ... If Len( ::aColumns ) > 0 For i := 1 To Len( ::aColumns ) If Valtype( ::aColumns[ i ]:aCheck ) == "A" AEval( ::aColumns[ i ]:aCheck, {|hBmp| If( Empty( hBmp ), , DeleteObject( hBmp ) ) } ) EndIf If Valtype( ::aColumns[ i ]:aBitMaps ) == "A" AEval( ::aColumns[ i ]:aBitMaps, {|hBmp| If( Empty( hBmp ), , DeleteObject( hBmp ) ) } ) EndIf Next EndIf If Valtype(::aBitMaps) == "A" AEval(::aBitMaps, {|hBmp| If( empty(hBmp), , DeleteObject(hBmp) ) }) EndIf ... [/pre2] т.е. в тек. версии утечка есть при oBrw:aBitMaps := {LoadImage(...), ...} на колонках утечки нет.

Haz: SergKis пишет: т.е. в тек. версии утечка есть при oBrw:aBitMaps := {LoadImage(...), ...} на колонках утечки нет Возможно и а текущей не будет утечки если aBitMaps задавать массивом. Внутренние переменные бровса убьются сборщиком мусора после дестроя самого бровса. А во время работы бровса новые объекты не создаются. В моем же случае было uBmpCell := {¦¦ if( lFllag, Loadimage(), nil)} тоесть при навигации бровса постоянно создаётся новый хендл картинки, не уничтожая старый. GdiPlus при навигации показал утечки. Обнаружил проблему Дима, у него пользователь от скуки гонял курсор вверх вниз и брос падал. С дестроем в твой версии все понятно. Непривычно само поведение - кормишь бровсу переменную, а он ее убивает. Этот момент нужно учитывать. У меня маленькая статусная картинка используется в нескольких модулях и в каждом бровсе, я ее определил в паблик переменной при старте программы сслаюсь на нее везде. т. е. LoadImage() делал один раз. Поскольку aCheck практически не использовал то проблем не видел. Будем считать это особеннстью бровса.

SergKis: Haz пишет В моем же случае было uBmpCell := {¦¦ if( lFllag, Loadimage(), nil)} Это скорее недосмотр кода, т.к. именно для oCol:uBmpCell можно использовать PUBLIC\PRIVATE переменные, т.е. oCol:uBmpCell := {¦¦ if( lFllag, m->hPicture1, nil)} или из массива брать handle image Будем считать это особеннстью бровса Пара LoadImage() -> DeleteObject() для aChecк, aMitMaps как особенность тсб, просто надо учитывать, а усилить поведение, при необходимости, всегда можно, к примеру :aCheck := { 'PICTURE1', Nil } - будет внутри делать LoadImage('PICTURE1') и DeleteObject() при Dectroy() :aCheck := { hPicture1, Nil } - не будет делать ни LoadImage() ни DeleteObject() при Dectroy() для :aBitMaps аналогично. Надо ли ?

Haz: SergKis пишет: aChecк, aMitMaps как особенность тсб, просто надо учитывать я про это же . Пока сам не наткнешься- не поймешь )

gfilatov2002: SergKis пишет: В моей версии еще такие строки в методе Destroy(): Благодарю за исправление Добавил его в текущий код. Кстати, уже готов RC 3 для новой сборки. Кратко, что нового см. ниже [pre2]- The RadioGroup control supports an optional AUTOSIZE clause. - The Report Generator by Roberto Lopez was moved to MiniGUI core. - Added the command CHECK TYPE [ SOFT ] <var1> AS <type1> [ , <var2> AS <type2> [ , <varN> AS <typeN> ] ] (synchronized with Official HMG). - The function HttpConnect was modified to use TUrl and TIpClientHttp classes. - Updated and improved the following libraries: TSBrowse, HbNetIO, SddODBC. - Updated Harbour Compiler 3.2.0dev to a latest Git-version. - Added the new interesting samples and updated some Advanced samples. [/pre2]

Andrey: Haz пишет: А вот отдельный пример экспорта бровса сделать конечно можно. Подвалы, суперхидеры, шрифты и цвета, это все решаемо. Но делать из какого либо примера винегрет, тоже не вариант. Так что только отдельный и небольшой, чтоб было понятно что где. Сделал отдельный пример. Отправил на почту. Ждем что выйдет из под руки мастера !

Haz: Andrey пишет: Ждем что выйдет За пару дней, что нибудь да выйдет.

gfilatov2002: Andrey пишет: Отправил на почту На какую Ничего не пришло...

Haz: gfilatov2002 пишет: На какую Ничего не пришло... Григорий, мне пришло Андрей хочет выгрузку в Excel из бровса в формате XML увидеть. Я так вывожу отчёты из программ. Качество оформления как OLE, скорость выгрузки как BIFF

gfilatov2002: Haz пишет: мне пришло Понял, буду ждать от Вас выгрузку в Excel из бровса в формате XML

Haz: Andrey пишет: Сделал отдельный пример. Отправил на почту. Ждем что выйде Андрей, скинул на почту. Для справки : Под выгрузку немного допиливал библиотеку hbxlsxml, в оригинальной косяки с русским языком и многострочными ячейками в Excel. Библиотека не секрет , могу выложить все исходники. Теперь немного про особенности XML выгрузки . Для выгрузки необходимо сначала определить все возможные форматы ячеек , которые будут на листе экселя. И в момент экспорта ссылаться на них, в примере это видно. Сама выгрузка должна идти заполнением листа сверху - вниз и слева - направо т.е сначала первая строка , потом вторая и так далее , вернуться на первую уже нельзя ( тоже и по колонкам ) И наконец выгрузка бровса - частный случай. Я рисую морду отчету и гружу из DBF ЗЫ В примере не стал трогать Excel3() , которую подправил Сергей, а написал Brw2Xml и вставил ее вызов.

Andrey: Haz пишет: Андрей, скинул на почту. 1) Заголовок таблицы - косяк: размер фонта не тот.[pre2] FUNC Brw2xml( oBrw, cFile, lActivate, hProgress, cTitle ) нужно как сейчас в библиотеке: Excel2( cFile, lActivate, hProgress, aTitle, lSave, bPrintRow ), где aTitle := { cTitle, hFont } // титул со своим фонтом из-за этого я и сделал похожую функцию: Excel3Xml( oBrw, cFile, lActivate, aTitle, lSave ), где aTitle := { cTitle, hFont } // титул со своим фонтом[/pre2] 2) Суперхидера в экспорте НЕТ ! 3) Формат вывода 6-ой колонки не соответствует Tsbrowse 4) Далее нет цветового оформления. Т.е. нужно бы сделать цвета таблицы полностью как в Tsbrowse. Возможно ли такое сделать ? А так - классно получилось ! Haz пишет: Библиотека не секрет , могу выложить все исходники. Это наверное тоже нужно добавить в проект. Пускай Григорий папку отдельно сделает, чтобы были исходники, откуда плясать можно всем. P.S. Судя по правкам в исходнике, у тебя ещё старая версия МиниГуи !

Haz: Andrey пишет: Заголовок таблицы - косяк: размер фонта не тот. Я его и не делал, все для этого есть. Как задать шрифт видно из примера по хидеру и футеру. Опрелить стиль для заголовка дело 3 минут. То же и суперхидер, сделать можно, но зачем? Задачу воспроизводства бровса в Excel один в один, решить то можно, только кому она нужна? Более востребованы быстрые выгрузки в Excel, тем более оформленные как отчёты. Andrey пишет: Формат вывода 6-ой колонки не соответствует Tsbrowse Форматы все задаются в функции XMLSetDefault(), специально задал только 2. Не хочу писать транслятор с форматов PICTURE в форматы Excel. Это отдельное и бесполезное развлечение. Andrey пишет: Далее нет цветового оформления. Т.е. нужно бы сделать цвета таблицы полностью как в Tsbrowse. Возможно ли такое сделать ? Возможно, при условии что цвет задан явно, а не блоком кода. В примере это показано по хидеру и футеру. Кстати твоя выгрузка через Excel2() вообще ничем в этом раскладе, ни шрифтов ни цвета. PS Andrey пишет: Судя по правкам в исходнике, у тебя ещё старая версия МиниГуи ! Там правка только карго касается, не гонюсь сразу обновряться, т. к. некоторые библиотеки харбура приходится обновлять (в поставке они старые) Да и сюрпризы в отлаженном коде после обновлений иногда бывают. Обновляюсь когда есть время на ловлю блох в своих проектах после обновлений. Ну и главное, мы тут переписываемся, а народ не знает о чем. Кто выложит пример? PS сегодня, внесу мелкие правки

Andrey: Haz пишет: Ну и главное, мы тут переписываемся, а народ не знает о чем. Кто выложит пример? Григорию отправлю пример, как сделаем. Haz пишет: Возможно, при условии что цвет задан явно, а не блоком кода. В примере это показано по хидеру и футеру. Кстати твоя выгрузка через Excel2() вообще ничем в этом раскладе, ни шрифтов ни цвета. Тогда, если можно дай пример закраски шапки таблицы (любым цветом) и отрицательных чисел. Чтобы потом можно было делать на базе этого свою раскраску отчёта. А выгрузка через Excel2() ограничена, из-за чего я и ухватился за твой пример. Haz пишет: Форматы все задаются в функции XMLSetDefault(), специально задал только 2. Не хочу писать транслятор с форматов PICTURE в форматы Excel. Это отдельное и бесполезное развлечение. Согласен с этим, но в качестве примера как сделать ТОЛЬКО для одного формата я и ввел в пример такое поле. Чтобы потом, каждый кто будет использовать это, смог сделать свою обработку.

Haz: Andrey пишет: Согласен с этим, но в качестве примера как сделать ТОЛЬКО для одного формата я и ввел в пример такое поле. Чтобы потом, каждый кто будет использовать это, смог сделать свою обработку. Лови https://drive.google.com/open?id=1J_3jTxCSvdPg_xzhhLgSqi7yro6l_NyL

Haz: Andrey пишет: Тогда, если можно дай пример закраски шапки таблицы (любым цветом) и отрицательных чисел. Чтобы потом можно было делать на базе этого свою раскраску отчёта. в примере шапка и так красится, что касается отрицательных чисел , то это задается теми же форматами Excel к примеру так "# ##0,00_ ;[Красный]-# ##0,00\ " на числовой колонке PS Проверил. Точнее так [pre2] XmlSetDefault( oBrw ) // Можно значения по умолчанию переопределять oBrw:aColumns[6]:XML_Format := "00\:00\:00" oBrw:aColumns[9]:XML_Format := "0.00_ ;[Red]\-0.00\ " Brw2Xml(oBrw, "TEST.XML", .T.,, aTitle) XmlReSetDefault( oBrw ) [/pre2]

Haz: Haz пишет: А выгрузка через Excel2() ограничена На самом деле если бы была нормальная спецификация пл BIFF2(4) , то выгрузка Excel2() довольно легко дополняется. Видел только англоязычную где то, да и с примерами по BIFF очень скудно.

Andrey: Haz пишет: в примере шапка и так красится, У меня нет. Excel 2003

Dima: Andrey пишет: Excel 2003 Я думал один такой на форуме

Haz: Andrey пишет: У меня нет. Excel 2003 Да , у 2003 ограничения по палитре. Попробуй в коде подставить [pre2] вместо этого oStyle:bgColor( '#' + NToC(oBrw:nClrSpcHdBack, 16) ) вот это oStyle:bgColor( '#' + NToC(CLR_GREEN, 16) ) [/pre2]

Haz: Dima пишет: Я думал один такой на форуме Надо же чтоб кто то на старье потестил )))

Dima: Haz пишет: На самом деле если бы была нормальная спецификация пл BIFF2(4) Не она ? https://www.openoffice.org/sc/excelfileformat.pdf

Haz: Dima пишет: Не она ? Это видел, кто возьмется перевести на "великий и могучий" ?

Andrey: Я поставил для суперхидера, шапки и подвала: oStyle:bgColor( '#' + NToC(CLR_HGRAY, 16) ) // only Excel 2003 Пример получился классным. При смене таблицы на одну строку: #define MULTILINE_TSB .F. , то же экспортирует классно. Остался ОДНА проблема касающаяся METHOD Excel2(). При использовании колонки в Tsbrowse числового формата "@R 99:99:99", то при экспорте всегда лезет такая ошибка: И колонка остаётся без формата. Я сделал 6-ю колонку специально для тестирования. Можно как нибудь убрать/починить этот формат для METHOD Excel2() ?

Haz: Andrey пишет: Можно как нибудь убрать/починить этот формат для METHOD Excel2() ? или полностью переделывать , то есть все предустановки выносить из Excel2() и назначать до экспорта ( у меня для этого служит XMLSetDefault() и переопределения перед экспортом) или навсегда вшивать этот ( никому не нужный формат ) в исходник Excel2(). Сам формат можно подсмотреть у меня в выгрузке.

Andrey: Haz пишет: или навсегда вшивать этот ( никому не нужный формат ) в исходник Excel2(). Хотя бы так или сделать определение этого формата до вызова Excel2(), как ты сделал у себя: [pre2] XmlSetDefault( oBrw ) // Можно значения по умолчанию переопределять oBrw:aColumns[6]:XML_Format := "00\:00\:00" oBrw:aColumns[9]:XML_Format := "0.00_ ;[Red]\-0.00\ " Brw2Xml(oBrw, "TEST.XML", .T.,, aTitle) // экспорт в Excel XmlReSetDefault( oBrw )[/pre2] А лучше наверное в исходнике дать этот формат и небольшое описание, типа для назначения своих форматов. Можно название твоей функции поменять на Excel3Xml() ? И ещё вопрос: [pre2] For nCol := 1 To Len( oBrw:aColumns ) uData := Eval( oBrw:aColumns[ nCol ]:bData ) cType := ValType( uData )[/pre2] можно добавить сюда сразу:[pre2] nBackColor := oBrw:aColumns[ nCol ]:nClrBack oStyle:bgColor( '#' + NToC(nBackColor, 16) ) // Excel > 2003 [/pre2] Или так не пойдёт, потому что цвета Tsbrowsa состоят из блок-кода ?

Haz: Andrey пишет: сделать определение этого формата до вызова Excel2(), как ты сделал у себя: Это потребует переделки метода, лучше выносить наружу, т.к форматов в Excel гораздо больше чем в харбур и могут они быть любые Andrey пишет: Можно название твоей функции поменять на Excel3Xml() Называй как хочешь )

SergKis: Andrey пишет Или так не пойдёт, потому что цвета Tsbrowsa состоят из блок-кода ? Сделай обработку блока кода[pre2] nBackColor := oBrw:aColumns[ nCol ]:nClrBack If Valtype( nBackColor ) == "B" Eval( nBackColor, oBrw:nAt, nCol, oBrw ) EndIf oStyle:bgColor( '#' + NToC(nBackColor, 16) ) // Excel > 2003 [/pre2]

SergKis: PS сори, пропустил пока набирал (маленький экран) nBackColor := Eval( nBackColor, oBrw:nAt, nCol, oBrw )

Andrey: SergKis пишет: Сделай обработку блока кода Сделал. Цвета не появляются ! Хотя коды цвета правильные, совпадают с CLR_HGRAY Вот код:[pre2] For nCol := 1 To Len( oBrw:aColumns ) uData := Eval( oBrw:aColumns[ nCol ]:bData ) cType := ValType( uData ) nBackColor := oBrw:aColumns[ nCol ]:nClrBack If Valtype( nBackColor ) == "B" nBackColor := Eval( nBackColor, oBrw:nAt, nCol, oBrw ) EndIf //? nLine, nCol, nBackColor, "== 12632256", CLR_HGRAY oStyle:bgColor( '#' + NToC(nBackColor, 16) ) switch cType[/pre2] Наверное ещё что-то нужно сделать, чтобы применить цвет к этой ячейке ?

Haz: Andrey пишет: Наверное ещё что-то нужно сделать, чтобы применить цвет к этой ячейке ? Стиль нужно определить заранее. С блоками скорее в два прохода придётся. Сначала анализируем весь бровс на возможные форматы по цвету, шрифту и пр. На основе анализа формируем все эти форматы, а потом, при выводе бровса в зависимости от результата блока выбираем нужный формат. Excel читает XML построчно. К момену вывода ячейки формат должен быть определен Из примера куска кода не ясно где он расположен в тексте Ps почитал выше, тут не сработает. Тут идёт вывод и форматы уже определены ранее. Андрей, ты зациклен на воспроизводстве внешнего вида бровса. Либо заранее опрелить цвет которам ты будешь рисовать. Либо взять цвет из каждой ячейки при первомпроходе, сформитовать форматы запомнив координаты. А при выводе брать по координатам. Я же сторонник того, что копия бровса в Excel никому не нужна. Достаточно вывести данные в читаемом и оформленном виде, для маньков путь анализа бровса. Другим способом можно назвать условное ворматирование Excel, но там тоже все не само появится, и нужно как минимум знать как написать условный формат.

Andrey: Haz пишет: Из примера куска кода не ясно где он расположен в тексте Вот код: [pre2] While nLine <= nLen oSheet:cellHeight( nRow, 1, oBrw:nHeightCell / 1.3 ) For nCol := 1 To Len( oBrw:aColumns ) uData := Eval( oBrw:aColumns[ nCol ]:bData ) cType := ValType( uData ) nBackColor := oBrw:aColumns[ nCol ]:nClrBack If Valtype( nBackColor ) == "B" nBackColor := Eval( nBackColor, oBrw:nAt, nCol, oBrw ) EndIf //? nLine, nCol, nBackColor, "== 12632256" oStyle:bgColor( '#' + NToC(nBackColor, 16) ) switch cType[/pre2] Haz пишет: Я же сторонник того, что копия бровса в Excel никому не нужна. Достаточно вывести данные в читаемом и оформленном виде, для маньков путь анализа бровса. Согласен, просто хотелось бы иметь просто пример как это делается (оформление цветами). В качестве примера и сделал меню для повтора цветов:[pre2] MENUITEM 'color table white ' ACTION nTsbColor := 1 FONT Font1 MENUITEM 'color table gray ' ACTION nTsbColor := 2 FONT Font1 MENUITEM 'color of the table "ruler"' ACTION nTsbColor := 3 FONT Font1 MENUITEM 'color of the table "columns"' ACTION nTsbColor := 4 FONT Font1 MENUITEM 'color of the table "chess"' ACTION nTsbColor := 5 FONT Font1[/pre2] Вот я решил сделать цвета в xml и не могу с ходу. Для этого нужно разбираться. А что за пример в котором не показано как можно сделать ! И не маньяк я, а хочу иметь в качестве примера - как нужно правильно делать, а не методом тыка работает/не работает. Т.е. отдельно написать: // секция для цветового оформления таблицы. Шапку, суперхидер и подвал как заполнять цветом уже понятно, осталось только саму таблицу покрасить.

Haz: Andrey пишет: Вот я решил сделать цвета в xml и не могу с ходу. Для этого нужно разбираться. Определить стиль перед выводом заранее. При выводе указать каким стилем. Ты же пытаешься во время вывода ячеек бровса сунуть цвет непонятно какому стилю. Это как раскраски, хочу фигурку закрасить желтым, беру жёлтый фломастер каторый уже заранее преготовлен. Я же не просто так говорил про варианты : 1 выбирать заранее определенные стили - условные цвета вывода 2 попытаться при прогоне по бровсу сформировать все комбинации цвет, шрифт, рамка, выравнивание. Опрелить их как стили с привязкой к координатам ячейки и при выводе бровса брать эти стили 3 тоже что и 2 но использовать условное форматирование. Мне не сложно еще раз повторить, что Excel читает XML сверху вниз и слева направо. То есть сначала раскладываем фломастеры и их уже не меняем. Потом рисуем тем что разложили. Реализация динамической раскраски начинается с вопроса, а какие фломастеры потребуются. Ну уж если совсем по простому То обрати внимание что цвет шапки и подвала задаётся в соответствуюших местах кода под коментарием ОПРЕДЕЛЯЕМ СТИЛИ ШАПКИ и ОПРЕДЕЛЯЕМ СТИЛИ ПОДВАЛА. Там же есть и комментарий ОПРЕДЕЛЯЕМ СТИЛИ КОЛОНОК, вот туда свой цвет и пихай. И учти каждый стиль одного цвета, нужен другой цвет - определяй новый стиль.

Andrey: Haz пишет: На самом деле если бы была нормальная спецификация пл BIFF2(4) , то выгрузка Excel2() довольно легко дополняется. Видел только англоязычную где то, да и с примерами по BIFF очень скудно. Пример MiniGUI\SAMPLES\Advanced\Tsb_Brw2xml из последней версии МиниГуии - классный получился ! Спасибо Haz ! Экспорт для Excel2() для нескольких строк - то что нужно ! Даже наверное шрифты можно не уменьшать. Но да ладно, пускай остаются в качестве примера, как можно делать. Единственно что не хватает в экспорте для Excel2() рамок в ячейках таблицы. В шапке и подвале таблицы рамки есть, а на ячейках нет ! Можно это как то подправить ?

Haz: Andrey пишет: Единственно что не хватает в экспорте для Excel2() рамок в ячейках таблицы. В шапке и подвале таблицы рамки есть, а на ячейках нет ! Можно это как то подправить ? А самому хотя бы посмотреть что мешает ? [pre2]Function BiffRec( nOpCode, uData, nRow, nCol, lBorder, nAlign, nPic, nFont )[/pre2]

Andrey: Прикрутил к этому же проекту ещё один экспорт, через ОЛЮ ! 1) Для одной строки всё прекрасно работает, для многострочных строк нет ! 2) Как задать титул перед шапкой определённым фонтом (также, как для нового oBrw:Excel2() ) ? Как бы исправить исходники ? Проект вот тут - https://cloud.mail.ru/public/JNeH/xGmMBvmVD Почему не работает в методе oBrw:ExcelOle( cXlsFile, ....) следующее назначение ? [pre2] lSave := .T. cPath := GetStartUpFolder() + "\" // путь записи файла cMaska := "A14_ДолгСальдо" // шаблон файла cXlsFile := cPath + cMaska + "_" + DTOC( DATE() ) + "_" cXlsFile += SUBSTR( CharRepl( ":", TIME(), "-" ), 1, 5 ) + ".xls"[/pre2] Обрезает до A14_ДОЛГСАЛЬДО_12.03.2018_23-18

Andrey: Andrey пишет: Почему не работает в методе oBrw:ExcelOle( cXlsFile, ....) следующее назначение ? lSave := .T. cPath := GetStartUpFolder() + "\" // путь записи файла cMaska := "A14_ДолгСальдо" // шаблон файла cXlsFile := cPath + cMaska + "_" + DTOC( DATE() ) + "_" cXlsFile += SUBSTR( CharRepl( ":", TIME(), "-" ), 1, 5 ) + ".xls" Обрезает до A14_ДОЛГСАЛЬДО_12.03.2018_23-18 Убрал в модуле h_tbrowse.prg строку 4809: [pre2] If ! Empty( cXlsFile ) //cXlsFile := AllTrim( StrTran( Upper( cXlsFile ), ".XLS" ) ) поставил // EndIf[/pre2] Перестало обрезать ! И убрался только верхний регистр ! То что нужно ! Григорий, убери пожалуйста в исходниках эту строку. Или замени её как нужно, для следующих версий МиниГуи ! Заранее спасибо !

Andrey: [pre2] oBrw:ExcelOle( cXlsFile, lActivate, hProgress, cTitle, hFont, lSave, bExtern, aColSel, bPrintRow ) cXlsFile // имя файла lActivate := .T. // открыть Excel hProgress := nil // хенд для ProgressBar lSave := .T. // сохранить файл bExtern := nil // ? aColSel := nil // ? bPrintRow := nil // ?[/pre2] Подскажите пожалуйста, что за параметры (за что отвечают) ?

Andrey: SergKis пишет: Предлагаю новый метод для tsb, для растяжки нескольких колонок до размера тсб по ширине. ..... Использование при ширине tsb > ширины колонок :AdjColumns() - все колонки :AdjColumns({"NAME", "SUMMA"}) - указанные колонки по cName :AdjColumns({3, 4, 5}) - указанные колонки по номеру А нормально будет работать ? Я при включении предыдущего метода на примере Tsb_Config.prg [pre2] oBrw:nAdjColumn := 2 // stretch column 2 to fill the voids in the right Tbrowse[/pre2] имел хороший баг при изменении ширины окна ! Григорий помог его решить через: [pre2] // repartition column 2 (1 + 1 -SELECTOR) - otherwise buggy oBrw:bInit := {|| oBrw:SetColSize( 2, nWidthFirstColumn )} .... ////////////////////////////////////////////////////////////////// FUNCTION ResizeBrowse() .... Eval(oBrw:bInit) // read the second column of the table ... [/pre2]

SergKis: Andrey пишет А нормально будет работать ? Я при включении предыдущего метода на примере Tsb_Config.prg oBrw:nAdjColumn := 2 SergKis пишет Использование при ширине tsb > ширины колонок т.е. ты вызываешь метод так (др. вариантов не предполагал пока)[pre2] :AdjColumns({3, 4, 5}) // или :AdjColumns() END TBROWSE oRpt:SetNoHoles()[/pre2] возможно при увеличении окна и размера тсб, тоже сработает, если вызвать. Можешь пробовать libу кинул

Andrey: SergKis пишет: Можешь пробовать libу кинул Классно ! Работает ! Но, если использовать [pre2] oBrw:HideColumns( {10} ,.t.) // скрыть колонки [/pre2] То последняя колонка становится слишком широкой ! Т.е. наверное не учитываются скрытые колонки ? А так очень понравился этот метод !

SergKis: Andrey пишет То последняя колонка становится слишком широкой ! Есть такая бяка. Надо правки делать[pre2] METHOD AdjColumns( aColumns, nDelta ) CLASS TSBrowse ... LOCAL nVisible := 0, aVisible := {} ... AEval( ::aColumns, {|oc| nVisible += iif( oc:lVisible, oc:nWidth, 0 ) }) AEval( aCol , {|nc| iif( obr:aColumns[ nc ]:lVisible, AAdd(aVisible, nc), Nil ) }) k := Len(aVisible) ... For i := 1 To k c := aVisible[ i ] ... [/pre2] вроде работает, погоняй еще, либу кинул

Andrey: SergKis пишет: вроде работает, погоняй еще, либу кинул Погонял... Не работает... Свой пример кинул.

SergKis: Andrey пишет Погонял... Не работает... SergKis пишет :AdjColumns({3, 4, 5}) // или :AdjColumns() END TBROWSE а у тебя[pre2] :lLockFreeze := .T. // избегать прорисовки курсора на замороженных столбцах :AdjColumns() // растяжка колонок до размера тсб по ширине ... :GetColumn("Name_8"):lEdit := .T. :HideColumns( {10} ,.t.) // скрыть колонки TsbColor( oBrw ) // задание цветов таблицы ... т.е. сначала разместили по ширине колонки, потом скрыли. ЗАМЕЧАТЕЛЬНО Убрал в самый низ ... :AdjColumns() // растяжка колонок до размера тсб по ширине END WITH // oBrw объект снят сработало как надо. [/pre2]

Andrey: SergKis пишет: Убрал в самый низ Поторопился я ... Как всегда.

Andrey: Сделал пример ! Tsb кладу на уже готовую форму в другом модуле. Всё показывает нормально, кроме вертикального скролинга. Должен быть, а не показывает при старте. Если стрелками(мышкой) подёргать, то линия скролинга появляется... обгрызанная, без стрелки вверху и внизу. Можно ли как то перерисовать весь вертикальный скролинг ?

Andrey: Новая версия МиниГуи - 18.04 Метод oBrw:ExcelOle(). При экспорте в таблице столбец с номерами домов (примерно такой порядок: 1, 2, 5, 9/2 и т.д.) неправильно экспортирует. Превращает этот столбец в 1,2,5, 09 февраля. Григорий, я сделаю тестовый пример с этим и вышлю на почту.

Andrey: Как указать правильно формат показа в Tsbrowse для текстового поля (значения "123300") по шаблону "@R 99:99:99" ? Для числового поля показ идёт правильный, а как задать такой же шаблон для текстового поля ? Если создаём aPict := { nil, nil, nil, nil, nil, "@R 99:99:99", nil } и передаём в [pre2]oBrw:SetArrayTo(aArray, aFontHF, aHead, aSize, aFoot, aPict, aAlign, aName)[/pre2] То показ 6 колонки будет так - "123300" Если сделать [pre2] oBrw:SetArrayTo(aArray, aFontHF, aHead, aSize, aFoot, aPict, aAlign, aName) oBrw:aColumns[6]:cPicture := '@R 99:99:99' [/pre2] То показ в 6 колонке будет уже "12:33:00" Опять глюк нашёл в Tsb ?

SergKis: Andrey пишет Опять глюк нашёл в Tsb ? Это от того, что игнорируешь исходники. :SetArrayTo не обрабатывает сложные Picture, а делает расчет ширины колонок для размещения правильно данных header, строк, footer (что бы помещалось все в колонке при просмотре), превращая Picture в простой вид для строки к примеру cPict := Replicate( "X", Len( ::aDefValue[ nI ] ) ). Все что не устраивает, в полученном варианте, правишь сам после создания тсб. К примеру, в массиве в колонке мах длина всех элементов 20 символов, но в процессе работы может быть 30 длина, тогда можешь регулировать колонкой задав ширину в пикселях или задав aPict[6] := repl('X', 30), ::aDefValue[ 6 ], будет от заданного aPict[6].

Andrey: Предложение по METHOD Excel2() - сделать как у METHOD ExcelOle() в самом конце метода: [pre2] If lActivate ShellExecute( 0, "Open", If( lSave, cFile, cWork ),,, 3 ) EndIf ::Display() If hProgress != Nil SendMessage( hProgress, PBM_SETPOS, 0, 0 ) EndIf Return Nil [/pre2] В METHOD ExcelOle() предлагаю сделать в самом начале: [pre2] Default lSave := ! lActivate .and. ! Empty( cXlsFile ), ; cXlsFile := "", ; hFntTitle := hFont CursorWait() // Check the file name for the number of points If AtNum( ".", HB_FNameName( cFile ) ) > 0 cMsg := 'Calling from: ' + ProcName(0) + '(' + hb_ntos( ProcLine(0) ) cMsg += ') --> ' + ProcFile(0) + ';;' cMsg += 'Output File Name - "' + HB_FNameName( cFile ) + '";' cMsg += 'contains several signs dot !;' cMsg += 'Excel can "truncate" the file name !;;' cMsg := AtRepl( ";", cMsg, CRLF ) MsgStop( cMsg , "Error" ) Endif If ::lSelector[/pre2] Только это обязательно нужно сделать, я ОЧЕНЬ ДОЛГО не мог понять почему у меня режет имя файла, а на некоторых компах нет ! Чтобы потом другим было легче это понять !!! Если в имени файла использовать несколько точек, то САМ EXCEL "режет" имя файла. Можно конечно сделать немного по другому: переименовать входящее имя файла, но тогда нужно будет потом закрывать Ole-Эксель, и открывать его заново с переименованным файлом. Не очень красивое решение здесь для Экселя. Этот вариант сделал для Экспорта Dbf-файла.

Haz: Andrey пишет: предлагаю сделать Поддержу Андрея. По первому предложению лишним не будет. В принципе хорошийстиль за собой все проводить в исходное состояние. По второму думаю все сложнее, проблема может быть не только в количестве точек. Как вариант - может сообщать о недопустимости такого имени файла, а со временем критерии могут быть расширены.

SergKis: Andrey пишет If AtNum( ".", HB_FNameName( cFile ) ) > 0 ... Не уверен, скорее уверен, что этого в ExelOle делать не надо. Как пишет Игорь варианты возможны разные, все не засунешь, да и процедура ExelOle вызывается где то, вот там как надо и лепим имя файла, если очень надо, то и excel можно запустить отдельно не в ExcelOle. Второе предложение это перегруз

Andrey: SergKis пишет: процедура ExelOle вызывается где то, вот там как надо и лепим имя файла, если очень надо, то и excel можно запустить отдельно не в ExcelOle. Второе предложение это перегруз Я проверял поведение Excel. Имя файла с несколькими точками - режется ТОЛЬКО при вызове через OLE ! Если делать вызов Excel по другому, то всё нормально. Меню экспорта 1 и 3 в программе работает нормально. В конце метода ExcelOle() вызов экселя запускается НЕ ОТДЕЛЬНО !!! [pre2] If ! Empty( cXlsFile ) .and. lSave oBook:SaveAs( cXlsFile, xlWorkbookNormal ) // вот здесь и режется... If ! lActivate CursorArrow() oExcel:Quit() ::Reset() Return Nil EndIf EndIf CursorArrow() If lActivate oSheet:Range( "A1" ):Select() oExcel:Visible := .T. // показ Экселя EndIf[/pre2] Из-за этого я и предлагаю для ЭТОГО варианта разместить предупреждения, чтобы потом кто-то не налетел на ! Я Григория замучил - что режется имя файла, месяца 2 не мог понять почему. А решение оказывается совсем ПРОСТОЕ !

PSP: Андрей, нужно абстрагироваться от конкретного случая. Все обработки вариантов нужно делать "до того, как". Методу нужно предоставить данные в том виде, в котором они будут на 100% обработаны предсказуемым образом без всяких MsgStop(...)

Dima: PSP +1

Haz: PSP пишет: Все обработки вариантов нужно делать "до того, как" +500 Под конкретный случай, нужно конкретно и решать

Andrey: Понял ваше мнение ! Andrey пишет: Новая версия МиниГуи - 18.04 Метод oBrw:ExcelOle(). При экспорте в таблице столбец с номерами домов (примерно такой порядок: 1, 2, 5, 9/2 и т.д.) неправильно экспортирует. Превращает этот столбец в 1,2,5, 09 февраля. А как это исправить ? В методе :Excel2(...) выгрузка идёт правильно.

Andrey: Пробовал задавать явно формат столбца, всё равно не помогает.[pre2] // только для 6 и 10 колонки oBrw:aColumns[6]:cPicture := '@R 99:99:99' // без этого нет показа в колонке ":" oBrw:aColumns[10]:cPicture := 'xxxxxxxxx' [/pre2]

Dima: Andrey глянь

Andrey: Спасибо Дима ! Не получается... добавить перед числом апостроф (‘). Например: ’11-53 или ‘1/47. Апостроф не отображается после нажатия клавиши ВВОД; Поставил в колонке 10 апостроф (‘) - выгружате через Оле-Эксель так же ‘3/2 или ‘9/3 Конечно как самый примитив пойдёт, только юзера будут очень недовольны таким номером дома... Можно сделать первым символом знак "_" или "~" ставить. Но потом бы из документа этот знак желательно убрать... Тогда нужно ставить обработку удаления, после вставки из буфера... А лучше надо бы в конвертацию формата для текстового поля явно в исходниках указать, типа: [pre2]oSheet:Cells( nLine, nI ):SET( "NumberFormat", '@' ) // текстовая ячейка[/pre2] Пытался разобраться сaм, ничего не понял... Там идёт накопление в буфер, а потом идёт вставка из буфера. Как до этого указать формат столбца не знаю.

Andrey: Ура ! Получилось... Нужна правка в исходнике h_tbrowse.prg: [pre2] For nCol := 1 To Len( ::aColumns ) If aColSel != Nil .and. AScan( aColSel, nCol ) == 0 Loop EndIf uData := Eval( ::aColumns[ nCol ]:bData ) If ValType( uData ) == "C" oSheet:Cells( nLine, nCol ):SET( "NumberFormat", '@' ) // text cell EndIf If ValType( uData ) == "C" .and. At( CRLF, uData ) > 0 uData := StrTran( uData, CRLF, "&&" ) If AScan( aRepl, nCol ) == 0 AAdd( aRepl, nCol ) EndIf EndIf[/pre2] В METHOD ExcelOle() предлагаю сделать эту правку ! Pasha пишет: Как вариант: перед заполнением таблицы по строкам можно установить NumberFormat для тех столбцов, для которых это надо, т.е:

Dima: Andrey пишет: SET( "NumberFormat", '@' ) Может не сработать в ряде случаев когда много цифр в ячейке и Excel по своему покажет

Andrey: Dima пишет: Может не сработать в ряде случаев когда много цифр в ячейке и Excel по своему покажет В каких случаях ? Я тестировал столбец из номеров домов - вида: 1,2,3/2, 4, 5/3, 6А, 112Б, 94 стр.3 и т.д. ТОЛЬКО для текстового столбца делаю формат :SET( "NumberFormat", '@' ) // text cell Остальные столбцы НЕ ТРОГАЮ.

Dima: Andrey пишет: В каких случаях ? Да был случай лет 5 назад , вываливал в Excel коды морозильных камер (штук 500 примерно) В этих кодах были цифры , пробелы , точки и тире. Все коды разные. Из 500 штук , штуки 3 всегда показывало криво , и шаблон подобрать не удалось (руками тоже пробовали) . PS Это был файл формата CSV

Andrey: Возвращаюсь опять к методу ExcelOle(). При вызов экселя, он запускается, а потом уходит на второй план, т.е. под задачу. У всех так происходит ? Или это только у меня так, из-за Far. Если у всех, то надо бы Эксель на передний план ВСЕГДА переключать. Или ключ ввести для перевода. У кого какие будут соображения ?

Andrey: Предложение по METHOD Excel2() - сделать задержку, чтобы бегунок показывался на экране нормально, это в конце метода: [pre2] If ! Empty( aRepl ) For nCol := 1 To Len( aRepl ) oSheet:Columns( Chr( 64 + aRepl[ nCol ] ) ):WrapText := .T. Next EndIf If hProgress != Nil SendMessage( hProgress, PBM_SETPOS, nCount, 0 ) EndIf INKEYGUI(100) If ::lSelector ::InsColumn( ::aClipBoard[ 2 ], ::aClipBoard[ 1 ] ) ::lNoPaint := .F. EndIf If ! Empty( cXlsFile ) .and. lSave .....[/pre2] И ещё предложение: [pre2] EndIf //If ! Empty( ::aSuperHead ) // заменить как ниже If (::lDrawSuperHd) For nCol := 1 To Len( ::aSuperHead ) nVar := If( ::lSelector, 1, 0 ) uData := If( ValType( ::aSuperhead[ nCol, 3 ] ) == "B", Eval( ::aSuperhead[ nCol, 3 ] ), ;[/pre2] Поясню почему. Если в примере нужно убрать показ суперхидера, то можно назначит ему высоту 1 пиксел. И исходники пересматривать не придётся. Но если у нас суперхидер есть в 1 пиксел, то ! Empty( ::aSuperHead ) выдаст что суперхидер есть и сделает экспорт его на лист Экселя. А If (::lDrawSuperHd) позволит этого избежать.

Haz: Andrey пишет: сделать задержку, чтобы бегунок показывался на экране нормально Тормозить программу специально? Ради красоты бегунка Правильнее нормально задавать параметры отображения. К примеру если рисуем процентовку, которая, напоминаю равна 100 То незачем прорисовывать каждую запись из 1000. Дастаточно каждую десятую.

Andrey: Haz пишет: Правильнее нормально задавать параметры отображения. К примеру если рисуем процентовку, которая, напоминаю равна 100 То незачем прорисовывать каждую запись из 1000. Дастаточно каждую десятую. А как надо правильно ? Подправь пожалуйста исходник, а то в методе :Excel2() нормально рисуется бегунок, а в методе :ExcelOle() - огрызок какой-то.

Andrey: И ещё одна странность в методе :ExcelOle() - не рисуется подвал таблицы ! Там же есть вроде в тексте: [pre2] If AScan( ::aColumns, { |o| o:cFooting != Nil } ) > 0 For nCol := 1 To Len( ::aColumns ) If ( aColSel != Nil .and. AScan( aColSel, nCol ) == 0 ) .or. ::aColumns[ nCol ]:cFooting == Nil Loop EndIf uData := If( ValType( ::aColumns[ nCol ]:cFooting ) == "B", Eval( ::aColumns[ nCol ]:cFooting ), ; ::aColumns[ nCol ]:cFooting ) uData := cValTochar( uData ) uData := StrTran( uData, CRLF, Chr( 10 ) ) oSheet:Cells( nLine, nCol ):Value := uData Next EndIf [/pre2] Как исправить, чтобы заработало ?

Haz: Andrey пишет: Предложение по METHOD Excel2() - сделать задержку, Ты уж определись про какой метод ты пишешь ? А то говоришь про Excel2() а код кидаешь из ExcelOle() Вместо INKEYGUI() скорее подойдет Sysrefresh() или DoEvents() В конце метода nCount == nTotal ?? при выводе этого [pre2] ::ExcelOle() If hProgress != Nil SendMessage( hProgress, PBM_SETPOS, nCount, 0 ) EndIf [/pre2] если посмотреть в Excel2() то в конце там не nCount . Может тут проблема ? [pre2] ::Excel2() If hProgress != Nil SendMessage( hProgress, PBM_SETPOS, nTotal, 0 ) EndIf [/pre2] Следующий фокус я не понял [pre2] If hProgress != Nil nTotal := ( ::nLen + 1 ) * Len( ::aColumns ) + 30 SetProgressBarRange ( hProgress , 1 , nTotal ) SendMessage( hProgress, PBM_SETPOS, 0, 0 ) nEvery := Max( 1, Int( nTotal * .02 ) ) // refresh hProgress every 2 % EndIf [/pre2] и затем два раза [pre2] If hProgress != Nil nCount -= 15 SendMessage( hProgress, PBM_SETPOS, nCount, 0 ) EndIf [/pre2]

Andrey: Haz пишет: Ты уж определись про какой метод ты пишешь ? А то говоришь про Excel2() а код кидаешь из ExcelOle() Вместо INKEYGUI() скорее подойдет Sysrefresh() или DoEvents() Да точно, перепутал я. Понял насчёт Sysrefresh() или DoEvents(). Но остальной код я тоже не понимаю, зачем так сделано: nCount -= 15 и т.д. - для меня загадка... Напиши пожалуйста как правильно сделать, а Григорий уже исправит исходники ! И как насчёт подвала таблицы, почему нет в экселе её ?

Haz: Andrey пишет: И ещё одна странность в методе :ExcelOle() - не рисуется подвал таблицы ! В версии 2018/03/28: HMG Extended Edition version 18.03. все рисуется из твоего же примера Tsb_Brw2xml Ищи где намудрил с исходниками

Andrey: Haz пишет: В версии 2018/03/28: HMG Extended Edition version 18.03. все рисуется из твоего же примера Tsb_Brw2xml Я понял в чём дело. Если увеличить таблицу то 1000 элементов, то подвал в таблице пропадает ! Я пробовал на версии 18.03 - тоже нет подвала. Сделал в версии 18.04 кол-во строк 240, подвал есть. На 250 строках подвала уже нет и вот такая таблица получается: Что-то ерундит алгоритм выгрузки в эксель. Как и где подправить ? Смотреть последний проект - Tsb_Export8d.7z

Haz: Andrey пишет: Что-то ерундит алгоритм выгрузки в эксель. Как и где подправить ? А ерундит счетчик строк в алгоритме, на твоей картинке ясно виден разрыв ( пустая строка ) и после нее еще 5 строк. Если в примере общее число строк уменьшить на 5 , то разрыв исчезнет и подвал появится. Скорее всего из-за разрыва подвал затирается. Так что ищи причину разрыва, подвал - это следствие

Haz: Добавлю чуть. В текущей реализации ::ExcelOle() морально устарел , а убивец текущей реализации метода - Паша После появления поддержки вариантного массива этот ::ExcelOle() стал рудиментом, т.к. с __oleVariantNew() работать приятнее и понятнее , чем клеить ячейки в строку с ограничением в 20к

Andrey: Haz пишет: В текущей реализации ::ExcelOle() морально устарел , а убивец текущей реализации метода - Паша После появления поддержки вариантного массива этот ::ExcelOle() стал рудиментом, т.к. с __oleVariantNew() работать приятнее и понятнее , чем клеить ячейки в строку с ограничением в 20к А можно сделать замену этой текущей реализации для всех ? Я этого сам не осилю.

Haz: Andrey пишет: Я этого сам не осилю. Ну надо же когда то начинать

Haz: Никак не могу понять почему зависает следующий код Есть колонка NAME с текстовым полем , хочу и редактировать его и выбирать из справочника . Идеально подходит ::SetBtnGet Следующий код при выборе кнопки записывает слово "Test" в поле, но только в первый раз, во второй раз бровс зависает [pre2]oBrw:SetBtnGet( "NAME", "", { | oEdit, xVar | xVar := "Test",; oEdit:VarPut( xVar ), oEdit:Refresh() }, 16 )[/pre2] Мож есть у кого мысли куда копать ? PS Даже с таким кодом на второй раз завис [pre2]oBrw:SetBtnGet( "NAME", "", { | | NIL } , 16 )[/pre2] и еще интереснее , если в первый раз ввести значение ручками , а во второй вызвать кнопку - тоже завис.

Pasha: Haz пишет: В текущей реализации ::ExcelOle() морально устарел для начала можно убрать некоторые рудименты: строки oBook := oExcel:Get( "ActiveWorkBook") oSheet := oExcel:Get( "ActiveSheet" ) заменить на oBook := oExcel:ActiveWorkBook oSheet := oExcel:ActiveSheet аналогично вызов (в 2-х местах) oSheet:Range( cRange ):Set( "HorizontalAlignment", xlHAlignCenterAcrossSelection ) заменить на oSheet:Range( cRange ):HorizontalAlignment := xlHAlignCenterAcrossSelection после этого можно перейти на использование класса win_oleAuto из библиотеки hbwin, заменив строку oExcel := CreateObject( "Excel.Application" ) на win_oleCreateObject( "Excel.Application" ) Используя класс win_oleAuto, можно вместо передачи через буфер обмена передавать в Excel всю таблице одним вызовом __oleVariantNew() В принципе передача через буфер обмена фрагментами по 20к тоже работает быстро, но можно и делать это прямой записью.

SergKis: Haz пишет Следующий код при выборе кнопки записывает слово "Test" в поле, но только в первый раз, во второй раз бровс зависает Добавил в пример Tsb_addrecord_2 [pre2] ADD COLUMN TO oBrw DATA FieldWBlock( "ITG", Select( "base" ) ) ; HEADER "Total" FOOTER hb_ntos(nItg) ; ALIGN DT_RIGHT, DT_CENTER, DT_RIGHT ; SIZE 90 oBrw:SetBtnGet( 3, "", { |oe,cv| cv := "Test",; oe:VarPut(cv), oe:Refresh() }, 16 ) [/pre2] работает не виснет. Игорь, наверно, примерчик нужен

Haz: SergKis пишет: работает не виснет. Игорь, наверно, примерчик нужен Сергей, спасибо. Пока обошелся решив по другому. Сейчас не до примерчиков, позже сделаю обязательно ( может дома подготовлю и то не уверен ) ! Тащу два объемных проекта, даже тараканов в них давить некогда. Нужно сдать ! После сдачи видимо будет период оптимизации кода и украшательства. Вот там примерчики начнутся.

Haz: Сергей работает не виснет. Вобщем это я тупанул. Работает конечно при чистом запуске. Я пользуюсь для сборки проектов фришным редактором от Xailer ( xEdit ) Этот редактор , при запуске проекта на исполнение , пытается управлять приложением ( пытается использовать отладку, показать значения переменных, ресурсов и пр.) Возможно и можно его прикрутить как отладчик, но я не пользуюсь. Так вот, при запуске из под редактора , кнопка эта вешает задачу, при запуске нормальном - все ок. Знал же, раньше натыкался и все выяснил. Но время прошло и за неиспользованием этого функционала все забыл ((. Пол дня потратил на старые грабли

gfilatov2002: Pasha пишет: для начала можно убрать некоторые рудименты Благодарю за помощь! Выполнил предложенные правки Используя класс win_oleAuto для следующей сборки

SergKis: Haz пишет Есть колонка NAME с текстовым полем , хочу и редактировать его и выбирать из справочника . Идеально подходит ::SetBtnGet У себя исп. вариант без кнопки, но с назначением клавиш, может будет интересно. Изменения: [pre2] CLASS TSColumn ... DATA aKeyEvent INIT {} DATA bKeyEvent ... METHOD SetKeyEvent( nKey, bKey, lCtrl, lShift, lAlt ) ... ENDCLASS ... METHOD SetKeyEvent( nKey, bKey, lCtrl, lShift, lAlt ) CLASS TSColumn AAdd( ::aKeyEvent, { nKey, bKey, lCtrl, lShift, lAlt } ) RETURN Self ... CLASS TGetBox FROM TControl ... METHOD New( nRow, nCol, bSetGet, oWnd, nWidth, nHeight, cPict, bValid,; ... ::oGet := _DefineGetBox ( cControl, ParentFormName, nCol, nRow, nWidth, nHeight, uValue, ; // BK ... METHOD Edit( uVar, nCell, nKey, nKeyFlags, cPicture, bValid, nClrFore, ; ... Local nK, aKey, oGet ... oCol:oEdit := TGetBox():New( nRow+::aEditCellAdjust[1], nCol+::aEditCellAdjust[2], ; bSETGET( uValue ), Self, nWidth+2+::aEditCellAdjust[3], nHeight+2+::aEditCellAdjust[4], ; cPicture,, nClrFore, nClrBack, hFont, ::cChildControl, cWnd, ; cMsg,,,,, bChange, .T.,, lSpinner .and. cType $ "ND", bUp, bDown, ; bMin, bMax, oCol:lNoMinus ) IF ! empty(oCol:aKeyEvent) oGet := oCol:oEdit:oGet For nK := 1 TO Len(oCol:aKeyEvent) aKey := oCol:aKeyEvent[ nK ] If HB_ISNUMERIC( aKey[1] ) oGet:SetKeyEvent( aKey[1], aKey[2], aKey[3], aKey[4], aKey[5] ) EndIf Next ENDIF EndIf ... Пример Tsb_addrecord_2\demo.prg ... ADD COLUMN TO oBrw DATA FieldWBlock( "ITG", Select( "base" ) ) ; HEADER "Total" FOOTER hb_ntos(nItg) ; ALIGN DT_RIGHT, DT_CENTER, DT_RIGHT ; SIZE 90 // oBrw:SetBtnGet( 3, "", { |oe,cv| cv := "Test",; // oe:VarPut(cv), oe:Refresh() }, 16 ) oBrw:aColumns[3]:SetKeyEvent(VK_F5, {|og,ky| MyKeyEvent(og, ky) }) oBrw:aColumns[3]:SetKeyEvent(VK_F6, {|og,ky| MyKeyEvent(og, ky) }) oBrw:aColumns[3]:SetKeyEvent(VK_F7, {|og,ky| MyKeyEvent(og, ky) }) AEval( oBrw:aColumns, {|oCol,nCol| oCol:lFixLite := .T., ; ... *---------------------------------------------- STATIC FUNCTION MyKeyEvent( oGet, nKey ) *---------------------------------------------- LOCAL cVK := '', cTx := 'Test ' If nKey == VK_F5 cVK := 'VK_F5' ElseIf nKey == VK_F6 cVK := 'VK_F6' ElseIf nKey == VK_F7 cVK := 'VK_F7' EndIf oGet:VarPut(cTx+cVK) oGet:Refresh() // MsgBox( cVK + ' : ' + cValToChar( oGet:VarGet() ), 'Info' ) RETURN NIL [/pre2]

SergKis: PS DATA bKeyEvent надо убрать, остался от опытов

Haz: SergKis пишет: У себя исп. вариант без кнопки Сергей. Спасибо. В понедельник поткстирую

Haz: Сергей : может будет интересно. У меня есть очень draft, ну совсем бета альтернативного комбо в ячейке. Руки не доходят довести до ума, но испьзую так как есть. В понедельник скину в форум пример. Глянешь, интересны идеи. Суть в том, что вместо комбика попытался использовать бровс по базе. В последних проектах использую успешно, хоть и бета. А вот времени на осмысление нет. И чтоб совсем точки над ё, я не прошу сделать за меня. Я предлагаю идею и готов выслушать мнение.

SergKis: Haz пишет Суть в том, что вместо комбика попытался использовать бровс по базе. С этого начинал, с combo (и с поиском по букве). В итоге отказался, со временем маленький список -> в большой, + колонки ... Практически везде перехожу на тсб (с hb 2.0 browse, на 3.2 переделываю на тсб) А вот времени на осмысление нет. Со временем туго, согласен, справочники делаю по такой схеме (с поправками на задачу конечно), как идея (код из задачи, как есть) [pre2] // SPR modal window #include "minigui.ch" #include "tsbrowse.ch" MEMVAR oApp, oMain, oTbr, aReturn FUNC SprAGENT() LOCAL cBrw := 'AGENT' LOCAL cDbf := cBrw LOCAL cCapt := gTxt(Agenti) LOCAL nOrder := 1 LOCAL aColumn := { 'TNOM' , 'FIO' , 'FIO3' } LOCAL aName := { 'KOD' , 'NAM' , 'NOTE' } LOCAL aHeader := { gTxt(Kod) , gTxt(Nam), gTxt(Note) } LOCAL aWidth := { gW(1) , gW(2) , gW(2) } LOCAL aOrder := { 'KOD' , 'NAM' , } LOCAL aEdit := { .F. , .F. , .F. } LOCAL aAlign := { 1 , 0 , 0 } LOCAL aFAlign := { 1 , 0 , 0 } LOCAL aPicture := { , , } LOCAL aFixLite := { .T. , .T. , .T. } LOCAL aNoDescend := { .T. , .T. , .T. } LOCAL aOnGotFocusSelect := { .T. , .T. , .T. } LOCAL aEmptyValToChar := { .T. , .T. , .T. } LOCAL aEditMove := { 0 , 0 , 0 } LOCAL aBlockData := { , , } LOCAL aFields := { , , } LOCAL aData := { aColumn , ; // 1 aName , ; // 2 aHeader , ; // 3 aWidth , ; // 4 aOrder , ; // 5 aEdit , ; // 6 aAlign , ; // 7 aFAlign , ; // 8 aPicture , ; // 9 aFixLite , ; // 10 aNoDescend , ; // 11 aOnGotFocusSelect , ; // 12 aEmptyValToChar , ; // 13 aEditMove , ; // 14 aBlockData , ; // 15 aFields ; // 16 } RETURN SprGet( cBrw, cCapt, aData, nOrder ) FUNC SprU04() LOCAL cBrw := 'U04' LOCAL cDbf := cBrw LOCAL cCapt := gTxt(Klienti) LOCAL nOrder := 2 LOCAL aColumn := { 'R_1' , 'R_2' , 'R_4' , 'R_5' , 'R_13' , 'R_34' } LOCAL aName := { 'KOD' , 'NAM' , 'RNR' , 'PNR' , 'GRU' , 'ADR' } LOCAL aHeader := { gTxt(Kod) , gTxt(Nam), gTxt(Kli_R_4), gTxt(Kli_R_5), gTxt(Kli_R_13), gTxt(Kli_R_34) } LOCAL aWidth := { gW(1) , gW(3.5) , gW(1.5) , gW(1.5) , gW(1) , gW(4)+gW(0.5) } LOCAL aOrder := { 'KOD' , 'NAM' , , , , } LOCAL aEdit := { .F. , .F. , .F. , .F. , .F. , .F. } LOCAL aAlign := { 1 , 0 , 0 , 0 , 0 , 0 } LOCAL aFAlign := { 1 , 0 , 0 , 0 , 0 , 0 } LOCAL aPicture := { , , , , , } LOCAL aFixLite := { .T. , .T. , .T. , .T. , .T. , .T. } LOCAL aNoDescend := { .T. , .T. , .T. , .T. , .T. , .T. } LOCAL aOnGotFocusSelect := { .T. , .T. , .T. , .T. , .T. , .T. } LOCAL aEmptyValToChar := { .T. , .T. , .T. , .T. , .T. , .T. } LOCAL aEditMove := { 0 , 0 , 0 , 0 , 0 , 0 } LOCAL aBlockData := { , , , , , {|| KliAdr() } } LOCAL aFields := { , , , , , } LOCAL aData := { aColumn , ; // 1 aName , ; // 2 aHeader , ; // 3 aWidth , ; // 4 aOrder , ; // 5 aEdit , ; // 6 aAlign , ; // 7 aFAlign , ; // 8 aPicture , ; // 9 aFixLite , ; // 10 aNoDescend , ; // 11 aOnGotFocusSelect , ; // 12 aEmptyValToChar , ; // 13 aEditMove , ; // 14 aBlockData , ; // 15 aFields ; // 16 } RETURN SprGet( cBrw, cCapt, aData, nOrder ) * ----------------------------------------------------------------------------------- * FUNC SprGet( cID, cTitle, aData, nOrder, cBrwName ) * ----------------------------------------------------------------------------------- * LOCAL nY, nX, nH, nW, nT LOCAL cBrw := iif( empty(cBrwName), 'oSprav', cBrwName ) LOCAL cDbf := cID LOCAL cAls := cID LOCAL cWnd := 'w'+cBrw LOCAL aColumn := aData[ 1 ] // 1 LOCAL aName := aData[ 2 ] // 2 LOCAL aHeader := aData[ 3 ] // 3 LOCAL aWidth := aData[ 4 ] // 4 LOCAL aOrder := aData[ 5 ] // 5 LOCAL aEdit := aData[ 6 ] // 6 LOCAL aAlign := aData[ 7 ] // 7 LOCAL aFAlign := aData[ 8 ] // 8 LOCAL aPicture := aData[ 9 ] // 9 LOCAL aFixLite := aData[ 10 ] // 10 LOCAL aNoDescend := aData[ 11 ] // 11 LOCAL aOnGotFocusSelect := aData[ 12 ] // 12 LOCAL aEmptyValToChar := aData[ 13 ] // 13 LOCAL aEditMove := aData[ 14 ] // 14 LOCAL aBlockData := aData[ 15 ] // 15 LOCAL aFields := aData[ 16 ] // 16 LOCAL nDcell := 5 LOCAL nI, nK := len(aColumn) LOCAL hWnd := iif( _HMG_BeginWindowMDIActive, GetActiveMdiHandle(), GetActiveWindow() ) LOCAL nWndY := GetWindowRow (hWnd) LOCAL nWndX := GetWindowCol (hWnd) LOCAL nWndH := GetWindowHeight(hWnd) LOCAL nWndW := GetWindowWidth (hWnd) LOCAL nModH := GetClientHeight(hWnd) LOCAL nModW := GetVScrollBarWidth() + 2 + nK LOCAL nAls := Select() LOCAL hSpl, cNam, aHmg, oGet, cPic, oCel DEFAULT nOrder := 2 PRIVATE oTbr, aReturn := {} If ! Spr_Use( cDbf, cAls, .T. ) MsgStop( gTxt(NotUsed) + CRLF + cDbf + '.DBF', gTxt(Info) ) RETURN aReturn EndIf SET ORDER TO nOrder cAls := Alias() aHmg := Save_Rest_HMG(hWnd) AEval(aWidth, {|nw| nModW += nw }) nY := int( (nWndH - nModH) / 2 ) + nWndY nX := int( (nWndW - nModW) / 2 ) + nWndX DEFINE WINDOW &cWnd ; AT nY, nX ; WIDTH nModW ; HEIGHT nModH ; TITLE cTitle ; ICON oApp:Icon ; MODAL NOSIZE ; ON RELEASE ( iif( Select(cAls) > 0, (cAls)->( dbCloseArea() ), ), dbSelectArea(nAls) ) DEFINE SPLITBOX HANDLE hSpl DEFINE TOOLBAR ToolBar_1 BUTTONSIZE 68,32 FLAT BUTTON 06 CAPTION gTxt(Sort) PICTURE 'page_123' ACTION oTbr:PostMsg( WM_KEYDOWN, VK_F6, 0 ) ; TOOLTIP 'F6' SEPARATOR BUTTON 07 CAPTION gTxt(Find) PICTURE 'page_fltr' ACTION Press_Key(oTbr) ; TOOLTIP 'F7' SEPARATOR BUTTON E1 CAPTION ' ' PICTURE 'br_empty' ACTION NIL ; SEPARATOR BUTTON 13 CAPTION gTxt(Vibor) PICTURE 'page_enter' ACTION oTbr:PostMsg( WM_KEYDOWN, VK_RETURN, 0 ) ; TOOLTIP 'Enter' SEPARATOR END TOOLBAR DEFINE TOOLBAR ToolBar_2 BUTTONSIZE 48,32 FLAT BUTTON 10 CAPTION gTxt(Exit) PICTURE 'exit' ACTION ThisWindow.Release ; TOOLTIP 'Esc' END TOOLBAR END SPLITBOX nW := ThisWindow.ClientWidth nY := GetWindowHeight(hSpl) nX := 0 nH := ThisWindow.ClientHeight - nY nT := nY DEFINE TBRW &cBrw TO oTbr AT nY,nX WIDTH nW HEIGHT nH ALIAS cAls CELL oTbr:Cargo := cID :aColSel := aColumn :hFontHead := gProp(TsbHeader) :hFontFoot := gProp(TsbFooter) :LoadFields(.T.) :nWheelLines := 1 :nClrLine := COLOR_GRID :nHeightCell += nDcell :nHeightHead += nDcell :nHeightFoot := :nHeightCell :lNoGrayBar := .F. :lDrawFooters := .T. :lFooting := .T. :lNoVScroll := .F. :lNoHScroll := .T. :nFreeze := 1 :lLockFreeze := .F. :nFireKey := VK_F4 // default Edit :nLineStyle := LINES_ALL // LINES_NONE LINES_ALL LINES_VERT LINES_HORZ LINES_3D LINES_DOTTED :SetColor( { CLR_FOCUSB }, { { |a,b,c| If( c:nCell == b, {Rgb( 66, 255, 236), Rgb(209, 227, 248)}, ; {Rgb(220, 220, 220), Rgb(220, 220, 220)} ) } } ) For nI := 1 To nK oCol := :aColumns [ nI ] oCol:cName := aName [ nI ] oCol:cField := aColumn [ nI ] oCol:cHeading := aHeader [ nI ] oCol:nWidth := aWidth [ nI ] oCol:lEdit := aEdit [ nI ] oCol:nAlign := aAlign [ nI ] oCol:nFAlign := aFAlign [ nI ] oCol:lFixLite := aFixLite [ nI ] oCol:lOnGotFocusSelect := aOnGotFocusSelect[ nI ] oCol:lEmptyValToChar := aEmptyValToChar [ nI ] oCol:nEditMove := aEditMove [ nI ] If ! empty(aPicture [ nI ]) oCol:cPicture := aPicture [ nI ] EndIf If ! empty(aOrder[ nI ]) oCol:cOrder := aOrder [ nI ] // отключаем подсветку в Footer // If oCol:cName == "KOD" // oCol:cFooting := { |nc,obr| nc := (obr:cAlias)->( OrdKeyNo() ), ; // iif( empty(nc), '', hb_ntos(nc) ) } // ElseIf oCol:cName == "NAM" // oCol:cFooting := { |nc,obr| nc := (obr:cAlias)->( OrdKeyCount() ), ; // ' '+iif( empty(nc), '', hb_ntos(nc) ) } // EndIf EndIf If ! empty(aBlockData[ nI ]) If HB_ISCHAR(aBlockData[ nI ]) oCol:bData := AliasBlock(aBlockData[ nI ], cAls, .T.) Else oCol:bData := aBlockData[ nI ] EndIf EndIf If ! empty(aFields [ nI ]) oCol:cField := aFields [ nI ] EndIf Next :nCell := :nColumn('NAM') :aSortBmp := { LoadImage("br_up"), LoadImage("br_dn") } // отключаем подсветку в Footer // :bChange := {|obr| obr:DrawFooters() } :bLDblClick := {|p1,p2,p3,obr| p1:=p2:=p3:=Nil, obr:PostMsg( WM_KEYDOWN, VK_RETURN, 0 ) } :SetIndexCols( :nColumn('KOD'), :nColumn('NAM') ) :SetOrder(:nColumn(iif( nOrder == 1, 'KOD', 'NAM') )) if :nLen > :nRowCount() :ResetVScroll( .T. ) :oHScroll:SetRange(0,0) EndIf :UserKeys(VK_F6 , {|obr,nky,cky| Order_Set(obr,nky,cky)}) :UserKeys(VK_F7 , {|obr | Press_Key(obr )}) :UserKeys(VK_RETURN, {|obr | Recno_Get(obr )}) :UserKeys( , {|obr,nky,cky| Press_Key(obr,nky,cky)}) END TBRW oTbr:SetNoHoles() oTbr:SetFocus() cPic := StrTran( oTbr:GetColumn('KOD'):cPicture, '@K ', '' ) oCel := oTbr:GetCellInfo( 1, oTbr:nColumn('KOD') ) nX := 2 nW := oCel:nWidth - 5 nH := oTbr:nHeightCell nY := nT + GetWindowHeight(oTbr:hWnd) - oTbr:nHeightFoot // 550 @ nY, nX GETBOX KOD OBJ oGet HEIGHT nH WIDTH nW VALUE space(len(cPic)) ; BACKCOLOR oApp:BColorGet PICTURE cPic ; ON CHANGE Seek__Set(oTbr) ; INVISIBLE NOTABSTOP oGet:lOnGotFocusSelect := .F. oGet:OnEscape := {|og| og:GetObj():Hide(), oTbr:SetFocus(), .T. } oGet:OnEnter := {|og| og:GetObj():Hide(), oTbr:SetFocus() } oGet:OnDown := {|og| og:GetObj():Hide(), oTbr:SetFocus() } oGet:OnUp := {|og| og:GetObj():Hide(), oTbr:SetFocus() } cPic := StrTran( oTbr:GetColumn('NAM'):cPicture, '@K ', '' ) oCel := oTbr:GetCellInfo( 1, oTbr:nColumn('NAM') ) nX := oCel:nCol + 2 nW := oCel:nWidth - 10 @ nY, nX GETBOX NAM OBJ oGet HEIGHT nH WIDTH nW VALUE space(len(cPic)) ; BACKCOLOR oApp:BColorGet PICTURE cPic ; ON CHANGE Seek__Set(oTbr) ; INVISIBLE NOTABSTOP oGet:lOnGotFocusSelect := .F. oGet:OnEscape := {|og| og:GetObj():Hide(), oTbr:SetFocus(), .T. } oGet:OnEnter := {|og| og:GetObj():Hide(), oTbr:SetFocus() } oGet:OnDown := {|og| og:GetObj():Hide(), oTbr:SetFocus() } oGet:OnUp := {|og| og:GetObj():Hide(), oTbr:SetFocus() } END WINDOW ACTIVATE WINDOW &cWnd Save_Rest_HMG(aHmg) dbSelectArea(nAls) RETURN aReturn * ----------------------------------------------------------------------------------- * STATIC FUNC KliAdr() * ----------------------------------------------------------------------------------- * LOCAL cAdr, cAls := oTbr:cAlias If empty((cAls)->R_34) cAdr := Alltrim((cAls)->R_3 ) + ' ' + AllTrim((cAls)->R_3A) Else cAdr := Alltrim((cAls)->R_34) + ' ' + AllTrim((cAls)->R_35) EndIf RETURN cAdr * ----------------------------------------------------------------------------------- * STATIC FUNC Order_Set( oBrw, nKey, cKey ) * ----------------------------------------------------------------------------------- * LOCAL cOrd := (oBrw:cAlias)->( OrdSetFocus() ) If cOrd == "KOD" oBrw:nCell := oBrw:nColumn('NAM') oBrw:SetOrder( oBrw:nCell ) Else oBrw:nCell := oBrw:nColumn('KOD') oBrw:SetOrder( oBrw:nCell ) EndIf oBrw:SetFocus() RETURN Nil * ----------------------------------------------------------------------------------- * STATIC FUNC Seek__Set( oBr ) * ----------------------------------------------------------------------------------- * LOCAL oBrw := iif( empty(oBr), oTsb, oBr ) LOCAL cBrw := oBrw:Cargo LOCAL cAls := oBrw:cAlias LOCAL cNam := (cAls)->( OrdName() ) LOCAL cVal := _GetValue(cNam, oBrw:cParentWnd) If ! empty(cVal) If cNam == 'KOD' If 'U02' != cBrw cVal := TR0(cVal) EndIf Else cVal := ELRU(Trim(upper(cVal))) EndIf (cAls)->( dbSeek(cVal) ) oBrw:GotoRec( (cAls)->( RecNo()) ) DoEvents() EndIf RETURN Nil * ----------------------------------------------------------------------------------- * STATIC FUNC Press_Key( oBrw, nKey, cKey ) * ----------------------------------------------------------------------------------- * LOCAL cNam := (oBrw:cAlias)->( OrdName() ) LOCAL oSpr := _WindowObj(oBrw:cParentWnd) LOCAL oGet := oSpr:GetObj(cNam) If empty(nKey) oGet:Show() oGet:SetFocus() DoEvents() Else cKey := VK2Char(nKey) If len(cKey) > 0 oGet:Show() oGet:SetFocus() DoEvents() oGet:Get:VarPut(space(len(oGet:Get:Picture))) _PushKey(nKey) EndIf EndIf RETURN Nil * ----------------------------------------------------------------------------------- * STATIC FUNC Recno_Get( oBrw, nKey, cKey ) * ----------------------------------------------------------------------------------- * LOCAL cID := oBrw:Cargo LOCAL cAls := oBrw:cAlias LOCAL oWnd := _WindowObj(oBrw:cParentWnd) If cID $ 'U03,U04' AAdd(aReturn, (cAls)->R_1) AAdd(aReturn, (cAls)->R_2) ElseIf cID $ 'AGENT,KART' AAdd(aReturn, (cAls)->TNOM) AAdd(aReturn, (cAls)->FIO ) EndIf oWnd:Release() RETURN Nil ЗЫ oGet:OnEscape := {|og| og:GetObj():Hide(), oTbr:SetFocus(), .T. } oGet:OnEnter := {|og| og:GetObj():Hide(), oTbr:SetFocus() } oGet:OnDown := {|og| og:GetObj():Hide(), oTbr:SetFocus() } oGet:OnUp := {|og| og:GetObj():Hide(), oTbr:SetFocus() } это аналоги oGet:SetKeyEvent В задаче применяю (окно с тсб и рядом типа карточки) y := nRow x := nCol n := 'KliKod' // код клиента (справочник) @ y, x GETBOX &n OBJ o WIDTH oSt:W(10) HEIGHT oSt:H('G') VALUE space(4) ACTION wPost(91) IMAGE 'view' ; VALID SayGet_Value(.T., .T.) BACKCOLOR BG FONTCOLOR FC o:lOnGotFocusSelect := .T. o:OnEscape := {|og| oView:SetFocus(), .T. } o:OnF5 := {| | wPost(91) } y += This.&(n).Height + b n := 'KliNam' @ y, x GETBOX &n OBJ o WIDTH oSt:W(35) HEIGHT oSt:H('G') VALUE space(10) ; READONLY BACKCOLOR BG FONTCOLOR FC NOTABSTOP ... y += This.&(n).Height + b n := 'KliAgent' // код агента, для клиента (справочник) @ y, x GETBOX &n OBJ o WIDTH oSt:W(10) HEIGHT oSt:H('G') VALUE space(5) ACTION wPost(92) IMAGE 'view' ; VALID SayAgent_Value(.T., .T.) PICTURE '99999' BACKCOLOR BG FONTCOLOR FC o:lOnGotFocusSelect := .T. o:OnF5 := {| | wPost(92) } o:OnEscape := {|og| oView:SetFocus(), .T. } This.&(n).Value := TR0( Alltrim(gProp(Agent)), Len( This.&(n).Value ) ) x += This.&(n).Width n := 'NamAgent' @ y, x GETBOX &n OBJ o WIDTH oSt:W(25) HEIGHT oSt:H('G') VALUE space(30) ; READONLY BACKCOLOR BG FONTCOLOR FC NOTABSTOP ... и события (как я без них) For i := 1 To nCnt :Event( i, {|ow,ky| PressTBar(ow, ky), TsbCreate(ow, ky) } ) Next :Event( 91, {|ow | KliU04(ow) } ) :Event( 92, {|ow | KliAgent(ow) } ) :Event( 98, {|ow | OrdSave(ow) } ) :Event( 99, {|ow | oWnd:Action := .T., ow:Release() } ) END WITH // ---- Window events ... [/pre2]

Haz: Сергей Haz пишет: У меня есть очень draft, ну совсем бета альтернативного комбо в ячейке. Выдернул из проекта , переписал под CDX вроде работает . Логика похожа на твой пример - те же массивы заголовков, полей и пр. Подчеркиваю это совсем бета , по мере допиливаю понемногу. Но что это понятно из примера [pre2] #include "minigui.ch" #include "tsbrowse.ch" #include "hmg.ch" #include "common.ch" Static oMain Procedure Main() local i := 0 local cCol := "" PUBLIC aFont := {} SET OOP ON REQUEST DBFCDX SET CENTURY ON SET DELETED ON RDDSETDEFAULT('DBFCDX') DEFINE FONT Font_1 FONTNAME "Arial" SIZE 8 DEFINE FONT Font_2 FONTNAME "Arial" SIZE 8 ITALIC AAdd( aFont, GetFontHandle( "Font_1" ) ) AAdd( aFont, GetFontHandle( "Font_2" ) ) if ! File('base1.dbf') DBCreate( "BASE1.DBF" , {{"REC", "N", 4, 0},{"ID", "N", 4, 0} } ) end if ! File('base2.dbf') DBCreate( "BASE2.DBF" , {{"ID", "N", 4, 0}, {"NAME", "C", 20, 0} } ) end USE "BASE1.DBF" EXCL NEW ALIAS "BASE1" USE "BASE2.DBF" EXCL NEW ALIAS "BASE2" IF BASE2->(Eof()) FOR i := 1 TO 100 BASE2->(dbAppend()) BASE2->ID := i BASE2->NAME := RandStr( 20 ) END INDEX ON ID TAG "ID" TO "BASE2" END IF BASE1->(Eof()) FOR i := 1 TO 10 BASE1->(dbAppend()) BASE1->ID := i END END BASE2->(OrdSetFocus("ID")) DEFINE WINDOW Form1 ; AT 0,0 ; WIDTH 355 ; HEIGHT 600 ; TITLE "MAIN" ; MAIN ; FONT 'Tahoma' SIZE 10 oMain :=This.Object END WINDOW DEFINE TBROWSE oBrw At 25, 5 ALIAS "BASE1" ; OF Form1 ; WIDTH oMain:ClientWidth - 10 ; HEIGHT oMain:ClientHeight - 10 :LoadFields( TRUE ) :lCellBrw := TRUE :nHeightCell := 22 :nHeightHead := 22 END TBROWSE AEval(oBrw:aColumns(), {|oCol| oCol:bPrevEdit := {|xVal, oBrw| TEST_PrevEdit( xVal, oBrw ) } }) cCol := "REC" oBrw:SetColSize( cCol , 50) with object oBrw:GetColumn( cCol ) :cHeading := "RecNo #" :cPicture := Replicate("9", 4) :lEdit := FALSE :nAlign := DT_RIGHT :bData := { || BASE1->(RECNO()) } end cCol := "ID" oBrw:SetColSize( cCol , 250) with object oBrw:GetColumn( cCol ) :cHeading := "String" :cPicture := Replicate("X", 20) :lEdit := TRUE :nAlign := DT_LEFT :bData := { || SeekID( BASE1->ID ) } end Form1.CENTER ACTIVATE WINDOW Form1 Return FUNCTION RandStr( nLen ) LOCAL cSet := "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM" LOCAL cStr := "" LOCAL i := 0 FOR i := 1 TO nLen cStr += SubStr( cSet, Random( 52 ), 1 ) NEXT RETURN cStr FUNC SeekID(nId) LOCAL xRet := NIL IF BASE2->(dbSeek( nId, FALSE )) xRet := BASE2->NAME END RETURN xRet FUNC TEST_PrevEdit( xVal, oBrw ) LOCAL cCol := Upper(oBrw:aColumns[oBrw:nCell]:cName ) LOCAL cAlias := oBrw:cAlias LOCAL cSql := "" LOCAL nPos := 0 LOCAL nRecSave := 0 LOCAL nOrdSave := 0 LOCAL lRet := TRUE DO CASE CASE cCol == "ID" xLbx := LBX():New() xLbx:cAlias := "BASE2" xLbx:cRetField := "ID" xLbx:aHeaders := {'Тип'} xLbx:aWidth := {250} xLbx:aField := {'NAME'} xLbx:nHeightCell := 20 xLbx:nHeightHead := 0 xLbx:nHeightFoot := 0 xLbx:bPostBlock := {|| NIL } xLbx:ListBox( oBrw, xVal ) lRet := FALSE END RETURN lRet FUNC ToRGB(nColor) LOCAL nR := 0 LOCAL nG := 0 LOCAL nB := 0 LOCAL cColor := NTOC(nColor, 16) /* BBGGRR, где XX - число от 00 до FF. */ nR := CTON(SUBSTR( cColor, 5, 2 ), 16) nG := CTON(SUBSTR( cColor, 3, 2 ), 16) nB := CTON(SUBSTR( cColor, 1, 2 ), 16) RETURN {nR, nG, nB } //////////////////////////////// #include "minigui.ch" #include "tsbrowse.ch" #include "common.ch" #include "hmg.ch" #define GWL_STYLE (-16) #define GWL_EXSTYLE (-20) #define WS_BORDER 0x00800000 #define WS_EX_CLIENTEDGE 0x00000200 #define WS_EX_DLGMODALFRAME 0x00000001 #define WS_EX_LEFTSCROLLBAR 0x00004000 #define WS_EX_TOOLWINDOW 0x00000080 #define WS_DLGFRAME 0x00400000 #include "hbclass.ch" CREATE CLASS Lbx VAR oBrw VAR oBrwParent VAR oWLbx VAR oLbx VAR aHeaders INIT {} VAR aFooters INIT {} VAR aData INIT {} VAR aAlign INIT {} VAR aFAlign INIT {} VAR aHAlign INIT {} VAR aWidth INIT {} VAR aField INIT {} VAR aFont INIT {} VAR cAlias INIT "LBX" VAR cRetField INIT "NAME" VAR bPostBlock INIT nil VAR bSearch INIT nil VAR nHeightCell INIT 20 VAR nHeightHead INIT 20 VAR nHeightFoot INIT 20 METHOD New() METHOD ListBox(oBrw, xVal) METHOD Release(oBrw) METHOD UserKeys( nKey, nFlg, oBrw, oBrwParent, cRetField ) ENDCLASS METHOD Lbx:new() RETURN SELF METHOD Lbx:ListBox(oBrw, xVal) LOCAL nRecCount := 0 LOCAL nCol := 0 LOCAL nWidth := 0 LOCAL nHeight := 0 LOCAL nRow := 0 LOCAl oCell LOCAL aWRect := {0,0,0,0} LOCAL aCRect := {0,0,0,0} LOCAL lFlip := FALSE LOCAL i := 0 LOCAL nWh := 0 if !Empty( ::aWidth ) AEval(::aWidth, {|e| nWh += e + 1 }) end SET OOP ON GetWindowRect(oBrw:hWnd, aWRect ) oCell := oBrw:GetCellinfo(oBrw:nRowPos, oBrw:nCell, FALSE) nCol := oCell:nCol + aWRect[1] - Getproperty(oBrw:cParentWnd, oBrw:cControlName, "Col") nRow := oCell:nRow + aWRect[2] - Getproperty(oBrw:cParentWnd, oBrw:cControlName, "Row") nWidth := oCell:nWidth nHeight := oCell:nHeight // Поправка на координаты прииспользовании TAB IF __objHasData(oBrw, 'nColShift') IF oBrw:nColShift <> NIL nCol := nCol - oBrw:nColShift END END IF __objHasData(oBrw, 'nRowShift') IF oBrw:nRowShift <> NIL nRow := nRow - oBrw:nRowShift END END // // Если правый край выезжает за экрам IF nWh > nWidth IF nCol < aWRect[1] nCol := oCell:nCol + aWRect[1] - Getproperty(oBrw:cParentWnd, oBrw:cControlName, "Col") END IF nWh + nCol > Getproperty(oBrw:cParentWnd, "Width") nCol := Getproperty(oBrw:cParentWnd, "Width") - nWh - 35 END nWidth := nWh END // Если выезжает за низ окна IF oMain:ClientHeight - nRow - 130 < Min( ((::cAlias)->(RecCount()) + 2) * ::nHeightCell ,300 ) // Нужно показывать вверх lFlip := TRUE END DEFINE WINDOW LBEX ; AT nRow + IF( lFlip, -Min( ( (::cAlias)->(RecCount()) + 2) * ::nHeightCell ,300 ), nHeight ), nCol ; WIDTH nWidth ; HEIGHT Min( (::cAlias)->(RecCount() + 2) * (::nHeightCell) + (::nHeightCell) ,300 ) ; NOCAPTION ; CHILD ; ON LOSTFOCUS {|| oWLbx:Release()} ; ON RELEASE {|| ::Release( oBrw ) } oWLbx :=This.Object END WINDOW hWnd := GetFormHandle("LBEX") SetWindowLong(hWnd, GWL_EXSTYLE, WS_EX_TOOLWINDOW ) SetWindowLong(hWnd, GWL_STYLE, WS_DLGFRAME) (::cAlias)->(dbGoTop()) DEFINE TBROWSE oLbx At 25, 0 ALIAS ::cAlias ; OF LBEX ; WIDTH oWLbx:Width-3 ; HEIGHT oWLbx:Height - 30 ; END TBROWSE ::oBrw := oLbx ::oBrwParent := oBrw SetWindowLong (::oBrw:hWnd, GWL_EXSTYLE, WS_EX_STATICEDGE) if hb_isArray(::aField) .AND. Len( ::aField) > 0 ::oBrw:aColSel := ::aField endif ::oBrw:LoadFields( TRUE ) ::oBrw:lCellBrw := TRUE ::oBrw:nHeightCell := ::nHeightCell ::oBrw:nHeightHead := ::nHeightHead ::oBrw:nHeightFoot := ::nHeightFoot ::oBrw:lNoChangeOrd := TRUE ::oBrw:lNoHScroll := TRUE ::oBrw:ChangeFont( M->aFont[ 1 ], , 3 ) // nLevel 1 = Cells 2= Headers 3 = Footers ::oBrw:ChangeFont( M->aFont[ 1 ], , 2 ) // nLevel 1 = Cells 2= Headers 3 = Footers ::oBrw:ChangeFont( M->aFont[ 2 ], , 1 ) // nLevel 1 = Cells 2= Headers 3 = Footers ::oBrw:bLDblClick := {|| ; (::oBrwParent:cAlias)->&(::oBrwParent:GetColumn(::oBrwParent:nCell):cName ) := (::oBrw:cAlias)->&(::cRetField),; oWLbx:Release(); } ::oBrw:bUserKeys := {|nKy,nFl,oBr| ::UserKeys(nKy, nFl, oBr ) } ::oBrw:SetColor( { 6 }, { { |a,b,c| IF( c:nCell == b, -CLR_HRED , -RGB(128,225,225) ) } } ) // фон курсора ::oBrw:SetColor( { 2 }, { { || GetSysColor( COLOR_BTNFACE ) } }, ) // фон ::oBrw:hBrush := CreateSolidBrush( ToRGB(GetSysColor( COLOR_BTNFACE ))[1],; ToRGB(GetSysColor( COLOR_BTNFACE ))[2],; ToRGB(GetSysColor( COLOR_BTNFACE ))[3] ) IF hb_isArray( ::aWidth ) .AND. Len( ::aWidth ) > 0 FOR i := 1 TO Len(::aWidth) ::oBrw:SetColSize(i, ::aWidth[ i ] ) END ELSE ::oBrw:SetColSize(1, nWidth ) END IF hb_IsArray( ::aHeaders ) .AND. Len( ::aHeaders ) > 0 FOR i := 1 TO Len(::aHeaders) ::oBrw:aColumns[ i ]:cHeading := ::aHeaders[ i ] END END AEval(::oBrw:aColumns(), {|oCol| oCol:nClrSeleBack := oCol:nClrFocuBack, oCol:nClrSeleFore := oCol:nClrFocuFore, oCol:lEdit := FALSE }) DEFINE IMAGE Image_1 PARENT LBEX ROW 3 COL 0 WIDTH 15 HEIGHT 15 PICTURE 'FIND' STRETCH .F. END IMAGE DEFINE GETBOX Text_FTS PARENT LBEX ROW 0 COL 16 WIDTH oWLbx:Width - 42 HEIGHT ::nHeightCell VALUE Space(100) FONTNAME 'Arial' FONTSIZE 9 FONTBOLD FALSE TOOLTIP '' READONLY FALSE MAXLENGTH 100 BACKCOLOR {255,255,255} ON CHANGE IF( HB_IsBlock(::bSearch), Eval( ::bSearch, ::Self , This.Value ), nil ) END GETBOX DEFINE BUTTONEX Button_Del PARENT LBEX ROW 3 COL oWLbx:Width - 22 WIDTH 15 HEIGHT 15 ACTION {|| (::oBrwParent:cAlias)->&( ::oBrwParent:GetColumn(oBrw:nCell):cName ) := 0, oWLbx:Release() } CAPTION "" PICTURE "DB_CANCEL" TABSTOP .F. TOOLTIP "ВНИМАНИЕ Нажимая здесь Вы очистите значение в ячейке таблицы !" FONTNAME "Arial" FONTSIZE 9 END BUTTONEX ON KEY ESCAPE OF LBEX ACTION LBEX.Release Domethod( "LBEX", "Text_FTS", "SetFocus") ::oBrw:SetNoHoles() ::oBrw:SetFocus() ::oBrw:Reset() ACTIVATE WINDOW LBEX RETURN NIL METHOD Release( oBrw ) oBrw:SetFocus() oBrw:DrawSelect() IF(HB_IsBlock( ::bPostBlock), Eval(::bPostBlock, oBrw, oLbx ), NIL) RETURN NIL METHOD UserKeys( nKey, nFlg, oBrw ) Local uRet, cOrd, oCell, nRow, nPos nFlg := Nil do case case nKey == VK_RETURN .OR. nKey == VK_SPACE uRet := .F. (::oBrwParent:cAlias )->&( ::oBrwParent:GetColumn(::oBrwParent:nCell):cName ) := (::oBrw:cAlias)->&(::cRetField) oWLbx:Release() Case nKey < 48 oBrw:SetFocus() otherwise uRet := .F. oBrw:SetFocus() End RETURN uRet [/pre2]

SergKis: Игорь Поправь [ i ], начиная с этого текста и т.д. [pre2] IF hb_isArray( ::aWidth ) .AND. Len( ::aWidth ) > 0 FOR i := 1 TO Len(::aWidth) ::oBrw:SetColSize(i, ::aWidth[ i ] ) END ELSE ::oBrw:SetColSize(1, nWidth ) END [/pre2]

Dima: SergKis пишет: Игорь Поправь [ i ], начиная с этого текста и т.д. Поправил

Haz: Dima пишет: Поправил и я

SergKis: Haz пишет Глянешь, интересны идеи. Суть в том, что вместо комбика попытался использовать бровс по базе 1.Таких вариантов поля (Id -> наименование) замена, практически нет в работе, все как то сложнее. 2.Кроме id записи, есть клиентский код, который пользователи любят и вводят его (многие наизусть), а не через наименование. К примеру: - ФИО однозначно не определяет запись, надо ТАБ.НОМЕР и\или персональный код - наименование магазина, так же однозначно на дает запись, надо страну\город\адрес\регистр.номер(ИНН) или клиентский код - группы материалов\товаров могут иметь одинаковые наименования, но разные клиентские коды и др. показатели. ... 3.От ведения на тсб практически отказался, осталось только на совсем простеньких справочниках. Ввод, корректировку делаю на окне типа InputWindow(...) из hmg. Там validы, заполнение доп. полей и т.д. 4. Замену ComboBox-у делаю на GetBox-ах, как показал в примере выше. Если исп. в тсб на колонке вызов справочника, то исп. установку клавиши F5 на колонку (изменеия в MiniGui.lib перед примером выше) и VALID колонки, если значение задают не через вызов справочника, а кодом руками. Есть такое использование (в тсб) на окнах запросов для получения отчетов. 5.Мысли по твоему варианту: - возможность указывать, кол-во строк в тсб, если меньше, то окно меньше - располагать окно с тсб не только сверху\снизу, но и слева\справа, указывая L[eft],R[ight],T[op],B[ottom] - если использовать механизм назначенной клавиши для вызова списка, ввод в само поле можно исп. для поиска в списке или в footer, как у меня в примере

SergKis: Haz, Dima Как то правка не прошла [pre2] ::oBrw:aColumns[ i ]:cHeading := ::aHeaders[ i ] // тут надо, может и ниже тоже END END [/pre2]

Haz: SergKis пишет: Мысли по твоему варианту Про назначение клавиш - спасибо. Прикину как прикрутить. В остальном пример сильно кастрирван. Там есть список полей, которые нужно показать в бровсе и поле которое нужно вернуть из справочника. ID и NAME это частный случай. Поиск по справочнику делаю по содержимому getbox через вызов bSearch. В примере не смог его показать т. к. это FTS поиск от ADS, то есть по вхождению в любых полях. Как в CDX сделать не знаю. У меня для поиска клиента, к примеру, можно в Getbox ввести ИНН или КПП или форму собственноси или почтрвый индекс или чего ещё. или через пробел все это сразу сразу. В FTS задается что искать, любое или все. И бровс фильтрует записи по условию поиска. Все уже привыкли не думая набирать или часть наименования или адреса или телефона. А вот до назначения клавиш я не допер. Повешу на них доп инструмент. У меня главный косяк в том что на модальной форме этот бровс ругается что из модала можно только модал. А если бровс сам сделать модальным, то на нем не отыграть потерю фокуса так как модал не его потерять). Твой пример посмотрел, все понятно. Спасибо буду использовать

SergKis: Haz пишет У меня главный косяк в том что на модальной форме этот бровс ругается что из модала можно только модал. А если бровс сам сделать модальным, то на нем не отыграть потерю фокуса так как модал не его потерять). 1 Можно делать два типа окна для child и modal имея признак в объекте. - modal делать похожим на справочник и иметь кнопку выхода+Esc - child как сейчас, но можно и одинаково оформлять вызывать с модального окна модальный режим, с др. child 2 GetBox_FTS можно делать с двумя\одной родными кнопками с image для поиска\очистки или еще что то. 3 Исп. не bPrevEdit, а Valid и назн. клавишу для вызова списка, тогда в поле TGETBOX можно не вызывая списка вводить, если был On Change (меняем значение в поле тсб - поиск) по клавише или в valid по Enter вызываем объект списка, переносим значение из TGETBOX в GetBox_FTS с отработкой оного. 4 Иметь метод в объекте установки Row, Col отображения списка относительно родителя и задания кол-ва строк в списке

Haz: SergKis пишет: Можно делать два типа окна для child и modal 1 Буду тип задавать по типу родителя. Так решается проблема что из чего вызывать. Вот как быть с потерей фокуса у модала ?? не дает он его терять, а у меня на это событие справочник закрывается с отказом от выбора. 2 - 4 Согласен . это уже детали реализации.

SergKis: Haz пишет Вот как быть с потерей фокуса у модала ?? не дает он его терять, а у меня на это событие справочник закрывается с отказом от выбора. По мне, выбор по Enter, DblClick, Button Ok (выбор сделан, список убираем), а все остальное отказ. Выход базовый по кнопке крестику (своя, работа с NOCAPTION .T.) или Esc (отказ, список убираем). Потеря фокуса - для child режима - частный случай отказа

SergKis: PS Игорь, вспомнилось, ты вроде занимался морганием модальных окон при потере фокуса, можно туда приблуду вставить типа, по handle окна получить объект (если есть) и получить свойство bBlock := oW:GetProp('LostFocus') и если блок задан, выполнить Do_WindowEventProcedure ( bBlock, oW:Index, oW ) В объект окна списка ставить блок (ThisWindow.Object):SetProp('LostFocus', {|ow| ow:Release() }

Haz: SergKis пишет: Игорь, вспомнилось, ты вроде занимался морганием модальных окон при потере фокуса, можно туда приблуду вставить Примерно так и думаю. Пока ещё не смотрел. Хочу сделать не трогая исходников. Не получится., придется править.

SergKis: Haz пишет Не получится., придется править. Тогда в TWndData можно добавить DATA bLostFocusModal и устанавливать и работать с ним

Andrey: Andrey пишет: Сделал в версии 18.04 кол-во строк 240, подвал есть. На 250 строках подвала уже нет и вот такая таблица получается: ..... Что-то ерундит алгоритм выгрузки в эксель. Как и где подправить ? Предложение по правке этой ошибки (h_tbrowse.prg): [pre2] nColHead := 0 For nCol := 1 To Len( ::aColumns ) If aColSel != Nil .and. AScan( aColSel, nCol ) == 0 Loop EndIf uData := If( ValType( ::aColumns[ nCol ]:cHeading ) == "B", Eval( ::aColumns[ nCol ]:cHeading ), ; ::aColumns[ nCol ]:cHeading ) If ValType( uData ) != "C" Loop EndIf uData := StrTran( uData, CRLF, Chr( 10 ) ) nColHead ++ oSheet:Cells( nLine, nColHead ):Value := uData If hProgress != Nil If nCount % nEvery == 0 SendMessage( hProgress, PBM_SETPOS, nCount, 0 ) EndIf nCount ++ EndIf Next nStart := ++ nLine // поставить вместо этого nStart := nLine + 1 EndIf[/pre2] И ещё при печати подвала: [pre2] If AScan( ::aColumns, { |o| o:cFooting != Nil } ) > 0 For nCol := 1 To Len( ::aColumns ) If ( aColSel != Nil .and. AScan( aColSel, nCol ) == 0 ) .or. ::aColumns[ nCol ]:cFooting == Nil Loop EndIf uData := If( ValType( ::aColumns[ nCol ]:cFooting ) == "B", Eval( ::aColumns[ nCol ]:cFooting ), ; ::aColumns[ nCol ]:cFooting ) uData := cValTochar( uData ) uData := StrTran( uData, CRLF, Chr( 10 ) ) oSheet:Cells( nLine + 1, nCol ):Value := uData // вот так сделать Next EndIf[/pre2] Григорий, файл h_tbrowse.prg который присылал мне, я исправил и выслал на почту.

gfilatov2002: Andrey пишет: Предложение по правке этой ошибки Благодарю за это исправление Проблема с выводом подвала решена

Andrey: gfilatov2002 пишет: Проблема с выводом подвала решена ДА ! И проблема показа текстовых столбцов вида 3/2, 1/5 и т.д. ТОЖЕ решена в отправленном модуле !

Andrey: Вспомнил про ещё один баг в METHOD ExcelOle() ! После создания xls файла, сам Эксель уходин на второй план, т.е. под окно этого экспорта. Юзера ЗЛЯТСЯ ОЧЕНЬ на это !!! Для исправления этого нужно сделать так: [pre2] CursorArrow() ::Reset() If hProgress != Nil SendMessage( hProgress, PBM_SETPOS, 0, 0 ) EndIf If lActivate oExcel:Visible := .T. hWnd := oExcel:hWnd ShowWindow( hWnd, 6 ) // MINIMIZE windows INKEYGUI(100) ShowWindow( hWnd, 3 ) // MAXIMIZE windows BringWindowToTop( hWnd ) Else oExcel:Application:Quit() EndIf //::Reset() //If hProgress != Nil // SendMessage( hProgress, PBM_SETPOS, 0, 0 ) //EndIf Return Nil [/pre2] Такой код оставляет ЭКСЕЛЬ на переднем плане.

Alex_Cher: Andrey пишет: Вспомнил про ещё один баг в METHOD ExcelOle() А в oExcel := TOleAuto():New( "Excel.Application" ) можно получить такой же же эффект, что бы при создание Excel вылетал на передний план ?

Andrey: Alex_Cher пишет: можно получить такой же же эффект, что бы при создание Excel вылетал на передний план ? Да. Делай последние строчки так же как METHOD ExcelOle() и получишь такой же результат.

Andrey: Может такой код нужно ставить, чтобы Эксель оставался на экране: [pre2] If lActivate oExcel:Visible := .T. If VAL( oExcel:Version ) <= 13 // Excel 2003 ShowWindow( oExcel:hWnd, 6 ) // MINIMIZE windows ShowWindow( oExcel:hWnd, 3 ) // MAXIMIZE windows Endif Try BringWindowToTop( oExcel:hWnd ) // a window on the foreground End Try Else oExcel:Application:Quit() EndIf[/pre2]

Alex_Cher: Andrey пишет: Делай последние строчки так же как METHOD ExcelOle() Андрей, неверное я что-то не догоняю, с сырцах не нашел метод TOleAuto(): и куда добавлять ...?

Andrey: Alex_Cher пишет: неверное я что-то не догоняю, с сырцах не нашел метод TOleAuto(): и куда добавлять ...? Этот код добавляй в свою программу. Я писал про METHOD ExcelOle() который находиться MiniGUI\SOURCE\TsBrowse\h_tbrowse.prg Но этот метод Григорий исправит и будет достен в следующей версии.

Andrey: Нашёл ещё один баг в METHOD ExcelOle(): При многострочном построении Tsbrowsa при экспорте - получается так: Хотя таблица выглядеть должна примерно так: Как и где исправить код для этого метода ?

Alex_Cher: Andrey пишет: Этот код добавляй в свою программу. Андрей с Excel все получилось ... , почему с Word не получается - oWord:Visible := .T. hWnd := oWord:hWnd ShowWindow( hWnd, 6 ) // MINIMIZE windows INKEYGUI(100) ShowWindow( hWnd, 3 ) // MAXIMIZE windows BringWindowToTop( hWnd )

Andrey: Alex_Cher пишет: почему с Word не получается - Там фигня с Вордом. Я делаю так: [pre2] If lActivate oText:HomeKey(wdStory) // в начало текста oWord:Visible := .T. SetWordWindowToForeground(oWord) // окно Word на передний план EndIf RETURN NIL ////////////////////////////////////////////////////////////////////// // окно Word на передний план FUNCTION SetWordWindowToForeground(oWord) LOCAL hWnd, nVer, cCaption, cTitle // ------------------- поиск ХЕНДЛА открытого окна документа -------------- hWnd := 0 nVer := VAL( oWord:Version ) // Версия Word IF nVer > 14 // Word 2010 hWnd := oWord:ActiveDocument:ActiveWindow:Hwnd ELSE //hWnd:=oWord:hwnd - так делать нельзя ! cCaption := oWord:Windows[1]:Caption cTitle := cCaption + " - MICROSOFT WORD" hWnd := FindWindowEx(,,, cTitle ) IF hWnd == 0 cTitle := cCaption + " [Режим ограниченной функциональности] - MICROSOFT WORD" hWnd := FindWindowEx(,,, cTitle ) ENDIF ENDIF IF hWnd > 0 ShowWindow( hWnd, 6 ) // MINIMIZE windows ShowWindow( hWnd, 3 ) // MAXIMIZE windows BringWindowToTop( hWnd ) // A window on the foreground ENDIF RETURN NIL[/pre2] Смотри пример DBF_to_DOC_03.7z на https://abonent4.ru/minigui/

Alex_Cher: Andrey пишет: Там фигня с Вордом. Я делаю так: Все получилось, Андрей, большое тебе спасибо ....!



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