Форум » 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:....

Ответов - 300, стр: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 All

Dima: Andrey Рассчитывай ширины столбцов так , что бы не было виртуального столбца , тогда и красить ни чего не придется. PS Или юзай nAdjColumn

Andrey: Dima пишет: Рассчитывай ширины столбцов так , что бы не было виртуального столбца , тогда и красить ни чего не придется. Есть справочники состоящие из 2 колонок всего. Так что без виртуального столбца на экране никак не обойтись.

Haz: Andrey пишет: Так что без виртуального См obrw:hBrush в примерах


Dima: Andrey Где то была процедура заливки фантома (строки и столбца) , Has показывал , но с ходу не найду Еще можно попробовать поиграть с фантомным столбцом через объект oPhant (это я по быстрому на сырец глянул)

Andrey: Haz пишет: См obrw:hBrush в примерах Нашёл. Поставил себе - не работает !!! Делаю у себя 10 колонку: [pre2] ADD COLUMN TO oBrw1 HEADER "Lang" ; .......... COLOR CLR_BLACK, CLR_WHITE ; ..... [/pre2] Потом ставлю для блокировки цвета ещё 11 колонку: [pre2] // для избавления от белого цвета конца таблицы ADD COLUMN TO oBrw1 HEADER "" ; DATA {|| NIL } ; SIZE 0 ; COLOR nBackTable, nBackTable ; NAME ZERO [/pre2] Только тогда цвет виртуального столбца становиться в цвет фона таблицы. Но на экране некрасиво это выглядит, да и курсор туда убегает (становиться невидимым) - юзер теряться будет.....

Dima: Andrey пишет: Только тогда цвет виртуального столбца становиться в цвет фона таблицы. Но на экране некрасиво это выглядит, да и курсор туда убегает (становиться невидимым) - юзер теряться будет..... Растягивай первую колонку что бы не было фантомной.

Haz: Andrey пишет: Нашёл. Поставил себе - Тогда до понедельника

Haz: Andrey пишет: Только тогда цвет виртуального столбца становиться в цвет фона таблицы. Но на экране некрасиво это выглядит, да и курсор туда убегает (становиться невидимым) - юзер теряться будет..... А в исходники посмотреть? Там же буквами написано, что фантомная колонка ВСЕГДА красится в цвет той, которая перед ней. Другого указания цвета фантому в TS нет. Это было к вопросу почему фантом белый Теперь как исправить. Так же посмотреть в исходники и увидеть что после назначения цвета фантому по последней колонке выполняется ::bOnDrawLine ( если он определен ) и тогда исправить цвет становится просто - в этом блоке вызываем функцию , которая все лечит oBrw:bOnDrawLine := {|oBrw| SetPhantomBackcColor(oBrw) } [pre2] FUNC SetPhantomBackcColor(oBrw) IF oBrw:oPhant <> Nil oBrw:oPhant:nClrBack := RGB( 111, 183, 155 ) // к примеру пусть будет грязно голубой end RETURN NIL [/pre2]

Haz: Ну и напоследок бонус трек Самое простое и очевидное решение, просто поражающее простотой. Сделать колонку 11 скрытой

Dima: Haz пишет: Сделать колонку 11 скрытой Игорь крась яйца уже

Haz: Dima пишет: крась яйца Все покрашено с утра И яйца и фантом, хожу с кисточкой и думаю гдеб еще мазнуть

Dima: Haz

Andrey: Haz пишет: Самое простое и очевидное решение, просто поражающее простотой. Сделать колонку 11 скрытой Да подумал я об этом, сразу не сделал так как посчитал SIZE 0 будет 0, а не 2-3 пиксела как на экране. Спасибо за решение !

SergKis: gfilatov2002 Добавил, у себя, возмозможность уст. высоту Edit отличную от высоты Cell [pre2] CLASS TSBrowse FROM TControl ... DATA nHeightEdit AS NUMERIC INIT 0 // GetBox cell height ... METHOD Edit( uVar, nCell, nKey, nKeyFlags, cPicture, bValid, nClrFore, nClrBack ) CLASS TSBrowse ... IF ::nColSpecHd != 0 nRow := ::nHeightHead + ::nHeightSuper + If( oCol:l3DLook, 2, 0 ) nCol := nStartX + If( oCol:l3DLook, 2, 0 ) nWidth := ::GetColSizes()[ nCell ] - If( oCol:l3DLook, 2, 1 ) nHeight := ::nHeightSpecHd - If( oCol:l3DLook, 1, -1 ) else nRow := ::nRowPos - 1 nRow := ( nRow * ::nHeightCell ) + ::nHeightHead + ; ::nHeightSuper + ::nHeightSpecHd + If( oCol:l3DLook, 2, 0 ) nCol := nStartX + If( oCol:l3DLook, 2, 0 ) nWidth := ::GetColSizes()[ nCell ] - If( oCol:l3DLook, 2, 0 ) nHeight := ::nHeightCell - If( oCol:l3DLook, 1, -1 ) If ::nHeightEdit > 0 nI := nHeight - ::nHeightEdit If nI > 4 nHeight := ::nHeightEdit nRow += int(nI / 2) EndIf EndIf endif If oCol:cResName != Nil .or. oCol:lBtnGet ... [/pre2] Полезно при исп. тсб как аналог списка пар Label+GetBox без линий и с исп. image > 24

Dima: SergKis Так ее же можно установить в bPrevEdit с помощью SetGetAdjustBrw , нет ?

SergKis: Dima если ты имеешь ввиду aEditCellAdjust := {0,0,0,0}, то да, так можно управлять, но в моей версии этого нет и ... тогда предложение снимаю.

Dima: SergKis я имел в виду примерно такой код [pre2] obrw3:GetColumn("cod"):bPrevEdit := { |a, b, lLock| SetGetAdjustBrw(b,{2,0,-2,-3}) ............. [/pre2]

SergKis: Дима, где есть SetGetAdjustBrw(...) ? Просканировал MiniGui, не получил результата. Потом bPrevEdit исп. для простой ситуации (а если много колонок) ..., слишком сложно. В целом имея высоту getbox мне хватает того, что у себя сделал. А ширина всегда по ширине cell, этим манипулирует пользователь, а я - picture

Dima: Сергей я тупанул Это я свою функцию заюзал Func SetGetAdjustBrw(o,amas) o:aEditCellAdjust[1]:=amas[1] o:aEditCellAdjust[2]:=amas[2] o:aEditCellAdjust[3]:=amas[3] o:aEditCellAdjust[4]:=amas[4] return .t. Ты был прав насчет aEditCellAdjust

SergKis: Дима, зачем ты в это делаешь в bPrevEdit, разве не достаточно простого на весь tsb nHget := 22 nH := :nHeightCell - nHget If nH > 4 :aEditCellAdjust[1] := int(nH / 2) :aEditCellAdjust[4] := nHget EndIf для мультистрок будет своя высота пересчитана, а для др. ситуаций сделанного, достаточно

SergKis: PS :aEditCellAdjust[4] := -nH

SergKis: Похоже :aEditCellAdjust - возможность задать отступы в Cell (:aEditCellAdjust := {-2,-1,-1,-2}), а размеры редактирования это свойства колонки и должны быть в TColumns. Что то такое [pre2] DATA nEditWidth AS NUMERIC INIT 0 // editing width DATA nEditHeight AS NUMERIC INIT 0 // editing height [/pre2] с вытекающими из этого действиями ...

Dima: SergKis пишет: Дима, зачем ты в это делаешь в bPrevEdit Кто то подсказал в свое время , так и прижилось.

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

Dima: Haz У меня проблема была другого плана. После выхода из режима редактирования ячейки , "сетка" по периметру ячейки исчезала , поэтому координаты GET пришлось изменить что бы он не налазил на края ячейки.

SergKis: Dima пишет координаты GET пришлось изменить что бы он не налазил на края ячейки. Так это Григорий подправлял и сейчас все нормуль

Dima: SergKis пишет: Так это Григорий подправлял и сейчас все нормуль У меня версия еще от июня 2016 года , он правил позже ?

SergKis: Дима, трудно сказать, надо искать (там было GoLeft() и что то еще) Но уже давно, переносил изм. к себе помню ...

Dima: SergKis пишет: надо искать (там было GoLeft() и что то еще) Пороюсь. А GoLeft() был в 2008 году

SergKis: Dima пишет А GoLeft() был в 2008 году Позже было и GoRight и GoDown Нашел http://clipper.borda.ru/?1-1-40-00000454-000-180-0 пост N 848 от 06.11.15 21:33. gfilatov2002 пишет Вроде удалось поправить прорисовку разделительной линии в методах GoRight и GoDown С тех пор прорисовка линий после edit нормальная.

Dima: SergKis пишет: Позже было и GoRight и GoDown Да я чисто шарил по C:\MiniGUI\Doc\ChangeLog.txt а там только 8 год всплыл , да и фиг с ним )) SergKis пишет: пост N 848 от 06.11.15 21:33. И да , версия Минигуи у меня была уже старше и точно не 15 год )) SergKis пишет: С тех пор прорисовка линий после edit нормальная. Не понятно зачем я тогда правил все это дело на свежем Минигуи 2016 года Но глючило 100 %

Haz: Dima пишет: Но глючило 100 % И сейчас глючит. Без белых засветов вокруг закрытого гет обьекта, но линии гряды трет

SergKis: Haz пишет но линии гряды трет В какой ситуации ? Погонял примеры - не трет. У меня версия, тоже не трет.

Haz: SergKis пишет: В какой ситуации ? В ситуации обычного гетбокса. Сейчас точно сказать не могу т. к не на работе. Стандартная библиотека, прошлая или позапрошлая. Без выравнивани границ гет обьекта. После редактирования затирается одна из горизонтальных границ. Из дополнительных условий- двойной курсор с градиентом и браш на бровсе в цвет фона строк. Завтра погоняю, напишу подробнее. Но в принципе не напрягает, белых засветов нет и при желании легко исправляется выравниванием границ гет поля.

SergKis: Haz пишет Но в принципе не напрягает Только не хотелось, что бы клиент носом ткнул в эту ситуёвину

Haz: SergKis пишет: Только не хотелось, что бы клиент носом Перед сдачей клиенту всех мелких тараканов обычно принято давить. Но иногда и не до них бывает т. к есть и не мелкие) К примеру иногда наблюдаю традиционное залипание нижней строки. Понятно что исправимо, и не на всех рабочих местах у клиента проявляется. Такие вещи полирую уже при тестовой эксплуатации, т. к. с вероятностью больше 50% будут изменения в интерфейсе когда люди начнут работать.

gfilatov2002: Haz пишет: Но иногда и не до них бывает т. к есть и не мелкие Подтверждаю Вот набрел на ошибку, возникающую при использовании SPINNER внутри GetBox поля (при использовании метода oBrw:SetSpinner()). Проблема заключается в том, что при нажатии на ползунки этого Spinnerа начинает убегать указатель с текущей записи Haz Может, поможите побороть эту бяку

Haz: gfilatov2002 пишет: Может, поможите побороть эту бяку Григорий завтра посмотрю. Сейчас сижу болею дома

Dima: Haz пишет: Сейчас сижу болею дома Выздоравливай !!!

Haz: gfilatov2002 пишет: Проблема заключается в том, что при нажатии на ползунки этого Spinnerа начинает убегать указатель с текущей записи Это следствие , причина в том, что бровс получает команду сдвинуть этот указатель ползунками или кнопками не важно. Если в METHOD Command( nWParam, nLParam ) CLASS TControl закоментировать убиение фокуса [pre2] case nNotifyCode == EN_KILLFOCUS ::LostFocus() [/pre2] сразу видно как управляется бровс , а убиение фокуса просто делает это невидимым Пол дня проковырялся - безрезультатно. Не могу понять кто и где эту команду бровсу посылает Позже еще продолжу.

Haz: Поправлюсь не закоментить KillFoсus а нооборот показать добавив ниже case nNotifyCode == EN_SETFOCUS ::SetFocus() Пока все что выяснил - При нажатии какой-либо стрелки спина он посылает родительскому окну сообщение WM_VSCROLL. а родительским заявлено окно бровса и это заставляет бровс бегать по записям. Можно попробовать использовать флаг ::lDontChange , который учитывать при обработке событий в TSBrowse:HandleEvent() , можно попробовать в событиях просто фильтрануть lParam в котором будет передан дескриптор спина ( он определяется как ::hWndChild в METHOD TBtnBox:New() но в нем и хоронится и никуда не передается ) На скорую руку попробовал , частично помогает , но при выходе из режима редактирования чтото уперто сдвигает указатель на ::GoTop()

Haz: Григорий По поводу спиннера и дергания записей это частично решает проблему ( просто фильтруем в бровсе сообщения от спеннера) [pre2] * ============================================================================ * METHOD TSBrowse:HandleEvent() Version 9.0 Nov/30/2009 * ============================================================================ METHOD HandleEvent( nMsg, nWParam, nLParam ) CLASS TSBrowse #ifdef __HARBOUR__ ElseIf nMsg == WM_KEYUP Return ::KeyUp( nWParam, nLParam ) ElseIf nMsg == WM_VSCROLL If ::lDontchange Return Nil EndIf if nLParam == 0 Return ::VScroll( Loword( nWParam ), HiWord( nWParam ) ) endif #EndIf [/pre2] т.е. исключаем из обработки бровсом сооющения от спенера, но пока частично решает при первом клике в колонке со спином и выходе из редактирования запись улетает на GoTop() потом сколько не редактируй и не кликай по спину - все ОК скорее всего после первого редактирования выставляется какой нить внутренний флаг и потом его обрабатывает правильно что переводит запись в GoTop - так и не нашел, тк не смог поймать пока это единственное первое событие

gfilatov2002: Haz Благодарю за реальную помощь в этом вопросе! Haz пишет: исключаем из обработки бровсом сообщения от спайнера Принимается

SergKis: gfilatov2002 [pre2] METHOD LDblClick( nRowPix, nColPix, nKeyFlags ) CLASS TSBrowse ... If ( nClickRow == ::nRowPos .and. nClickRow > 0 ) .or. ( nClickRow == ::nRowPos .and. ! ::lDrawHeaders ) If ::lCellBrw .and. ::IsEditable( nCol ) ::nColSpecHd := 0 If ValType( Eval( ::aColumns[ nCol ]:bData ) ) == "L" .and. ; ::aColumns[ nCol ]:lCheckBox // virtual checkbox ::PostMsg( WM_CHAR, VK_SPACE, 0 ) ElseIf ::aColumns[ nCol ]:oEdit != Nil ::PostMsg( WM_KEYDOWN, VK_RETURN, 0 ) ElseIf ::bLDblClick != Nil Eval( ::bLDblClick, uPar1, uPar2, nKeyFlags, Self ) Else ::PostMsg( WM_KEYDOWN, VK_RETURN, 0 ) EndIf ... [/pre2] по мне, так правильнее будет. bLDblClick задан, но не срабатывает в этой ситуации (так было)

gfilatov2002: SergKis пишет: bLDblClick задан, но не срабатывает в этой ситуации Понимаю Вашу логику, но у автора библиотеки этот кодовый блок используется только для НЕ редактируемых TSBrowse Это явно следует из кода метода LDblClick

SergKis: gfilatov2002 пишет но у автора библиотеки этот кодовый блок используется только для НЕ редактируемых Мне кажется, у автора не до конца продумано. При наличии :nFireKey посылать надо oBr:PostMsg( WM_KEYDOWN, VK_F4, 0 ) а не VK_RETURN К примеру edit включаем VK_F4 ( :nFireKey := VK_F4 ), а VK_RTUEN назначить надо выбор строки. При работе со справочниками это сплошь и рядом - на окне где ТОЛЬКО справочник VK_RETURN может включать edit, а в вызове справочника (GrtBox) для выбора из списка (все операции по ведению спр. присутствуют) - VK_ENTER\bDblClick - это выбор строки для занесения данных в документ. В сегодняшней версии это затруднительно сделать простым способом

SergKis: PS правильно посылать надо oBr:PostMsg( WM_KEYDOWN, oBr:nFireKey, 0 )

gfilatov2002: SergKis пишет: При работе со справочниками это сплошь и рядом Тогда принимается - Вам виднее Благодарю за дополнительное разъяснение

Andrey: Что то перестал отображаться чекбокс в Tsbrowse. Версия MiniGUI Extended Edition 16.11 - работает отлично ! Версия MiniGUI Extended Edition 17.04 - не отображает.... Вот скрин экрана: Мышкой по чекбоксу кликаешь - нет отображения... Что там нужно доп. сделать у себя в коде чтобы отображалась ? В коде создаю колонку так: [pre2] // создать 3-ю колонку ADD COLUMN TO oBrw2 HEADER "Печать"+CRLF+"в таблице" ; DATA FieldWBlock( "VIEW", Select() ) ; ...... oBrw2:aColumns[3]:bPrevEdit := {|| HeadCheckField(), FALSE } // проверка до ввода[/pre2] В функции HeadCheckField() в конце обработки ставлю: [pre2] oBrw1:Reset() oBrw1:Refresh(.T.) oBrw2:Refresh(.T.) RETURN NIL[/pre2] Больше никаких функций не использую...

Dima: Andrey пишет: Версия MiniGUI Extended Edition 17.04 - не отображает.... Чеканул пример C:\MiniGUI\SAMPLES\Advanced\Tsb_array_2\ Все кажет норм !

Andrey: Dima пишет: Чеканул пример C:\MiniGUI\SAMPLES\Advanced\Tsb_array_2\ Все кажет норм ! Там по другому создаётся бровс. У меня конкретно в версии 16.11 работает, а в 17.04 - не отображает чекбокс. Что там сделали в исходниках я не знаю, но правка была же, если перестало работать ! По пробелу или по клику мышке ПЕРЕСТАЛ работать чекбокс после версии 16.11 ! Может быть из-за того что использую сразу ДВА бровса ? Как можно перерисовать конкретно 3 колонку после ввода ? Поможет ли это ? Попробовал поставить - oBrw2:aColumns[3]:bPostEdit := {|| oBrw2:DrawSelect(), FALSE } // проверка после ввода НЕ ПОМОГАЕТ !!!

Dima: Andrey пишет: По пробелу или по клику мышке ПЕРЕСТАЛ работать чекбокс после версии 16.11 ! Долго же ты ждал пока понял что не пашет :)

Andrey: Dima пишет: Долго же ты ждал пока понял что не пашет :) Да это не главное меню в программе. Редко кто пользуется. Вот и обнаружил с таким промежутком времени. Попробую проверить другие версии...

Andrey: Проверил. В версии 17.02 работает, а в 17.03 - уже не отображает чекбокс. Т.е. - по пробелу или по клику мышке ПЕРЕСТАЛ работать чекбокс после версии 17.02 ! Что нужно мне добавить в свой код чтобы по клику мышки стал отображаться чекбокс ? Использую сразу ДВА бровса на одном окне.

Dima: Andrey пишет: Т.е. - по пробелу или по клику мышке ПЕРЕСТАЛ работать чекбокс после версии 17.02 Так это не чекбокс по ходу а просто BMP как и на другом бровсе в твоем скрине

gfilatov2002: Andrey пишет: oBrw2:aColumns[3]:bPrevEdit := {|| HeadCheckField(), FALSE } // проверка до ввода Попробуй изменить это кодовый блок таким образом oBrw2:aColumns[3]:bPrevEdit := {|| HeadCheckField(), TRUE }

Andrey: gfilatov2002 пишет: Попробуй изменить это кодовый блок таким образом Так заработало ! Спасибо большое ! Хотя если только ОДИН бровс, то работает и со старым синтаксисом. Смотри пример Tsb_composite_(1.2).7z который я высылал... Там в 3х местах используется: [pre2] oBrw1:aColumns[3]:bPrevEdit := {|| FieldCheckBoxEdit(), FALSE } oBrw1:aColumns[4]:bPrevEdit := {|| FieldCheckBoxEdit(), FALSE } oBrw1:aColumns[5]:bPrevEdit := {|| FieldCheckBoxEdit(), FALSE } [/pre2]

Andrey: Ха, в версии 17.03 и выше перестал работать пример Tsb_composite_(1.2).7z - там где выбор флагов производиться... Один раз выбрать можно, на втором - программа НАГЛУХО ВИСНЕТ !!! Вот сам проект - https://cloud.mail.ru/public/2SXc/UtNfso4gf Что-то в коде нужно добавить ?

Andrey: Опять непонятка в работе функций.... Григорий, проект у тебя есть - Send2Mail.hbp Там вызов функции в модуле Tsb_send.prg строка: [pre2] oBrw:Excel2(cFile, lActivate, NIL, "_"+Space(70)+Form_0.Title, lSave )[/pre2] Версия 17.02 - работает, а в других уже НЕТ !!! Что там докрутить/исправить нужно, чтобы заработало ?

Andrey: Разобрался сам... Оказывается если нет такого пути к файлу, то Ексель и не создаёт и не открывает его ! Григорий, там можно в исходниках поставить проверку на создания по пути файла ?

Dima: Andrey пишет: Разобрался сам... Оказывается если нет такого пути к файлу, то Ексель и не создаёт и не открывает его Про это уже писалось и не раз ! Бывает :)

Vlad04: Haz Редактирование Ключевого поля в TsBrows. Я писал, что после выхода из редактирования курсор не поднимается на нужную строку Игорь, как-то выкладывал пример редактирования ключевого поля, но в примере были особенности- вторая форма для редактирования, программное построение Бровса и т.д. Посмотрите пример построенный в основном в Дизайнере - click here, может удастся заставить курсор подниматься ? И еще , при входе в редактирование сетка пропадает.

Dima: Vlad04 пишет: И еще , при входе в редактирование сетка пропадает. Почитай начиная с поста 6376 этой темы

Vlad04: Dima Все темы читаю. В примере кода практически нет, все должно работать по- умолчанию ( или почти всё) без танцев с бубном.

SergKis: Vlad04 пишет В примере кода практически нет, все должно работать по- умолчанию ( или почти всё) без танцев с бубном. Танцы вы сами придумали себе кодом: oBrw_1:aColumns[1]:bPrevEdit := { || oBrw_1:Upstable() , oBrw_1:Refresh(.T.) , oBrw_1:ResetVScroll() , .t. } запустив перед edit кучу процедур по прорисовке тсб, при этом совершенно забыв про очередь сообщений, по которой и происходят действия прорисовки. Все темы читаю но чуть чуть по диагонали. В примере Tsb_addrecord_3 ситуация с обработкой очереди для прорисовки показана была:[pre2] STATIC FUNC Add_Rec( oBrw ) ... If ! Empty(aResult) dbSelectArea(cAls) dbAppend() If ! NetErr() .and. RLock() nRec := RecNo() REPL KODS with aResult[1], ; NAME with aResult[2] If oBrw:nLen == oBrw:nRowCount() oBrw:oHScroll:SetRange(0,0) EndIf oBrw:GotoRec(nRec) nCol := oBrw:nColumn("NAME") If nCol != oBrw:nCell oBrw:nCell := nCol oBrw:DrawSelect() EndIf oBrw:lChanged := .T. oBrw:PostEdit(aResult[2], nCol, Nil) DO EVENTS oBrw:PostMsg(WM_KEYDOWN, VK_F4, 0) EndIf EndIf ... [/pre2] т.е. если убрать DO EVENTS много разного увидите

Haz: Vlad04 пишет: может удастся заставить курсор подниматься ? И еще , при входе в редактирование сетка пропадает. Нет ничего проще 1) в Form_0.fmg удалить это ON INIT Init_Form_0() и соответственно саму функцию в програмном модуле tsb.prg 2) в tsb.prg сделать так LOAD WINDOW Form_0 oBrw_1:SetIndexCols( 1 ) oBrw_1:SetOrder( 1 ) Form_0.Center Form_0.Activate PS Сергей прав по поводу танцев, но уверен со временем все уляжется в голове и танцы будут не нужны

Vlad04: SergKis примере Tsb_addrecord_3 Конечно,смотрел и этот пример. Многое не понял. Для такого простого результата - на форме одна таблица с 4-мя кнопками, код очень сложный. А если на форме несколько таблиц, а в программе десяток форм.... Haz oBrw_1:SetIndexCols( 1 ) oBrw_1:SetOrder( 1 ) просто и работает

Vlad04: Курсор поднимается , но на одно строку промахивается. При движении вниз так же ошибка на одну строку.

SergKis: Vlad04 пишет А если на форме несколько таблиц Код в примере практически не изменится для всех таблиц, используемых на окне(ах). Изменятся параметры задания колонок, валидности и др. не стандартных действий. И в примере есть ввод, едит и удаление (все сводится к примерно tsb_array_2 для таблиц). В вашем нет (якобы кода) ничего,кроме едит, но будет куча fmg для справочников в чилд\модал окнах, привязанных к железным алиасам. Не уверен, что это проще. Многое не понял Так лучше спросить, чем оставаться в не понятках. просто и работает Так это работало со времен примера Tsb_addrecord_2 [pre2] oBrw:SetIndexCols( oBrw:nColumn("ID"), ; oBrw:nColumn("INFO") ) oBrw:SetOrder( oBrw:nColumn("ID") ) [/pre2]

SergKis: Vlad04 пишет но на одно строку промахивается. После редактирования у колонки есть свойство, куда деть курсор после, по умолчанию переместиться дальше ... Потому такой результат. Поставьте [pre2] oBrw_1:aColumns[1]:nAlign := DT_LEFT oBrw_1:aColumns[ 1 ]:nEditMove := DT_DONT_MOVE oBrw_1:SetIndexCols(1) oBrw_1:SetOrder(1) oBrw_1:SetFocus() Form_0.Center Form_0.Activate [/pre2]

Vlad04: SergKis куча fmg для справочников в чилд\модал окнах, привязанных к железным алиасам. Не уверен, что это проще. Это и хорошо , что есть варианты.У меня есть одна универсальная форма для типовых справочников и отдельные формы для остальных случаев. Так это работало со времен примера Tsb_addrecord_2 Не понял сразу, в Делфи для Бровса( там это грид) несколько другая идеология - отображать данные, а не управлять ими.Да и консольный Харбор ведет себя по-другому.

Vlad04: Уф!! Теперь все нормально ! Спасибо всем !

SergKis: Vlad04 пишет У меня есть одна универсальная форма для типовых справочников и отдельные формы для остальных случаев. т.е. из меню главного окна у вас нельзя вызвать несколько окон справочников одновременно, только по очереди, т.к. в fmg прописан конкретный алиас в одной унив. форме ?

Andrey: SergKis пишет: т.е. из меню главного окна у вас нельзя вызвать несколько окон справочников одновременно А зачем юзеру редактировать/смотреть сразу несколько справочников ? Я тоже сделал одно модальное окно для справочника и туда передаю параметры из ини-файла (алиасы, поля базы и т.д.) для различных справочников. Иначе юзера начинают путаться с большим количеством справочников на экране.

SergKis: Andrey пишет А зачем юзеру редактировать/смотреть сразу несколько справочников ? Загнать в рамки дос пользователя - это вариант. А при работе с док. и спр. номенклатуры, разве не может возникнуть вопрос (по тел., от др. службы) по клиентскому спр., по автотранспорту (свой\чужой), по адресам погрузки\разгрузки, по ценнику клиента ...Что бросать (выходить) из того с чем работал или откладывать ответы на потом ... Иначе юзера начинают путаться с большим количеством справочников на экране Так это твое дело организация, что бы не путался, не дублировался, не используемый убирался. Ведь excel с sheetами не запрещают одновременно работать (типа можно но только последовательно). А ты выходит запрещаешь. Не демократично как то.

Andrey: SergKis пишет: Не демократично как то. Не... с юзерами демократию разводить не надо ! Сказали бурундук птичка и никаких зверьков и все ! С другой стороны, действительно можно дать возможность юзеру вернуться к отложенному справочнику. Интересно а как в 1С это реализовано или в других системах ? Но это наверное уже для другой ветки обсуждения, а не здесь.

PSP: Andrey пишет: Интересно а как в 1С это реализовано или в других системах ? Демократично)

Vlad04: SergKis у главного окна у вас нельзя вызвать несколько окон справочников одновременно Можно, форма универсальная для простых справочников, типа - код, наименование и т.д. В такой Форме алиасы , поля не прописаны и у меня считываются из файла при открытии формы.Эта форма описана полностью в виде кода, т.е. без дизайнера ( в нем в этом случае точно нет смысла) .

Andrey: Есть мой тестировочный проект. Раньше работал, сейчас нет. С какой версии перестал работать, даже не знаю. Сейчас вешается ВЕСЬ проект вот с таким сообщением: Вот сам проект - https://cloud.mail.ru/public/2SXc/UtNfso4gf Виснет - там где выбор флагов производиться... Один раз выбрать можно, на втором - программа НАГЛУХО ВИСНЕТ !!! Там даже второй выбор не нужно производить. Первый раз выбираем меню с флагами, потом мышкой кликаем на другой колонке (или стрелкой вверх/вниз) и тоже программа НАГЛУХО виснет !! Методом отладки определил, что перестают работать вот эти функции ПОСЛЕ выбора из модуля Form_Lang.prg: [pre2]_SetMenuItemBitmap ( "MYTABLERECNOMARK" , cForm , "CheckF28" ) _SetMenuItemBitmap ( "MYTABLERECNOPRINT", cForm , "CheckF28" ) _SetMenuItemBitmap ( "MYTABLERECNOSAVE" , cForm , "CheckF28" ) _SetMenuItemBitmap ( "MYTABLERECNOMAIL" , cForm , "CheckF28" ) [/pre2] Модуль demo.prg - строка 534 Помогите пожалуйста разобраться....

Vlad04: Выбор правой мышкой из контекстного меню ? Все работает !

Andrey: Vlad04 пишет: Выбор правой мышкой из контекстного меню ? НЕТ ! Vlad04 пишет: Все работает ! Виснет - там где выбор флагов производиться... Один раз выбрать можно, на втором - программа НАГЛУХО ВИСНЕТ !!! Там даже второй выбор не нужно производить. Первый раз выбираем меню с флагами, потом мышкой кликаем на другой колонке (или стрелкой вверх/вниз) и тоже программа НАГЛУХО виснет !!

Andrey: Привет всем ! Забыл как сделать чтобы после выбора из tsbrowse оставалась серая линия на выбранной строке таблицы. Подскажите пожалуйста ?

SergKis: Andrey пишет Забыл как сделать чтобы после выбора из tsbrowse оставалась серая линия на выбранной строке таблицы. См. Tsb_addrecord_3 Del_Rec(...) :lNoGrayBar

SergKis: Надоело везде писать (как бы лишнее, по мне) :bUserKeys := {|nKy,nFl,oBr| OnKeyDown(nKy, nFl, oBr) } и STATIC FUNC OnKeyDown( nKey, nFlg, oBrw ) // обработка KeyDown ... IF nKey == VK_RETURN ... ELSEIF nKey == VK_F2 ... ENDIF RETURN uRet Немного добавил в TsBrowse [pre2] CLASS TSBrowse FROM TControl ... DATA aUserKeys INIT hb_Hash() DATA lUserKeys INIT .F. ... METHOD UserKeys( nKey, bKey, lCtrl, lShift ) ... ENDCLASS METHOD UserKeys( nKey, bKey, lCtrl, lShift ) CLASS TSBrowse Local cKey := 'other', uVal If HB_ISBLOCK(bKey) // установить блок на ключ в hash If ! empty(nKey) If HB_ISNUMERIC(nKey) cKey := hb_ntos(nKey) cKey += iif( empty(lCtrl ), '', '#' ) cKey += iif( empty(lShift), '', '^' ) ElseIf HB_ISCHAR(nKey) cKey := nKey EndIf EndIf hb_HSet( ::aUserKeys, cKey, bKey ) ::lUserKeys := len(::aUserKeys) > 0 Else // выполнить блок по ключу из hash If HB_ISNUMERIC(nKey) cKey := hb_ntos(nKey) ElseIf HB_ISCHAR(nKey) cKey := nKey EndIf If ::lUserKeys // есть уст. блоки кода uVal := hb_HGetDef( ::aUserKeys, cKey, NIL ) If HB_ISBLOCK(uVal) cKey := Eval( uVal, Self, nKey, cKey, bKey, lCtrl, lChift ) EndIf EndIf EndIf RETURN cKey METHOD KeyDown( nKey, nFlags ) CLASS TSBrowse ... ::lNoPaint := .F. ::oWnd:nLastKey := ::nLastKey := ::nUserKey := nKey If ::lUserKeys uTemp := hb_ntos(nKey) uTemp += iif( _GetKeyState( VK_CONTROL ), "#", "" ) uTemp += iif( _GetKeyState( VK_SHIFT ), "^", "" ) uVal := hb_HGetDef( ::aUserKeys, uTemp, NIL ) If ! HB_ISBLOCK(uVal) uTemp := 'other' uVal := hb_HGetDef( ::aUserKeys, uTemp, NIL ) Endif If HB_ISBLOCK(uVal) uReturn := Eval( uVal, Self, nKey, uTemp ) If uTemp == 'other' .and. ! HB_ISLOGICAL(uReturn) uReturn := .T. EndIf If uReturn == Nil .or. ( HB_ISLOGICAL(uReturn) .and. ! uReturn ) ::nLastKey := 255 Return 0 EndIf uReturn := NIL EndIf uTemp := uVal := NIL EndIf If ::bUserKeys != Nil ... теперь в проге можно писать так :nFireKey := VK_F4 // default Edit If lRec_Select // режим выбор записи :bLDblClick := {|uP1,uP2,nFl,oBr| Get_Rec(oBr, uP1, uP2, nFl) } :UserKeys(VK_RETURN, {|oBr | Get_Rec(oBr) }) Else // режим Edit записи :bLDblClick := {|uP1,uP2,nFl,oBr| uP1 := uP2 := nFl := Nil, ; oBr:PostMsg( WM_KEYDOWN, oBr:nFireKey, 0 ) } :UserKeys(VK_RETURN, {|oBr | oBr:PostMsg( WM_KEYDOWN, oBr:nFireKey, 0 ) }) EndIf :UserKeys(VK_F2 , {|oBr,nKy,cKy| Add_Rec(oBr, nKy, cKy) }) :UserKeys(VK_F3 , {|oBr,nKy,cKy| Del_Rec(oBr, nKy, cKy) }) :UserKeys(VK_F3 , {|oBr,nKy,cKy| MsgBox(cKy, 'Ctrl + F3') }, .T.) :UserKeys(VK_F3 , {|oBr,nKy,cKy| MsgBox(cKy, 'Shift + F3') }, , .T.) :UserKeys(VK_F3 , {|oBr,nKy,cKy| MsgBox(cKy, 'C + S + F3') }, .T., .T.) // :UserKeys( , {|oBr,nKy,cKy| _LogFile(.T.,cKy, 'other', nKy ) }) // это обработка др. нажатий, уст. на ключ 'other' default Если уст. блок кода возвращает Nil или .F. Method KeyDown завершается (все выполнено), при возврате .T. Method KeyDown работает дальше. Может будет полезно, a c :bUserKeys осталось, как раньше [/pre2]

SergKis: Поясню назначение кода Else // выполнить блок по ключу из hash ... Установив на тсб :UserKeys(1.1, {|o|...}) :UserKeys(1.2, {|o|...}) :UserKeys('rpt1', {|o|...}) :UserKeys('rpt2', {|o|...}) ... на кнопках, пунктах, меню и т.д. ( для этого тсб) можно вызывать oBrw1:UserKeys(1.1, Param1, Param2, Param3) oBrw1:UserKeys('rpt2', Param1, Param2, Param3) ... если несколько тсб на окне, то для каждого делаем такие манипуляции

gfilatov2002: SergKis пишет: Может будет полезно, a c :bUserKeys осталось, как раньше Благодарю за Ваше предложение и примеры использования этого расширения! Очень интересное дополнение, которое будет доступно, если в коде библиотеки будет определена константа // #define __EXT_USERKEYS__

SergKis: gfilatov2002 пишет будет доступно, если в коде библиотеки будет определена константа // #define __EXT_USERKEYS__ А смысл пересобирать либу ? Изменения минимальны, старые алгоритмы не затронуты. Я забыл, когда последний раз пересобирал либу, пользуюсь (для примеров и проб) родной сборкой. Думается так многие делают.

gfilatov2002: SergKis пишет: Изменения минимальны, старые алгоритмы не затронуты. Все правильно, но, вероятно, потребуется определить #ifndef __XHARBOUR__ #define __EXT_USERKEYS__ #endif поскольку, например, функция hb_HGetDef() недоступна в xHarbour

SergKis: gfilatov2002 Пример для Harbour (на моей lib): и надо подправить (ошибочка) [pre2] METHOD UserKeys( nKey, bKey, lCtrl, lShift ) CLASS TSBrowse ... If ::lUserKeys // есть уст. блоки кода uVal := hb_HGetDef( ::aUserKeys, cKey, NIL ) If HB_ISBLOCK(uVal) cKey := Eval( uVal, Self, nKey, cKey, bKey, lCtrl, lShift ) EndIf EndIf [/pre2]

SergKis: PS Забыл в примере вывести в StatusBar сообщение о наличии меню на правую кнопку мыши (на тсб)

SergKis: PS в моей lib не работает (надо исп. вариант без DEFINE ...) DEFINE SPLITBOX HANDLE hSplit поэтому в примере StatusBar закрыт (на родной MiniGui.lib должно быть Ok!)

gfilatov2002: SergKis пишет: Пример для Harbour Благодарю за наглядный пример! SergKis пишет: Забыл в примере вывести в StatusBar сообщение о наличии меню на правую кнопку мыши Поправил - пример работает нормально

Петр: Конечно - это полезное дополнение. Только мне кажется, что UserKeys не совсем подходящее название метода и того, что этот метод делает. Не помешало бы и добавить что-то вроде SetUserKeys/GetUserKeys

SergKis: Петр пишет Не помешало бы и добавить что-то вроде SetUserKeys/GetUserKeys Тогда + DoUserKeys (выполнение), т.е. еще несколько доп. методов. Но в МиниГуи уклон к функциям с параметрами и пляской от них, потому пошел таким путем ("что бы не выделяться" (с))

Петр: SergKis пишет: Но в МиниГуи уклон к функциям с параметрами и пляской от них, потому пошел таким путем ("что бы не выделяться" (с)) Понятно, но название неподходящее: bUserKeys/UserKeys - клавиша/ключ, дезориентировать будет.

SergKis: Петр пишет но название неподходящее: bUserKeys/UserKeys - клавиша/ключ, дезориентировать будет. Т.к. действия bUserKeys с новым методом схожи, то не должно дезориентировать. Что там обработка пользовательских клавиш\ключей, что тут, от этого и брал название. Но если есть подходящее название - нет возражений.

SergKis: gfilatov2002 В примере надо заменить _HMG_ThisControlName на This.Name - это будет правильнее.

Петр: SergKis пишет: Что там обработка пользовательских клавиш\ключей, что тут Там обработка клавиш, тут - клавиши\ключа Причем у вас обработка события по ключу может быть и не связанной с нажатием какой-либо клавиши. Название должно отображать суть того, что происходит. А что здесь происходит я лично определиться не могу

SergKis: Петр пишет я лично определиться не могу Тогда, отдадим на откуп Григорию ( типа, наша хата с краю )

SergKis: Петр пишет Причем у вас обработка события по ключу может быть и не связанной с нажатием какой-либо клавиши. В связи с отсутствием на окне механизма работы через очередь (городить свой обработчик не хочется к каждому окну), к примеру WM_USER + 55 и через Post\SendMessage(hWnd, WM_USER + 55, nIndex\hControl, 0) и на окно вешать подобный механизм UserKeys, приходится вешать клавиши в :UserKeys VK_F21, VK_F22, ... и делать oBrw:PostMsg(...) + oBrw:Cargo с данными. Нажатия клавиш существуют всегда, причем клиент ТРЕБУЕТ дублирование кнопок клавишами КАТЕГОРИЧЕСКИ

SergKis: Петр Может смущает наличие многих параметров в блоках и функциях (это в основном для информации в MsgBox(...)), так в реальности, можно, практически, обойтись без них (oBrw1 Public\Private):[pre2] oBrw:bLDblClick := {|| oBrw1:PostMsg( WM_KEYDOWN, oBrw1:nFireKey, 0 ) } oBrw:UserKeys(VK_RETURN, {|| oBrw1:PostMsg( WM_KEYDOWN, oBrw1:nFireKey, 0 ) }) или oBrw:UserKeys(VK_RETURN, {|obr| obr:PostMsg( WM_KEYDOWN, obr:nFireKey, 0 ) }) :UserKeys('SetMode_1' , {|obr| Set_Mode(obr, 1)}) :UserKeys('SetMode_2' , {|obr| Set_Mode(obr, 2)}) или :UserKeys('SetMode_1' , {|| Set_Mode(oBrw1, 1)}) :UserKeys('SetMode_2' , {|| Set_Mode(oBrw1, 2)}) или :UserKeys('SetMode_1' , {|| Set_Mod1()}) // внутри функций :UserKeys('SetMode_2' , {|| Set_Mod2()}) // используем oBrw1 ... [/pre2]

SergKis: gfilatov2002 пишет функция hb_HGetDef() недоступна в xHarbour Может вместо #ifndef __XHARBOUR__ #define __EXT_USERKEYS__ #endif сделать [pre2] #ifndef __XHARBOUR__ FUNC hb_HGetDef( hHash, xKey, xDef ) Local nPos := HGetPos( hHash, xKey ) Return iif( nPos > 0, HGetValuePos( hHash, nPos ), xDef ) #endif [/pre2]

SergKis: PS вернее #ifdef __XHARBOUR__ ...

gfilatov2002: SergKis пишет: вернее #ifdef __XHARBOUR__ Заменил вызов HGetValuePos() на HGetValueAt() и добавил переопределение еще для двух функций #ifdef __XHARBOUR__ /* Hash item functions */ #xtranslate hb_Hash( [<x,...>] ) => Hash( <x> ) #xtranslate hb_HSet( [<x,...>] ) => HSet( <x> ) #endif теперь UserKeys работает и под xHarbour Благодарю за помощь

Петр: SergKis пишет: Может смущает наличие многих параметров в блоках и функциях Вот как раз это меня не смущает И даже наоборот, смущает то, что, например, в Events параметры не передаются в оконные события.

SergKis: gfilatov2002 Дополнительно, что бы было #ifdef __XHARBOUR__ #xtranslate hb_HHasKey( h, k ) => HHasKey( h, k ) #xtranslate hb_HDel( h, k ) => HDel( h, k )

Петр: SergKis пишет: Дополнительно, что бы было Включите hbcompat.ch из contrib/hbxhb

Andrey: Вопрос по индексам в Tsbrowse. К базе подключёны индексы. 3 индекс создан с ключом = "DESCEND(STR(KView))+UPPER(NAME)" Добавляю запись в базу. [pre2] nOrderTek := INDEXORD() DBSetOrder( 1 ) .... DBAppend() nTekRec := (oBrw:cAlias)->(RecNo()) lAppend := .T. DBSetOrder( nOrderTek ) .... IF lAppend // была добавлена запись oBrw:Refresh(.T.) oBrw:GoToRec(nTekRec) ENDIF Form_1.oBrw.Setfocus RETURN Nil [/pre2] После добавления курсор НЕ становиться на добавленной записи, а становиться на первую запись по индексу. Как нужно правильно сделать установку на добавленную запись ?

Dima: Andrey пишет: nOrderTek := INDEXORD() DBSetOrder( 1 ) .... DBAppend() nTekRec := (oBrw:cAlias)->(RecNo()) lAppend := .T. DBSetOrder( nOrderTek ) А так ? [pre2] nOrderTek := (oBrw:cAlias)->(INDEXORD()) (oBrw:cAlias)->(DBSetOrder( 1 )) .... (oBrw:cAlias)->(DBAppend()) nTekRec := (oBrw:cAlias)->(RecNo()) lAppend := .T. (oBrw:cAlias)->(DBSetOrder( nOrderTek )) [/pre2] PS Вместо INDEXORD() лучше юзать ordsetfocus() ежели это CDX

Andrey: Dima пишет: А так ? Равнозначно. Можно и так написать. С обычным порядком в индексе у меня всё работает. А если поставить другой индекс с обратным порядком в ключе = "DESCEND(STR(KView))+UPPER(NAME)" То запись перестаёт вставать на правильное место.

Dima: Была такая кака. Пришлось базу открывать 2 раза с разными алиас , добавление и смену ордера делаем во вспомогательной базе и после в основной (бровс по ней живет) прыгаем куда надо , не меняя ордера естественно. Такую "фигню" под консолью делать не нужно.....

Dima: Andrey пишет: Можно и так написать Я имел в виду OrdSetFocus по имени тега

SergKis: Anderey пишет С обычным порядком в индексе у меня всё работает. Dima пишет Пришлось базу открывать 2 раза с разными алиас , добавление ... По мне, это нормальная практика, т.е. просмотр[ы] по одной, а ввод, удаление, edit по вновь открываемой. А учитывая "тонкости" TsBrowse, возможно, лучший вариант. Повторное открытие, для модификаций еще с s87 практикую.

Andrey: MiniGUI Extended Edition 17.05 У меня сделано так: [pre2] oBrw:aColumns[nJ]:bPrevEdit := {|| nRecBuff := (oBrw:cAlias)->(RecNo()), ; MyFieldEdit( oBrw:aColumns[oBrw:nCell]:Cargo ) } oBrw:aColumns[nI]:bPostEdit := {|| oBrw:GoToRec(nRecBuff), oBrw:Refresh(.T.) } [/pre2] К базе подключёно 3 индекса. Последний индекс типа: STR(KView)+STR(KFILI)+UPPER(FIO) Всё работает отлично, но после редактирования поля входящее в индекс (например FIO) - курсор прыгает на 6 позиции вниз. Правка столбцов полей KView и KFILI - происходит нормально. Почему ? В FUNCTION MyFieldEdit(aCargo) нет переходов по базе. Только редактирование поля в зависимости от условий: [pre2] IF lEditField // сетевой захват записи IF (oBrw:cAlias)->(RLock()) FieldPut( FIELDNUM( cPoleField ), cPoleEdit ) (oBrw:cAlias)->KOPERAT := M->nOperat DBCommit() DBUnlock() ENDIF ENDIF [/pre2]

Dima: Andrey пишет: Почему ? Покажи скрин до и после редактирования поля FIO

Andrey: Dima пишет: Покажи скрин до и после редактирования поля FIO Вот: Если редактировать последние записи в таблице, то курсор перескакивает НИЖЕ записей таблице и на экране становится дублирование записей... Совсем юзер пугается...

Dima: а если закоментить строку oBrw:aColumns[nI]:bPostEdit := {|| oBrw:GoToRec(nRecBuff), oBrw:Refresh(.T.) }

Dima: Andrey пишет: В FUNCTION MyFieldEdit(aCargo) нет переходов по базе. Только редактирование поля в зависимости от условий: IF lEditField // сетевой захват записи IF (oBrw:cAlias)->(RLock()) FieldPut( FIELDNUM( cPoleField ), cPoleEdit ) (oBrw:cAlias)->KOPERAT := M->nOperat DBCommit() DBUnlock() ENDIF ENDIF Прикольно Только RLOCK смотрит в правильный ALIAS , все что ниже х.... знает куда

Andrey: Dima пишет: а если закоментить строку Сделал так: oBrw:aColumns[nI]:bPostEdit := {|| /*oBrw:GoToRec(nRecBuff)*/, oBrw:Refresh(.T.) } Стало отлично ! Не перескакивает. НО ТЕПЕРЬ другой справочник не работает. Если к базе подключаю только 2 индекса и 2-ой индекс типа: UPPER(NAME), то при редактировании поля NAME и изменению его на другое значение (было: "ООО СтройСервис", стало "1ООО СтройСервис") то КУРСОР остаётся на текущем месте, а отредактированная запись улетает вверх. Как теперь быть ?

Andrey: Dima пишет: Только RLOCK смотрит в правильный ALIAS , все что ниже х.... знает куда Из терминалки перенёс. Как правильно сделать ?

Vlad04: В примере Tsb_lastrow динамически можно изменить высоту заголовка таблицы.А можно подобное делать с высотой строк таблицы ?

Andrey: Vlad04 пишет: А можно подобное делать с высотой строк таблицы ? Можно так (или по другому): oBrw:nHeightCell += INT(nNumberLines * nFontSize/2) // расчёт высоты строки

Dima: Vlad04 А ты уже задавал этот вопрос в 2005 году и Has ответил http://clipper.borda.ru/?1-1-0-00000399-000-10001-0-1418918839

Veeha: оффтоп Andrey пишет: Совсем юзер пугается... Изучай основы построения интерфейсов ...

Andrey: Veeha пишет: Изучай основы построения интерфейсов ... Это терминалка была, я сделал по другому на МиниГу - юзера потребовали вернуть обратно ! Спасибо за картинку !

Veeha: Andrey пишет: Это терминалка была, я сделал по другому на МиниГу - юзера потребовали вернуть обратно ! Если что - я про цвета ... Чурки твои пользователи ( а может и ты) ! Тут, на форуме, есть ещё тебе подобные - в том числе и админ Dima

Andrey: Veeha пишет: Чурки твои пользователи ( а может и ты) ! В г.Николаеве пользователи программы есть. Да и по России немало, где работают (я точно знаю) диспетчера-украинцы. Выводы у тебя просто хамские. Всех подряд как правило критикуют те - у кого нет нормальных и тиражируемых программ, только и могут на г... исходить.

Dima: Andrey пишет: Выводы у тебя просто хамские Veeha ушел копать картошку на луну

Vlad04: Dima Vlad04 А ты уже задавал этот вопрос в 2005 году и Has ответил В 2005 году не помню, не нашел , вряд ли. В 2005 я только с Харбор познакомился. А MiniGui - позже, тема начата в 2013.

Haz: Dima пишет: Veeha ушел копать картошку на луну А чего так далеко то ??? Мне мастер класс по основам построения интерфейсов пригодился бы

Haz: Haz пишет: В 2005 году не помню, не нашел , вряд ли. В 2005 я только с Харбор познакомился. А MiniGui - позже, тема начата в 2013. Ошибся Дима годом, бывает Но ссылку дал правильную. По которой написано что "почти все что в классе определено как DATA может быть переопределено во время исполнения бровса" nHeightCell определен как DATA и отвечает за высоту строк при ПРОРИСОВКЕ бровса , а раз так то в любой момент можно изменить значение и перерисовать бровс Добавьте на форму бровса код ниже и увидете магию DEFINE TIMER Timer_1 OF FORM_1 INTERVAL 1000 ACTION {|| oBrw:nHeightCell++, oBrw:Refresh(TRUE) } // Каждую секунду на 1 пиксель увеличиваем строки

Dima: Haz пишет: Ошибся Дима годом Точно Зрение подвело...

VeeIha: Haz пишет: Мне мастер класс по основам построения интерфейсов пригодился бы Я бы постеснялся на твоём месте. А какие проблемы, если не прикалываешься? Ты же, вроде, не "чайник"

Haz: VeeIha пишет: А какие проблемы, если не прикалываешься? Проблема одна - на разработку интерфейсов уходит половина времени кодинга, Про цветовую палитру я не говорю , это как "на вкус и цвет все фломастеры разные", а вот впихнуть невпихуемое в окно программы - вечная дилема. PS. Продолжу. Критиковать оно всегда легче, предложить вариант - всегда лень. Сама разработка интерфейса - занятие очень неблагодарное, у каждого пользователя свои предпочтения. Цветовая гамма это маленькая часть. И эта гамма может подчеркивать свой фирменный стиль. Мне к примеру не нравится сочетание зелёного и фиолетового, это визитка мегафона. Но я везде узнаю эту визитку именно по этому сочетанию. Ты накинулся на Андрея с критикой, а слабо дать ему вариант который на твой вкус красивее? Правда в том что мы все не идеальны. Андрюха в своей текучке зачастую просто затыкает дыру в коде используя те же подсказки, причём не вникая в суть глубоко т.к. просто надо удовлетворить клиента срочно. Мне такой подход тоже не нравится, и я тоже покусывал Андрея незлобными нападками, но он не обижался, а у меня не было цели обидеть. А ведь многие интересные темы на форуме выросли именно из риторических вопросов, на которые просто ктото попытался ответить. Так что велкам с луны, и включайся в нормальное обсуждение. А теперь вернёмся к проблемам, мне очень бы помогли примеры интерфейсов других коллег. Изобретение велосипеда в тысячный раз просто сжирает много времени и опыт коллег не был бы лишний

gfilatov2002: Haz пишет: мне очень бы помогли примеры интерфейсов других коллег Мне прислали скриншоты программ, написанных на минигуи с использованием tsbrowse, и размещенных на сайте www.hardoffice.rs

Haz: gfilatov2002 пишет: Мне прислали скриншоты программ, написанных на минигуи Григорий спасибо. Начало положено. Могу свои шоты выложить. Может в отдельную ветку или вообще на сайт hmg? По этим скринам видно боковое меню. Пробовал делать похожее, при смене пункта этого меню на той части формы что справа удалял все контролы и рисовал новые для нового пункта. Работает, но не понравился подход. Пробовал не удаляя прятать старые и это пошло лучше. Боковую ленту делал тоже на tsbrowse Дизайн в принципе понятен. Пусть поживет в коллекции.

Andrey: Что то не понимаю почему СУПЕРХИДЕР не доходит до конца таблицы ? Пишу так: [pre2] // создать СУПЕРХИДЕР таблицы Add Super Header To oBrwV From Column 1 To Column 10 ; Color CLR_WHITE, { nBackForm, nHeadColor1 } ; Title cTableName [/pre2] Вот что получается:

SergKis: Andrey Возможно это связано с несовпадением кол. колонок в тсб и суперхидера. У тебя была хитрая колонка с раскраской. Может дело в ней ?

Andrey: SergKis пишет: Может дело в ней ? Нет. Такая фигня получается если делаешь 2 строки в одной колонке...

Andrey: Почему происходит перенос значения из справочника (подчинённой таблицы) на основную таблицу при выборе ? Т.е. имеется Основной Tsbrowse, открываю второй Tsbrowse и значение второго переносится на Основной Tsbrowse. Вот 1-ый экран: Нажимаю ENTER, выходит 2-ой Tsbrowse - новый и ПЕРВОЕ значение перекидывается на Основной Tsbrowse Вот 2-ой экран: После отказа от выбора, не делаю oBrw:Refresh( .T. ) и остаётся МУСОР с предыдущего справочника ! Т.е. тогда нужно всегда делать oBrw:Refresh( .T. ) даже если юзер ничего не выбрал... Ерунда получается. А на ХР вообще чудеса происходят... Колонка целиком чиститься: Как избавиться от этого ? Исходники посмотрите пожалуйста !

Andrey: Григорий написал мне что: [pre2]Вы используете команду SET RELATION TO ПО ПЕРВОМУ ИНДЕКСУ базы справочника, а когда вызываете окно выбора из справочника, то переключаете индекс этой базы на 2 для сортировки по имени. Естественно, что связанное поле в основном бровсе сразу отображает первую строку из базы справочника, ведь индекс теперь сбит. [/pre2] Теперь стало понятно такое поведение. На терминалке такого не было ! Попробовал очищать SET RELATION TO на Основной базе ПЕРЕД вызовом справочника - не помогает... Сделал вызов справочника по 1-ому индексу - та же беда ! 1-я запись справочника перепрыгивает в текущую запись основной таблицы !!! Как исправить этот глюк ?

Andrey: Ещё заметил. Если есть 1-ый столбец по индексу и запись в основной таблице стоит на 2-ой записи - №№=2 [pre2] ADD COLUMN TO oBrwV HEADER "№№" ; DATA {|| OrdKeyNo() } ;[/pre2] то после показа справочника 2-ка превращается в 1, т.е. №№=1 и в таблице 2 значения с 1 ! Вот экран: Наверное каким то волшебным образом перерисовывается Основная таблица ?

Dima: Andrey пишет: Теперь стало понятно такое поведение. На терминалке такого не было ! Да не было на терминалке. Открывай нужные базы несколько раз. Например справочник у тебя завязан на Relation , и есть момент когда ты его вызываешь в бровсе , так вот в этом месте юзай другой алиас этого же справочника.

Andrey: Dima пишет: Открывай нужные базы несколько раз. У меня при старте задачи открываются ВСЕ базы. Повторное открытие не использую. Наверное буду убирать SET RELATION. Из-за него наверное ошибка. Хотя может и не в нём... Благо в Tsbrowse можно легко подсунуть функцию в столбец. Это будет проще. Спасибо всем за помощь !

Dima: Andrey пишет: Повторное открытие не использую. А придется. Я тоже не использовал но пришлось. Дело не в SET RELATION , уверен , ты налезешь на те же грабли и без него. Допустим у тебя есть справочник GROUP , данные из него и показывай в основном бровсе а вот если хочешь показать сам справочник , поверх основной таблицы , то открой его повторно , скажем с алиас TMP_GROUP и ходи по нему в справочнике да и основная таблица не пострадает Решать тебе , просто я нарывался на такие же косяки и мне подсказали как надо сделать. А подход у меня был такой же как у тебя в терминалке.

Andrey: Понял ! Спасибо ! Чтобы добиться работы без открытия дубля базы, переделал свой тестовый пример, сделал без SET RELATION. Теперь уже работает, но тоже как то НЕПОНЯТНО !!! Становиться всё интересней.... Запись из Основной таблицы перескакивает в Справочник, т.е. справочник открывается не с 1-ой записи базы по индексу, а по условию записи из Основной базы. Вот скрин до выбора справочника: Вот скрин при показе справочника: Если посмотреть, то с другой стороны - классно получилось, юзеру даётся список с той улицы на которой стоит Основная база. Так и оставлю ! Это лучший вариант ! Тем более навигация по справочнику работает, буквы и цифры ставят фильтр. Больше юзеру и не надо !

Dima: Andrey пишет: буквы и цифры ставят фильтр Тут тоже можешь поймать сам знаешь что. Попробуй с дублем базы и "косяки" уйдут Andrey пишет: Больше юзеру и не надо ! Бедные юзера....

Andrey: Dima пишет: Попробуй с дублем базы и "косяки" уйдут Это не путь Рыцаря-джедая ... Убрал свой косяк, открывается справочник теперь нормально ! Потестил, всё отлично !

Dima: Andrey пишет: Убрал свой косяк, открывается справочник теперь нормально ! Ждем новый

Andrey: SergKis пишет: Ты хочешь управлять METHOD KeyChar(...) на самом деле и тогда, вероятно, надо делать, добавив переменную в класс DATA bKeyChar METHOD KeyChar( nKey, nFlags ) CLASS TSBrowse ... Default ::nUserKey := nKey IF ::bKeyChar != Nil .and. !Empty( EVal( ::bKeyChar, Key, Self, nFlag ) RETURN 0 ENDIF If ::nUserKey == 255 .or. ::lNoKeyChar // from KeyDown() method Return 0 EndIf Да, так будет удобней. Блокировать столбцы на цифры/буквы обязательно надо ! Желательно отдельно - вот так: [pre2] oBrw:aColumns[nI]:lNoKeyChar := .F.[/pre2] Тогда всем будет понятно. А то вот при нажатии цифр на колонке флагов - вот что получается:

SergKis: Andrey пишет oBrw:aColumns[nI]:lNoKeyChar := .F. задавать надо будет так oBrw:bKeyChar := {|ky,ob| ky := ob, ! hb_ntos(ob:nCell) $ '5,7,9' } т.е. для колонок 5,7,9 делаем edit от букв\цифр, для других нет. .T. - не делаем edit .F. - вкл. edit для колонки или oBrw:bKeyChar := {|ky,ob| ky := ob:aColumns[ ob:nCell ]:cName, ky $ 'NAME1,NAME2,NAME3' } для этих колонок вкл. edit, для др. нет

Andrey: Скачал со страницы сайта только что новую версию. Для своего примера установил: [pre2] oBrw1:bKeyChar := {|ky,ob| ky := ob, ! hb_ntos(ob:nCell) $ '6,7,8' } [/pre2] Осталось без изменений. Редактирование есть. Вдобавок появилась ошибка на 2,3,4 колонке вылет из программы: Error BASE/1004 Метод не экспортирован: NCELL Called from NCELL(0) Called from (b)MYCREATETABLE(428) Called from TCONTROL:KEYCHAR(576) Called from TSBROWSE:KEYCHAR(6420) Called from TSBROWSE:HANDLEEVENT(7436) Called from EVENTS(81)

SergKis: Andrey пишет Вдобавок появилась ошибка на 2,3,4 колонке вылет из программы: С чего решил, что это есть ? Мы скорее фантазировали. Потому как, кто мешает написать oBrw1:bUserKeys := {|ky,flg,ob| ky := flg := ob, ! hb_ntos(ob:nCell) $ '6,7,8' } :bKeyChar, если ты решил заменить родной method KeyChar своим, что вряд ли надо. надо все решать в :bUserKeys

Andrey: SergKis пишет: Мы скорее фантазировали. Потому как, кто мешает написать oBrw1:bUserKeys := {|ky,flg,ob| ky := flg := ob, ! hb_ntos(ob:nCell) $ '6,7,8' } Да я не понял, что мы фантазировали... Поставил, вообще непонятки. Смотри результат у себя...

Andrey: Всем привет ! Как сменить редактирование колонки типа ДАТА на обычную цифровую ? А то юзерам не нравиться. [pre2] ADD COLUMN TO oBrw1 HEADER "Date" ; .............. DATA FIELDWBLOCK("FDATE", Select(cAlias)) ; PICTURE "99.99.9999" ; NAME FDATE ; EDITABLE[/pre2] Я понимаю, что можно самому написать функцию ввода в окошке. А стандартное - ввод цифр есть или нет ?

Haz: Andrey пишет: А стандартное - ввод цифр есть или нет ? [pre2] oBrw1:GetColumn("FDATE"):lPickerMode := FALSE [/pre2] а можно и Я понимаю, что можно самому написать функцию ввода в окошке.

Andrey: Haz пишет: oBrw1:GetColumn("FDATE"):lPickerMode := FALSE Ошибка при выполнении: Error BASE/1005 Message not found: TSCOLUMN:_LPICKERMODE Called from __ERRRT_SBASE(0) Called from TSCOLUMN:ERROR(0) Called from (b)HBOBJECT(0) Called from TSCOLUMN:MSGNOTFOUND(0) Called from TSCOLUMN:_LPICKERMODE(0) Called from MYCREATETABLE(331) Called from FORMTABLE(106)

Haz: Andrey пишет: Ошибка при выполнении: Да не углядел. Эта переменная не колонки а самого бровса oBrw:lPickermode Через пару минут дойду до компа гляну подробнее

Andrey: Haz пишет: Да не углядел. Эта переменная не колонки а самого бровса oBrw:lPickermode Через пару минут дойду до компа гляну подробнее Вот так работает - oBrw1:lPickerMode := .F. Спасибо !

Andrey: Рабочий пример работы c Tsbrowse выложен Григорием - http://hmgextended.com/files/MISC/Tsb_composite.zip Работает без ошибок с версии МиниГуи 17.07 и исправленной библиотеки tsbrowse.lib (в модуле h_tbrowse.prg)

Alex_Cher: Andrey пишет: Работает без ошибок с версии МиниГуи 17.07 и исправленной библиотеки tsbrowse.lib (в модуле h_tbrowse.prg) Application: C:\MiniGUI\SAMPLES\MY_BASIC\Tsbrowse_7\Tsb_composite.exe Date: 24.08.17 Time: 09:00:26 Time from start: 0 days 0 hours 0 mins 27 secs Error BASE/1004 Метод не экспортирован: LAPPEND Called from LAPPEND(0) Called from TSBROWSE:EDITEXIT(4134) Called from (b)TSBROWSE_EDIT(4003) Called from TCOMBOBOX:LOSTFOCUS(212) Called from TCOMBOBOX:COMMAND(964) Called from TCONTROL:HANDLEEVENT(871) Called from TCOMBOBOX:HANDLEEVENT(155) Called from EVENTS(1675) Called from DOMESSAGELOOP(0) Called from _ACTIVATEWINDOW(1449) Called from DOMETHOD(4729) Called from FORMTABLE(161) Called from (b)MAIN(45) Called from _PROCESSINITPROCEDURE(1613) Called from _ACTIVATEWINDOW(1437) Called from MAIN(58) Версии МиниГуи 17.07, на счет библиотеки tsbrowse.lib ничего сказать не могу.

gfilatov2002: Alex_Cher пишет: Версии МиниГуи 17.07 Эта ошибка будет исправлена в августовской сборке Минигуи

Andrey: У себя в Tsbrowse наверху окна вывожу - язык раскладки клавиатуры (RUS/LAT) При смене языка раскладки остаётся старый язык, пока не нажмешь любую клавишу, тогда язык меняется на правильный. Как сделать чтобы при смене раскладки языка - показ языка отрабатывал сразу ?

Dima: Andrey Ни кто не даст ответа не видя как ты выводишь эту самую раскладку.

Andrey: Понял. В Tsbrowse назначаю свою обработку: oBrw:bUserKeys := { |a,b,c| MyKeyEdit(a,b,c) } Функция обработки: [pre2]STATIC FUNCTION MyKeyEdit( nKey, nFlag, oBrw ) LOCAL xRet := .T. ....... IF !Alltrim(cStaticSearch) == Form_0.Text_Seek.Value cStaticSearch := Form_0.Text_Seek.Value ENDIF DO CASE CASE nKey == VK_ESCAPE .... CASE nKey == VK_INSERT // [Ins] Добавить запись ... CASE nKey == VK_DELETE // [Del] Удалить запись .... CASE nKey == VK_BACK // Backspace IF LEN(Form_0.Text_Seek.Value) > 0 cStaticSearch := LEFT(cStaticSearch,LEN(cStaticSearch)-1) Form_0.Text_Seek.Value := cStaticSearch RefreshBrowse() ENDIF CASE nKey > 47 .AND. nKey < 254 cStaticSearch := cStaticSearch + KeyToChar(nKey) Form_0.Text_Seek.Value := cStaticSearch // показ вверху набранного ФИЛЬТРА по базе RefreshBrowse() xRet := .F. Form_0.Label_KB.Value := '('+KB_LANG()+')' CASE nKey == 16 .OR. nKey == 17 // Shift+Alt Shift+Ctrl xRet := .F. ENDCASE Form_0.Label_KB.Value := '('+KB_LANG()+')' // вывод раскладки клавиатуры Form_0.oBrw.SetFocus RETURN xRet [/pre2] Не всегда показывает смену языка клавиатуры !!! Как сделать, чтобы смена языка отображалась правильно ?

Dima: Варианты 1. STATIC FUNCTION MyKeyEdit( nKey, nFlag, oBrw ) LOCAL xRet := .T. Form_0.Label_KB.Value := '('+KB_LANG()+')' // вывод раскладки клавиатуры 2. Повесить показ на таймер 3. Повесить показ в потоке

Andrey: Dima пишет: Варианты 1. Этот не сработал.... Такая же фигня, меняешь язык - остаётся старый, пока не нажмёшь любую клавишу... 2 - не хочется загружать Tsbrowse сторонними процессами, уменьшать быстродействие 3-вообще экзотика, нафига в простом Tsbrowse отдельный поток.

Dima: Andrey Стандартного вывода от OS не хватает ?

Andrey: Dima пишет: Стандартного вывода от OS не хватает ? Да юзера пристали... Вот и сделал им... А не работает.

gfilatov2002: Andrey пишет: не хочется загружать Tsbrowse сторонними процессами, Да, это возможно сделать средствами самого TSBrowse. Надо добавить в функцию CreateBrw() такой обработчик: // Вывод подсказки с использованием внутреннего цикла TBrowse oBrw:bEvents := { |a,b| MyEventBrowse(a,b) } и перенести вывод подсказки из функции MyKeyEdit() в функцию ниже: [pre2]//////////////////////////////////////////////////////////// STATIC FUNCTION MyEventBrowse(oBrw, nMsg) oBrw:=nil IF _IsControlDefined( "Label_KB", "Form_0" ) .and. !(nMsg==WM_PAINT) Form_0.Label_KB.Value := '('+KB_LANG()+')' ENDIF RETURN 0 [/pre2]

Dima: gfilatov2002 пишет: // Вывод подсказки с использованием внутреннего цикла TBrowse oBrw:bEvents := { |a,b| MyEventBrowse(a,b) } Мерцать надпись не будет ?

Andrey: gfilatov2002 пишет: Да, это возможно сделать средствами самого TSBrowse. Заработало !!! И не мерцает... А как насчёт других вопросов (1,2 и 3) ?

Петр: Andrey пишет: А как насчёт других вопросов (1,2 и 3) А где эти вопросы прозвучали? Были 3 варианта от Dima и ваше резюме Andrey пишет: нафига

Dima: Петр пишет: А где эти вопросы прозвучали? Думаю только в его голове

Andrey: Dima пишет: Думаю только в его голове Я проект Tsb_config2 Григорию на прошлой неделе отослал...

Andrey: Сам проект - https://cloud.mail.ru/public/H4Do/1tDRrPPff Вопросы: 1) Модуль util_dbase.prg функция DbfCreateRecno() Нет надписи по команде - WAIT WINDOW "Подождите, создаю тестовую базу...." NOWAIT Что нужно сделать, чтобы надпись появилась ? 2) Модуль Form_operat.prg функция DimOperat() Обработка колонки срабатывает ТОЛЬКО после первого ввода. [pre2] oBrw:aColumns[nVal]:bPrevEdit := ..... oBrw:aColumns[nVal]:bEditing := ..... oBrw:aColumns[nVal]:bEditEnd := .....[/pre2] Как сделать, чтобы при первом вводе был показ подсказки ? 3) Модуль Tsb_Config.prg - нет отработки команды oBrw:nAt := 5 Например: [pre2] FUNCTION RecnoInsert() .......... oBrw:GoTop() // первая запись базы oBrw:nAt := 5[/pre2] или при ПЕРВОМ показе бровса [pre2] строка 364 - oBrw:nAt := 5 // передвинуть МАРКЕР на 5 строку [/pre2] Как исправить ?

gfilatov2002: Andrey пишет: как насчёт других вопросов (1,2 и 3) ? Вопросы. 1) Нет надписи по команде - WAIT WINDOW "Подождите, создаю тестовую базу...." NOWAIT Что нужно сделать, чтобы надпись появилась ? Проверял под Win7 - нет такой проблемы... 2) Как сделать, чтобы при первом вводе был показ подсказки ? Не знаю 3) нет отработки команды oBrw:nAt := 5 Попробуйте заменить на oBrw:GoPos( 5 )

Dima: Andrey пишет: Нет надписи по команде - WAIT WINDOW "Подождите, создаю тестовую базу...." NOWAIT Если сделаешь микро-пример я проверю у себя. Впрочем где то это я уже видел в твоих примерах "Подождите, создаю тестовую базу...." и у меня работало. PS Win-7

Петр: Dima пишет: Впрочем где то это я уже видел в твоих примерах "Подождите, создаю тестовую базу...." и у меня работало. Ну так в том проекте, что он выложил (пост 5490) есть такая штука и она работает - надпись есть (запускал на Win7 и WinXP). Andrey пишет: Модуль Tsb_Config.prg - нет отработки команды oBrw:nAt := 5 nAt обьявлено как DATA (VAR), что там может отрабатывать?

Andrey: Dima пишет: Если сделаешь микро-пример я проверю у себя. Возьми готовый проект, ссылка выше. На микро-примерах, как правило ВСЁ работает !gfilatov2002 пишет: gfilatov2002 пишет: Проверял под Win7 - нет такой проблемы... Значить это у меня под Win8.1 нет надписи ! Тогда можно не заморачиваться... Петр пишет: nAt обьявлено как DATA (VAR), что там может отрабатывать? На других примерах это срабатывает. gfilatov2002 пишет: Попробуйте заменить на oBrw:GoPos( 5 ) НЕ ТО ! Мне нужна 1-я запись и положение курсора/маркера на 5+2 столбце ("Событие") ? Нашёл как исправить: [pre2] ON INIT { || IniGetPosWindow(), IniGetTbrowse(oBrw,aStatClr2Usl), oBrw:GoPos( 1,7 ) } ; [/pre2]

Andrey: 1) Нет надписи по команде - WAIT WINDOW "Подождите, создаю тестовую базу...." NOWAIT На ХР надпись есть. Видать Win8.1 не срабатывает... На ХР появляется квадрат Малевича - синего цвета. Почему ? Вроде осталась последняя "непонятка" в примере и всё остальное работает ! Просьба ко всем - протестировать последнюю версию https://cloud.mail.ru/public/DFuN/tzKsbUF8R

Dima: Andrey пишет: 1) Нет надписи по команде - WAIT WINDOW "Подождите, создаю тестовую базу...." NOWAIT На ХР надпись есть. Видать Win8.1 не срабатывает... Попробуй с цветами поиграть , может появится...

Andrey: Dima пишет: Попробуй с цветами поиграть , может появится... А как пробовать то ? Там просто, без параметров - WAIT WINDOW "Подождите, создаю тестовую базу...." NOWAIT На ХР, Win7, Win10 надпись есть !

Dima: Andrey пишет: А как пробовать то ? Ты прав. Я бы забил на это дело и сделал своё WaitWindow

Andrey: Andrey пишет: Вроде осталась последняя "непонятка" в примере и всё остальное работает ! Прямоугольник присутствует на WinXP и Win7. На Win8.1 и Win10 - нет. Как исправить ?

Dima: Да , странно , косяков вроде нет в MyHelpLabel() а голубой квадрат Малевича , есть :) Цвет квадрата явно перекочевал из MyToolBar() PS Win-7

Andrey: Dima пишет: Цвет квадрата явно перекочевал из MyToolBar() Нет, не оттуда. Этот квадрат копия окна подсказки. Наверное как-то перерисовывается в Tsbrowse. Я придумал как его убрать. При создании окна делаем NOSHOW: [pre2] DEFINE WINDOW Form_Help ; .... NOSHOW ;[/pre2] а потом в MyPrevEditDim(): [pre2] SetProperty(cForm, "Row" , nY ) SetProperty(cForm, "Col" , nX ) SHOW WINDOW &cForm [/pre2] И всё - заработало !!!

Andrey: Всем привет ! Можно ли при наведении мышкой на определённый столбец менять вид курсора (типа пальца) ?

Dima: Andrey Можно попробовать через Brw:cToolTip это реализовать. C:\MiniGUI\SAMPLES\Advanced\Tsb_calendar\demo2.prg В блоке кода ловишь нужную колонку и меняешь форму курсора

Andrey: Dima , СПАСИБО за наводку ! Попробую...

Andrey: Посмотрел пример C:\MiniGUI\SAMPLES\Advanced\Tsb_calendar\demo2.prg Так и не понял как к себе применить. Есть такая таблица: Как мне сделать следующие подсказки (oBrw:cToolTip) : 1) В колонке 2 - "Открыть + имя_файла (в колонке)", поле бд FILE1 ? 2) В колонке 5 поставить ТОЛЬКО на красную стрелку подсказку "Конвертировать", поле бд LCONV ? 3) В колонке 6 - "Открыть + имя_файла (в колонке)", поле бд FILE2 - ТОЛЬКО для тех колонок, где есть имена файлов ? Смог сделать только так: [pre2] cToolTip := "Открыть " oBrw1:cToolTip := {|oBr,nCol,nRow| oBr:=nil,IIF( nCol==2, cToolTip + HB_NtoS(nRow),; IIF( nCol==6, cToolTip + HB_NtoS(nRow), "" ) ) }[/pre2]

Andrey: Как не изгалялся, так и не смог сделать/получить имена файлов и условие по красной стрелке. Единственно получилось, так это чтобы cToolTip не высвечивался на условиях if( nRow > 0 .AND. nRow < oBr:nLen+1 : [pre2] oBrw1:cToolTip := {|oBr,nCol,nRow| if( nRow > 0 .AND. nRow < oBr:nLen+1, IIF( nCol==2, "Открыть" ,; IIF( nCol==6, "Открыть" , IIF(nCol==5,"Конвертировать","" ) ) ),; ) }[/pre2]

SergKis: Andrey пишет Как не изгалялся,... [pre2] примерно такая схема (как надо сделаешь сам) ... DEFINE TBROWSE oBrw AT ... ... __objAddData( oBrw, 'aRowPosRec' ) ... // последними строками перед end tbrowse If empty(oBrw:aRowPosRec) oBrw:aRowPosRec := array(oBrw:nRowCount()) AFill(oBrw:aRowPosRec, 0) EndIf oBrw:bOnDrawLine := {|obr | On_DrawLine(obr) } oBrw:cToolTip := {|obr,col,row| On_ToolTip(obr,col,row) } END TBROWSE ... STATIC FUNC On_DrawLine( oBr ) LOCAL nRow := If( oBr:lDrawHeaders, Max( 1, oBr:nRowPos ), oBr:nRowPos ) If oBr:lPainted oBr:aRowPosRec[ nRow ] := (oBr:cAlias)->( RecNo() ) EndIf RETURN Nil STATIC FUNC On_ToolTip( oBr, nCol, nRow ) LOCAL cTxt := '' LOCAL nRec := 0 LOCAL cAls := oBr:cAlias LOCAL nOld := (cAls)->( RecNo() ) LOCAL cFil, nImg, cOut If nRow > 0 .and. nRow <= Len( oBr:aRowPosRec ) nRec := oBr:aRowPosRec[ nRow ] EndIf If nRec > 0 .and. ( nCol == 2 .or. nCol == 5 .or. nCol == 6 ) (cAls)->( dbGoto( nRec ) ) cFil := AllTrim(Eval(oBr:GetColumn(2):bData)) cOut := AllTrim(Eval(oBr:GetColumn(6):bData)) nImg := Eval(oBr:GetColumn(5):bData) // номер image: If empty(cOut) .or. nImg == 1 // 1 - '+', 2 - '-->' // image стрелка cTxt := 'Конвертировать ' + cFil Else // image плюсик cTxt := 'Открыть ' cTxt += iif( nCol == 6, cOut, cFil ) EndIf (cAls)->( dbGoto( nOld ) ) EndIf RETURN cTxt // Переменная DATA aRowPosRec, ее инициализация и содержимое On_DrawLine у меня // встроено в класс TsBrowse, без назначения :bDrawLine (для упрощения работы // с cToolTip) [/pre2]

Andrey: SergKis пишет: If empty(cOut) .or. nImg == 1 // 1 - '+', 2 - '-->' // image стрелка cTxt := 'Конвертировать ' + cFil Else // image плюсик cTxt := 'Открыть ' cTxt += iif( nCol == 6, cOut, cFil ) EndIf Для 2 и 6 колонки нужно писать "Открыть "+ имя файла / ALLTRIM(то что стоит соответственно в колонках) Для 5 колонки: для "+" ничего не писать, а для красной стрелке писать просто "Конвертировать"

SergKis: SergKis пишет STATIC FUNC On_DrawLine( oBr ) пропустил [pre2] STATIC FUNC On_DrawLine( oBr ) LOCAL nRow := If( oBr:lDrawHeaders, Max( 1, oBr:nRowPos ), oBr:nRowPos ) If oBr:lPainted If nRow == 1 AFill(oBr:aRowPosRec, 0) EndIf oBr:aRowPosRec[ nRow ] := (oBr:cAlias)->( RecNo() ) EndIf RETURN Nil [/pre2]

SergKis: Andrey пишет Для 2 и 6 колонки нужно писать "Открыть "+ имя файла / ALLTRIM(то что стоит соответственно в колонках) Для 5 колонки: для "+" ничего не писать, а для красной стрелке писать просто "Конвертировать" Это все сам, как надо, так делай примерно такая схема (как надо сделаешь сам)

Andrey: SergKis СПАСИБО БОЛЬШОЕ !

Andrey: Всем привет ! А можно ли запретить сдвиг таблицы вправо ? Допустим у меня есть 8 колонок в таблице, они прекрасно отображаются, но при движении стрелкой вправо - таблица двигается и показывается пустая колонка. Не хочу я чтобы эта пустая колонка отображалась у меня в таблице. Как это сделать ? Про параметр знаю : [pre2]oBrw:nAdjColumn := 6 // растянуть колонку до заполнения пустоты в бровсе справа [/pre2]

Dima: Andrey пишет: Про параметр знаю : Типа не юзаешь его ?

Andrey: Dima пишет: Типа не юзаешь его ? Не помогает ! Ширина таблицы на форме больше на 2 пиксела, чем сумма ширины всех колонок. Ставлю/не ставлю этот параметр - все равно присутствует пустая колонка. Как от неё избавиться не знаю.

Dima: Andrey Попробуй поиграть с nfreeze и lLockFreeze

Andrey: Dima пишет: Попробуй поиграть с nfreeze и lLockFreeze У меня уже стоит : [pre2] oBrw1:nFreeze := 1 // Заморозить столбец oBrw1:lLockFreeze := .T. // Избегать прорисовки курсора на замороженных столбцах[/pre2] А если убрать, то всё равно пустой столбец появляется, последним и вся таблица с пустым столбцом становиться.

Петр: Andrey пишет: У меня уже стоит : oBrw1:nFreeze := 1 Ну так все 8 или сколько там есть попробуйте заморозить.

Andrey: Петр пишет: Ну так все 8 или сколько там есть попробуйте заморозить. Сразу не понял что нужно заморозить ВСЕ столбцы. Сделал ! Получилось !!! Таблица вправо перестала сдвигаться. Спасибо БОЛЬШОЕ !

Andrey: Рано радовался. Таблица заморозилась и выбора в колонках теперь НЕТ !!! Значит заморозку использовать НЕЛЬЗЯ для этих целей...

Петр: Andrey пишет: выбора в колонках теперь НЕТ И при oBrw1:lLockFreeze := .F. ?

Dima: oBrw1:lLockFreeze := .F. PS Хэх одновременно написали

Andrey: Dima пишет: oBrw1:lLockFreeze := .F. Enter заработал, двойной клик мышки нет ! Ерунда опять получается... Писать отдельную функцию на срабатывание мышки - не есть хорошо, когда уже стандартная подключена по умолчанию. Дело в том что хочется обойтись стандартным кодом. У меня везде на нужных колонках стоит только: [pre2] // обработка до ввода oBrw1:aColumns[2]:bPrevEdit := {|| FieldEditFile(1), FALSE } oBrw1:aColumns[5]:bPrevEdit := {|| FieldImageEdit(), FALSE } oBrw1:aColumns[6]:bPrevEdit := {|| FieldEditFile(2), FALSE } [/pre2]

SergKis: SergKis пишет STATIC FUNC On_DrawLine( oBr ) ... Правильно так [pre2] STATIC FUNC On_DrawLine( oBr ) LOCAL nRow If oBr:lPainted nRow := oBr:nPaintRow If nRow == 1 AFill(oBr:aRowPosRec, 0) EndIf oBr:aRowPosRec[ nRow ] := (oBr:cAlias)->( RecNo() ) EndIf RETURN Nil [/pre2]

Vlad04: oBrw1:aColumns[2]:bPrevEdit := ... А можно сделать вызов общий для всех колонок, без указания № колонки ? Т.е. при выходе с редактирования из любой колонки вызывается одна функция или блок.

SergKis: Vlad04 1.[pre2] AEval(oBrw1:aColumns, {|oCol| oCol:bPrevEdit := {|val, brw | Prev( val, brw ) }, ; oCol:bPostEdit := {|val, brw, add| Post( val, brw, add ) } ) [/pre2] 2. или FOR ... применить

Vlad04: Ниже неправильно (выдает ошибку) AEval(Brw_3:aColumns, {|oCol| oCol:bPostEdit := {|val, brw, add| brw_3:Upstable() } ) Но как-то так хочется, т.е. для всех колонок Brw_3 при выходе с редактирования выполнять стабилизацию Бровса

SergKis: Vlad04 в блок кода передаются параметры val, brw, add, используйте их {|val, brw| brw:Upstable() }

SergKis: PS Vlad04 пишет Но как-то так хочется, т.е. для всех колонок Brw_3 при выходе с редактирования выполнять стабилизацию Бровса усложните блок кода, если надо после 2-ой колонки, то AEval(Brw_3:aColumns, {|oCol,nCol| oCol:bPostEdit := iif( nCol == 2, {|val, brw, add| brw:Upstable() }, NIL ) )

Vlad04: Скобка одна } пропущена, а так нормально AEval(Brw_3:aColumns, {|oCol| oCol:bPostEdit := {|val, brw | brw:Upstable() }} )

Andrey: Пробежаться для чтения по колонке для oBrw := SetArrayTo(...) можно так: [pre2]// Итог по колонке FUNCTION ItogoColumn( oBrw, cNameColumn ) LOCAL nCol := oBrw:nColumn(cNameColumn) LOCAL oCol, nItg := 0 aEval(oBrw:aArray, { |aVal,nElm| nItg += aVal[ nCol ] }) oCol:GetColumn(cNameColumn):cFooting := hb_ntos(nItg) oBrw:DrawFooters() // или // oCol := oBrw:GetColumn(nCol) // oCol:cFooting := hb_ntos(nItg) RETURN NIL[/pre2] или так [pre2] LOCAL nCol := oBrw:nColumn(cNameColumn) LOCAL nItg := 0 FOR nI := 1 TO LEN(oBrw:aArray) // или oBrw:nLen nItg += oBrw:aArray[ nI, nCol ] NEXT[/pre2] Пробежаться для записи по всей таблице для oBrw := SetArrayTo(...) можно так: ( Запись осуществляется средствами таблицы !) [pre2] // допустим колонка LMETKA nCol := oBrw:nColumn("LMETKA") FOR nI := 1 TO LEN(oBrw:aArray) // или oBrw:nLen lMark := oBrw:aArray[nI,nCol] oBrw:aArray[nI,nCol] := !lMark NEXT[/pre2] А как такую же операцию сделать для обычного TBROWSE, средствами таблицы ? И не средствами драйвера базы - (oBrw:cAlias)->LMETKA := !lMark

Haz: Andrey пишет: А как такую же операцию сделать для обычного TBROWSE, средствами таблицы ? Примерно так [pre2] FOR nI := 1 TO oBrw:nLen AEval( oBrw:aColumns, {|oCol| Eval(oCol:bData, !Eval(oCol:bData)) }) NEXT [/pre2]

Andrey: Haz пишет: Примерно так А позиционирование по строке таблицы - разве не нужно ? По массиву же стоит - oBrw:aArray[nI,nCol] = Или я просто не понял... Можешь написать без Eval() ...

Haz: Andrey пишет: А позиционирование по строке таблицы - разве не нужно нужно добавить oBrw:GoTop() а в цикле oBrw:Skip(1) и указать по какой колонке . в моем примере - по всем ( да и пример этот только показывает как использовать ::bData ) Без Eval() только через драйвер базы, да и Eval тоже неявно использует драйвер. Зачем такой изврат , если драйвер самое быстрое и надежное решение ?

Haz: Haz пишет: пример этот только показывает как использовать ::bData bData - это блок выборки / записи , такой же как и в Clipper , он же возвращается функцией FieldWBlock(). при предаче в блок парамера как Eval( ::bData, x ) -этот параметр присваивается в поле. При вызове без параметра - как Eval(::bdata ) возвращает значение поля. в классическом виде это примерно так {|x| if(pCount() == 0, FieldGet(nCol), FieldPut(nCol, x))}. Замечу - блок не заботится о блокировке записи. PS впрочем именно этот блок мы с тобой уже неоднократно обсуждали на форуме. PPS Оно тебе надо ? чем драйвер не угодил то if (oBrw:cAlias)->(Rlock()) (oBrw:cAlias)->&(oBrw:aColumns[oBrw:nCell]:cName) := 'новое значение' (oBrw:cAlias)->(dbUnlock()) end

Andrey: Haz пишет: Зачем такой изврат , если драйвер самое быстрое и надежное решение ? Это да, не спорю. Просто делаю тест для 2-х видов: движение по таблице и драйвером. Что бы было из чего посмотреть/выбирать. Haz пишет: а в цикле oBrw:Skip(1) и указать по какой колонке . в моем примере - по всем ( да и пример этот только показывает как использовать ::bData ) Это уже не пойдёт ! [pre2] // допустим колонка LMETKA bBlock := oBrw:GetColumn("LMETKA"):bData nCol := oBrw:nColumn("LMETKA") nRec := oBrw:nAt // номер текущей строки FOR nI := 1 TO oBrw:nLen ????? // позиционирование по строке таблицы - подойдёт ли oBrw:GoPos(nI,nCol) lMark := Eval(bBlock) IF (cAlias)->(RLock()) Eval(bBlock, !lMark) (cAlias)->( DbUnlock() ) ELSE MsgStop("Line " +HB_NtoS(nI)+ " in the table is blocked!") ENDIF NEXT oBrw:GoPos(nRec,nCol) // передвинуть на номер где первоначально стоял МАРКЕР [/pre2]

Haz: Andrey пишет: позиционирование по строке таблицы - подойдёт ли oBrw:GoPos(nI,nCol) Не подойдёт. :: nAt не является номером строки в таблице. А в RDDADS валиасе из SQL запроса, вообще как генератор случайных чисел. Для этого есть ::nRowPos, причём это именно строка в таблице а не запись в базе. Далее в твоём примере не произойдёт смены строки бровса, т. к. нет obrw:Skip(1) Почему просто не сделать в 4 строки nRec := (recno()) Dbeval({¦¦ lMetka :=! lMetka}) Dbgoto(nRec) Obrw:drawSelect() Рассинхронизации бровсе не произойдёт. Alias не указавал т. к. напрягает код писать с телефона. Напиши чего хочешь то? Менять поле по всей таблице используя только методы бровса? Это можно, но не эффективно и тормозит. Не понимаю зачем? Если есть желание, то движение по таблице можно через ::Down() Вернуть обратно на нужную запись ::GotoRec( nrec) Только твой тест заранее в пользу драйвера будет и в разы. Навигация по таблице и пр. все и так использует драйвер. [pre2] n := 1 oBrw:GoTop() nRec := (oBrw:cAlias)->(Recno()) While n <= oBrw:nLen IF (oBrw:cAlias)->(Rlock()) Eval( nBlock, ! Eval(bBlock)) (oBrw:cAlias)->(dbUnlock()) End oBrw:Down() n++ end oBrw:GotoRec(nRec) [/pre2] Вместо ::Down() можно использовать ::Skip() будет быстрее но не наглядно т. к. курсор бровса остаётся на месте. А вообще бросай ты эту затею))

SergKis: Haz пишет Это можно, но не эффективно и тормозит. Не понимаю зачем? Думаю, Андрей хочет построчное изменение тсб, с визуальным эффектом. Ты такое проделывал, кажется с excel, отбирая по одной записи из адс и закидывая через оле. Не эффективно, но наглядно.

Haz: SergKis пишет: Андрей хочет построчное изменение тсб, с визуальным эффектом. делал и в бровсе и в екселе. В екселе это себя еще оправдывает. В бровсе визуальный эффект напрягает 😀 Ну примерно как делать предложено, хочет пусть делает

Andrey: Haz пишет: Напиши чего хочешь то? Менять поле по всей таблице используя только методы бровса? Это можно, но не эффективно и тормозит. Не понимаю зачем? Да ! Просто чтобы было, как ещё второй доступный вариант ! Haz пишет: Если есть желание, то движение по таблице можно через ::Down() Вернуть обратно на нужную запись ::GotoRec( nrec) Это уже использование средства драйвера, через псевдо-метод бровса. Haz пишет: Только твой тест заранее в пользу драйвера будет и в разы. Навигация по таблице и пр. все и так использует драйвер. Это и понятно, я уже у себя в тесте заметил даже на небольших базах. У меня получилось использовать только один вариант с оператором oBrw:GoPos(nI,nCol) ! Здесь спрашивал, можно ещё как нибудь сделать. Свой тест высылаю на почту к тебе, чтобы было понятней о чём идёт речь.

Haz: Andrey пишет: Это уже использование средства драйвера, через псевдо-метод бровса. А ничего что блокировка записи через драйвер? И блок через драйвер работает. Более того в бровсе ты работаешь с текущей записью и никакими средствами не сможешь Получить данные из любой другой пока она не станет текущей, а как тут то без драйвера по Записям прыгать? Все что ты видишь на экране бровса это прошлое- картинка на момент прорисовки и не более. Так что без драйвера увы никак.

Andrey: По итогу всех обсуждений сделал краткую справку ! Как переходить/работать по записям в таблице ? (работа с базой методами бровса - Tsbrowse) 1) - с отображением строки: [pre2]oBrw:GoTop() // передвинуть на первую запись базы oBrw:GoBottom() // передвинуть на последнюю запись базы oBrw:GoDown() // передвинуть на одну запись базы вниз oBrw:GoUp() // передвинуть на oBrw:GotoRec( nRecNo ) // передвинуть на номер записи базы - или так: // меняет указатель записи с помощью GoTo() на нужную запись oBrw:GoPos(nI,nCol) // передвинуть МАРКЕР на nI-строку, nCol-колонку // Или можно так - меняет указатель записи с помощью ::Skip() ПЕРЕБОРОМ в цикле. Правда перебор оптимизирован по разнице nRec := oBrw:nAt // номер текущей строки в таблице nCell := oBrw:nCell // номер текущего столбца в таблице nRPos := oBrw:nRowPos // номер текущей строки в таблице - не меняет указатель записи nRecAll := oBrw:nLen // общее кол-во записей в таблице nRecAll := oBrw:nRowCount // общее кол-во записей в таблице nCol := oBrw:nColumn("LMETKA") // номер колонки LMETKA oCol := oBrw:GetColumn(nCol) bBlock := oCol:bData Eval(bBlock, .F./.T.) // запись значения в колонку LMETKA oCol:cFooting := 'Foot' // запись в подвал колонки или Eval( {|| oBrw:nColumn("LMETKA"):bData }, .F./.T. ) // запись значения в колонку LMETKA oBrw:nColumn("LMETKA"):cFooting := 'Foot' // запись в подвал колонки oBrw:DrawLine() // перерисовать текущую строку таблицы oBrw:DrawSelect() // перерисовать текущую текущую стоку выделенными цветами ( цветом курсора) [/pre2] 2) - без отображения строки: [pre2]cAls := oBrw:cAlias nRec := (cAls)->( RecNo() ) (cAls)->( dbGotop() ) DO WHILE ! (cAls)->( EOF() ) IF (cAls)->(RLock()) // записать в базу .................. (cAls)->( DbUnlock() ) ELSE MsgStop("Recording in the database is blocked!") ENDIF oBrw:Skip(1) ENDDO (cAls)->( dbGoto( nRec ) ) (cAls)->( DBCOMMIT() ) oBrw:Refresh() // или oBrw:Refresh(.T.) oBrw:SetFocus() [/pre2] Работа с базой методами бровса (прислал Игорь Назаров): [pre2]bBlock := oBrw:GetColumn("LMARK"):bData nRec := Eval( ::bRecNo ) oBrw:GoTop() While !oBrw:Eof() if Eval(oBrw:bRecLock()) Eval(bBlock, !Eval(bBlock)) end oBrw:GoDown() // вызовет смещение текущей строки в бровсе и указателя записи в базе // Можно использовать oBrw:Skip(1) НЕ вызовет смещение текущей строки в // бровсе, но сместит указатель записи в базе (бровс рассинхронизируется) End oBrw:GotoRec(nRec) // синхронизация бровса[/pre2] !!! Перемещение и заполнение "средствами таблицы" невозможно в принципе. !!! Все операции в бровсе делаются только через RDD драйвера базы. Рабочий пример смотреть - MiniGUI\SAMPLES\Advanced\Tsb_4bases Функция (вариант 3) присланная SerKis для примера в папке SAMPLES\Advanced\Tsb_4bases\: [pre2]////////////////////////////////////////////// FUNCTION Metka_Test3(cFltr) LOCAL nI LOCAL nO := select() LOCAL oB := oStaticBrw LOCAL cA := oB:cAlias LOCAL cF := 'DIR'+SUBSTR(cA,5) LOCAL bF := oB:GetColumn(cF):bData LOCAL nR := (cA)->( RecNo() ) LOCAL aR := {}, aE := {} dbSelectArea(cA) If ! empty(cFltr) SET FILTER TO &cFltr EndIf dbGotop() DO WHILE ! EOF() If RLock() EVal(bF, ! EVal(bF)) dbUnLock() Else AAdd(aR, RecNo()) EndIf DO EVENTS SKIP ENDDO If ! empty(cFltr) SET FILTER TO EndIf If Len(aR) > 0 FOR nI := 1 TO Len(aR) dbGoto(aR[ nI ]) If RLock() EVal(bF, ! EVal(bF)) dbUnLock() aR[ nI ] := 0 Else AAdd(aE, aR[ nI ]) EndIf NEXT EndIf nI := 0; AEval(aE, {|nv,nn| nI += iif( nv > 0, 1, 0 ) } ) If nI > 0 MsgStop("Строки " +HB_ValToExp(aE)+ " не доступны !") EndIf dbGoto(nR) dbSelectArea(nO) oB:Refresh() oB:SetFocus() RETURN NIL[/pre2]

Vlad04:

Haz: Андрей пишет: oBrw:DrawSelect() // перерисовать текущую ячейку Поправлю, этот метод перерисовывает текущую стоку выделенными цветами ( цветом курсора) и тут не верно oCol:bData := .F./.T. // запись значения в колонку LMETKA bData должно быть блоком кода {¦¦} в примере Eval() не просто так.

SergKis: Haz пишет Поправлю ... Я то же поправлю, как было[pre2] FUNCTION Metka_Test2( cFltr ) LOCAL nI, cFltr ... LOCAL nR := (cA)->( RecNo() ) ... dbSelectArea(cA) cFltr : = DBSETFILTER() ... If ! empty(cFltr) SET FILTER TO &cFltr // восстановить фильтр, если был EndIf dbGoto(nR) [/pre2]

Andrey: Подправил ! Спасибо за помощь !

Andrey: Пишу пример для новой таблицы, с помощью SetArrayTo() и опять засада ! Ну что за диагностика ошибок в SetArrayTo() ... Ничего не понятно из неё !!! [pre2] ? cTbrName, cForm, aArray, aFontHF, aHead, aFSize, aFoot, aPict, aAlign, aName возвращает: oBrwTxt Form_Txt ARRAY[1] NIL ARRAY[16] ARRAY[16] ARRAY[16] ARRAY[16] ARRAY[16] ARRAY[16] oBrw1 := SetArrayTo( cTbrName, cForm, aArray, aFontHF, aHead, aFSize, aFoot, aPict, aAlign, aName )[/pre2] При выполнении ошибка: Error BASE/1132 Переполнение массива: Неверное количество аргументов</p><BR> Called from SETARRAYTO(410) in module: h_tbrowse.prg Called from TABLECREATESTEPONE(160) in module: tsb_form.prg Нельзя указать в каком массиве ошибка ?

SergKis: Andrey пишет Нельзя указать в каком массиве ошибка ? а посмотреть ? [pre2] Function SetArrayTo( ControlName, ParentForm, Arr, uFontHF, aHead, aSizes, uFooter, aPicture, aAlign, aName ) *-----------------------------------------------------------------------------* Local ix, oBrw ix := GetControlIndex (ControlName, ParentForm) oBrw := _HMG_aControlIds [ix] // 410 oBrw:SetArrayTo(Arr, uFontHF, aHead, aSizes, uFooter, aPicture, aAlign, aName) Return oBrw [/pre2] есть др. варианты SetArray(...) и команды, если не подходит SetArrayTo

Andrey: Блин, разобрался... Но всё равно осадок от непонятных ошибок остался... [pre2] cTbrName := "oBrwTxt" DEFINE TBROWSE oBrw1 ; // нужно вместо oBrw1 писать &cTbrName ...... END TBROWSE ? cTbrName, cForm, aArray, aFontHF, aHead, aFSize, aFoot, aPict, aAlign, aName oBrw1 := SetArrayTo( cTbrName, cForm, aArray, aFontHF, aHead, aFSize, aFoot, aPict, aAlign, aName )[/pre2] Желательно бы подправить ошибку на такой случай ! Как всегда ищем ошибку не в том месте !

Andrey: SergKis пишет: а посмотреть ? Посмотрел до этого, но ничего с ходу и не понял... Это видно для знатоков понятно !

Andrey: Первоначально в таблице SetArrayTo было 26 столбцов. Меняю таблицу на 8 столбцов. [pre2] nColMax := LEN(aDim[1]) nColMaxOld := oBrw1:nColCount() For nI := nColMax + 1 To nColMaxOld oBrw1:DelColumn( nI ) Next ? nColMax, oBrw1:nColCount()[/pre2] Результат: [pre2]8 26 8 == 8 [/pre2] Далее пытаюсь заполнить таблицу по новому массиву: [pre2] oBrw1:DeleteRow( .T. ) // Delete All aArray := aDim // переопределяем на новый входящий массив For nI := 1 TO Len(aArray) ? nI, HB_VALTOEXP(aArray[nI]) if ! empty(aArray[ nI ]) ADD ITEM aArray[ nI ] TO &cBrw OF &cForm // строка 384 EndIf Next[/pre2] Вылет с ошибкой: Error BASE/1132 Переполнение массива: Неверное количество аргументов Called from TSBROWSE:SETARRAY(10562) in module: h_tbrowse.prg Called from TSBROWSE:ADDITEM(7901) in module: h_tbrowse.prg Called from _ADDITEM(771) in module: h_controlmisc.prg Called from DOMETHOD(4960) in module: h_controlmisc.prg Called from TABLEFILLSTEPTWO(384) in module: tsb_form.prg Почему ? Что не так делаю ?

Haz: Andrey пишет: Желательно бы подправить ошибку на такой случай ! Как всегда ищем ошибку не в том месте ! Тут не ошибу поправлять надо.... Андрей, ты передал в функцию несуществующий контрол, и ошибка тебе говорит что не могу найти индекс массива по этому контролу. Забивать исходники проверкой на дурака можно но не нужно. Но если это очень важно, ничто не мешает написать обертку для SetarrayTo(), в которой сначала перепроверить все переданные параметры, а потом отдать их в саму SetarrayTo()

Haz: Andrey пишет: Почему ? Что не так делаю ? А по простому в цикле чего не заполнять? oBrw:aArray[x] [y] := aDim[x] [y]

Andrey: oBrw1:DeleteRow( .T. ) // Delete All aArray := ACLONE(aDim) // переопределяем на новый входящий массив For nI := 1 TO Len(aArray) ? nI, HB_VALTOEXP(aArray[nI]) if ! empty(aArray[ nI ]) //ADD ITEM aArray[ nI ] TO &cBrw OF &cForm aRows := Array(1, 8) aRows[1][1] := aArray[nI,1] aRows[1][2] := aArray[nI,2] aRows[1][3] := aArray[nI,3] aRows[1][4] := aArray[nI,4] aRows[1][5] := aArray[nI,5] aRows[1][6] := aArray[nI,6] aRows[1][7] := aArray[nI,7] aRows[1][8] := aArray[nI,8] ? "aRows[1]=" , HB_VALTOEXP(aRows[1]) oBrw1:AddItem( aRows[1] ) EndIf Next Вылет на строке - oBrw1:AddItem( aRows[1] ) Почему ?

Andrey: Поставил отладку в h_tbrowse.prg и выяснил ОЧЕНЬ интересную вещь !!! Оказывается в таблице ОСТАЛОСЬ 26 столбцов ! Почему ? Я же делал удаление: [pre2] For nI := nColMax + 1 To nCol oBrw1:DelColumn( nI ) Next[/pre2] и перепроверял у себя в коде : ? oBrw1:nColCount() -> возвращает 8. А в модуле h_tbrowse.prg строка 10561: [pre2] For nI := 1 To nColumns ? nI, "/", nColumns ? ::aArray[ 1, nI ] cType := ValType( ::aArray[ 1, nI ] )[/pre2] ? nColumns возвращает 26 !!! Как так ? Может как то очистить надо ? Типа oBrw1:Reset() ?

Andrey: Чтобы не было путаницы, описываю кратко задачу которую делаю. 1) На форму вывожу таблицу из ОДНОЙ строки 26 колонок. Просто для краткости. 2) Далее эту таблицу удаляю и меняю на нужную - пусть будет 50 записей и 8 колонок. Вылет происходит при присваивании нового массива в таблицу. Пробовал двумя методами:[pre2] ADD ITEM aArray[ nI ] TO &cBrw OF &cForm и aRows := Array(1, 8) aRows[1][1] := aArray[nI,1] ..... oBrw1:AddItem( aRows[1] )[/pre2] Полазив по h_tbrowse.prg понял что там не правильно определяется размер колонок. Остаётся старая длина колонок - 26. Исходник h_tbrowse.prg строка 10558:[pre2] nColumns := If( ! Empty( aHead ), Len( aHead ), If( ! Empty( ::aArray ), Len( ::aArray[ 1 ] ), 0 ) ) ::aDefValue := Array( Len( aArray[ 1 ] ) ) ? "--------- h_tbrowse.prg nColumns=",nColumns // моя отладка возвращает 26 ? "Len( aHead )=", Len( aHead ), "Len( ::aArray[ 1 ] )=", Len( ::aArray[ 1 ] ) // моя отладка возвращает 26 и 8 For nI := 1 To nColumns ...........[/pre2] Вопрос - как у себя в программе обнулить массив - aHead который в h_tbrowse.prg ? Почему не срабатывает удаление колонок для массива заголовков таблицы, т.е. не работает этот код: [pre2] nCol := oBrw1:nColCount() // сколько колонок в текущем массиве nColMax := LEN(aDim[1]) // сколько колонок в новом массиве For nI := nColMax + 1 To nCol oBrw1:DelColumn( nI ) Next[/pre2] Может я не так удаляю ?

Петр: Просто для краткости - лезьте снова в h_tbrowse.prg и попытайтесь понять, как же работает метод DelColumn .. hb_ADel( ::aColumns, nPos, .T. ) // это в виде бонуса ..

Haz: Петр пишет: лезьте снова в h_tbrowse.prg Это правильный посыл. Петр пишет: это в виде бонуса Петр, это надо расписать подробнее для Андрея . Когда допиливалось заполнение бровса из массивов параметров, метод ::DelColumn(), прошли мимо. Думаю просто до него не дошли в тестах. Андрей в исходнике правильно нашёл 2 ключевых места. 1) количество колонок приоритено определяется по длинне массива заголовков 2) ::DelColumn не меняет массивы заголовков, шаблонов, и выравнивания. Но поскольку все это определено в данных объекта бровса, то легко доступно из прикладной программы. Вопрос Андрея понимаю так "как удалить элемент из массива?" И вот тут короче чем твой бонус уже не скажешь. PS. Но по большому счету это нужно добавить в :DelColumn() тремя аналогичными строками.

Andrey: Haz пишет: Но по большому счету это нужно добавить в :DelColumn() тремя аналогичными строками. Да, это было бы отлично ! Но увы, я не смогу, знаний у меня пока ещё не хватает... Если не сложно, сделайте пожалуйста это. Всё равно потом другой кто-то наткнётся на эти

SergKis: У нас уже была дискуссия по oBrw:DelColumn() nn времени назад. Результатом было отказ от него, т.к. проще сделать release и пересоздать тсб как нужно, чем корячится с отладкой тсб. Кинул пример Андрею, пусть поделится, если хочет, там его небольшая база использована

Haz: Andrey пишет: Но увы, я не смогу, знаний у меня пока ещё не хватает... Не пойму какие знания нужны для 1 строки кода [pre2] MEIHOD DelColumn() ... ... oCol := ::aColumns[ nPos ] ARRDEL_( ::aColumns, nPos ) ARRDEL_( ::aColSizes, nPos ) ARRDEL_( ::aHeaders, nPos ) // можно и с проверкой что такой элемент есть в этом массиве ... ... [/pre2] можно попутно резануть и массивы ::aFormatPic ::aJustify но на расчет nColumns в методе StArray/SetArrayTo они не влияют.

Haz: SergKis пишет: У нас уже была дискуссия по oBrw:DelColumn() nn времени назад. Результатом было отказ от него, т.к. проще сделать release и пересоздать тсб как нужно, чем корячится с отладкой тсб Сергей , я видимо пропустил эту дискуссию или был в коматозе от работы. Но даже в случае отказа от ::DelColumn - не велика потеря, хотя для полноты класса он нужен. Всегда можно написать свою функцию при необходимости. Я использую иногда у себя DelColumn тк это быстрее чем собирать сложный бровс. А вот HideColumn не люблю, на бровсе с большим количеством полей визуально как резиновый "растягай" себя ведет )) Release и пересоздание использую только когда на этом месте нужно показать другой бровс Вообще интересно , почему в методе SetArray ( который являлся изначальным шаблоном для твоего SetArrayTo ) количество столбцов определяется через Len( ::aHeading ), а не как Len( ::aColumns )

SergKis: Haz пишет интересно , почему в методе SetArray ( который являлся изначальным шаблоном для твоего SetArrayTo ) количество столбцов определяется через Len( ::aHeading ), а не как Len( ::aColumns ) ответ на кусочке из примера[pre2] STATIC FUNCTION MyTest() LOCAL aArray, aHead, aSize, aFoot, aPict, aAlign, aName, aFontHF LOCAL oBrw := _HMG_aControlIds [ (This.oBrw.Index) ] LOCAL cForm := oBrw:cParentWnd LOCAL cBrw := oBrw:cControlName LOCAL nSet := This.Cargo // это StatusBar.Cargo If empty(nSet) aArray := AClone( ThisWindow.Cargo[ 1 ] ) aHead := ASize(AClone( ThisWindow.Cargo[ 2 ] ), 6) aSize := ASize(AClone( ThisWindow.Cargo[ 3 ] ), 6) aFoot := ASize(AClone( ThisWindow.Cargo[ 4 ] ), 6) aPict := ASize(AClone( ThisWindow.Cargo[ 5 ] ), 6) aAlign := ASize(AClone( ThisWindow.Cargo[ 6 ] ), 6) aName := ASize(AClone( ThisWindow.Cargo[ 7 ] ), 6) This.Cargo := 1 Else aArray := AClone( ThisWindow.Cargo[ 1 ] ) aHead := AClone( ThisWindow.Cargo[ 2 ] ) aSize := AClone( ThisWindow.Cargo[ 3 ] ) aFoot := AClone( ThisWindow.Cargo[ 4 ] ) aPict := AClone( ThisWindow.Cargo[ 5 ] ) aAlign := AClone( ThisWindow.Cargo[ 6 ] ) aName := AClone( ThisWindow.Cargo[ 7 ] ) This.Cargo := 0 EndIf _ReleaseControl(cBrw, cForm) // delete picture object oBrw := CreateTsb(cBrw, cForm, aArray, aHead, aSize, aFoot, aPict, aAlign, aName) RETURN Nil [/pre2] т.е. достаточно сменить шапку и остальное не трогать, где то смысл есть в этом.

SergKis: Haz пишет ::DelColumn - не велика потеря, хотя для полноты класса он нужен. Но лезть в класс, лично у меня, нет сил, если кто то ...

Andrey: Haz пишет: Не пойму какие знания нужны для 1 строки кода А кто ж знал что нужно добавить только 1 строчку ? Я думал, что кучу всего тащить придётся ! Haz пишет: можно попутно резануть и массивы ::aFormatPic ::aJustify но на расчет nColumns в методе StArray/SetArrayTo они не влияют. Нужно ОБЯЗАТЕЛЬНО ! Т.е. если не переопределить, то при присвоении новых данных будет вылет по ошибке.

Петр: Для Andrey Не вникая в реализацию DelColumn, могу сказать, что он не заточен на удаление столбцов в цикле [pre2]procedure main() local aTest := Array( 26 ) local nSize := Len( aTest ) local i := 8 for i := i + 1 to nSize ? i, nSize, Len( hb_ADel( aTest, i, .T. ) ) next [/pre2] ps. по крайней мере это относится к циклу for, который вы собрались использовать

Andrey: Haz пишет: MEIHOD DelColumn() ... ... oCol := ::aColumns[ nPos ] ARRDEL_( ::aColumns, nPos ) ARRDEL_( ::aColSizes, nPos ) ARRDEL_( ::aHeaders, nPos ) // можно и с проверкой что такой элемент есть в этом массиве ... Не могу найти это кусок кода. Брал последний МиниГуи 17.12, в исходнике h_tbrowse.prg: [pre2]* ============================================================================ * METHOD TSBrowse:DelColumn() Version 9.0 Nov/30/2009 * ============================================================================ METHOD DelColumn( nPos ) CLASS TSBrowse .......... Строка 2078: oCol := ::aColumns[ nPos ] hb_ADel( ::aColumns, nPos, .T. ) hb_ADel( ::aColSizes, nPos, .T. )[/pre2] То или не то ?

Haz: Andrey пишет: То или не То, у меня видимо старее версия.

Haz: Сергей пишет : Но лезть в класс, лично у меня, нет сил, Аналогично, только если мелкими шагами. Поскольку этот класс в последние годы активно меняется Вижу только вариант постепенного доведения до условно оптимального. Что касается SetArray или SetArrayto, испозую редко. Но именно SetArrayTo логично востребован. У меня есть свой типа ComboBox на основе бровса. Для разных полей нужен разный выбор, и тут SetArrayTo отлично вписался.

SergKis: Игорь пишет и тут SetArrayTo отлично вписался. У меня, большинство, чтение csv и txt файлов. Типа ранее сохраненных hb_memowrit(cFile, hb_valtoexp(aArray)) потом читаемых aArray := &( hb_memoread(cFile) ) или aTemp := hb_ATokens(hb_memoread(cFile), CRLF) aArray := {}; AEVal(aTemp, {|cv| iif( empty(cv), Nil, AAdd(aArray, &cv) ) }) и т.д., т.е. отчеты\отборы, прием\обмен табл.данными

Andrey: Григорий - можно сделать правку в исходнике ? последний МиниГуи 17.12, в исходнике h_tbrowse.prg: [pre2]* ============================================================================ * METHOD TSBrowse:DelColumn() Version 9.0 Nov/30/2009 * ============================================================================ METHOD DelColumn( nPos ) CLASS TSBrowse .......... Строка 2078: oCol := ::aColumns[ nPos ] hb_ADel( ::aColumns, nPos, .T. ) hb_ADel( ::aColSizes, nPos, .T. ) hb_ADel( ::aHeaders, nPos, .T. ) // новая строка hb_ADel( ::aFormatPic, nPos, .T. ) // новая строка[/pre2] С этой правкой мой проект заработал ! Т.е. удаление столбцов и присваивание новых массивов и показ новой таблицы проходит отлично ! Единственно что не проверил это добавление новых столбцов. Но это уже чуть позже.

gfilatov2002: Andrey пишет: можно сделать правку в исходнике ? Да, конечно. По итогу обсуждения добавил такие строки [pre2] If ValType( ::aHeaders ) == "A" .and. Len( ::aHeaders ) >= nPos hb_ADel( ::aHeaders, nPos, .T. ) EndIf If ValType( ::aFormatPic ) == "A" .and. Len( ::aFormatPic ) >= nPos hb_ADel( ::aFormatPic, nPos, .T. ) EndIf [/pre2]

Петр: gfilatov2002 пишет: По итогу обсуждения добавил такие строки Григорий, проверки здесь излишние. hb_ADel и так их выполняет, не сваливаясь при этом в обработчик ошибок.

ММК: Haz пишет: А вот HideColumn не люблю, на бровсе с большим количеством полей визуально как резиновый "растягай" себя ведет )) — Соломон Моисеевич, вы любите жизнь? — Люблю! — А почему? — А куда деваться? SergKis пишет: т.е. достаточно сменить шапку и остальное не трогать, где то смысл есть в этом. Правый клик по шапке и в меню. Убрал птичку -нет столбца. Поставил птичку - есть столбец ...

Haz: ММК пишет: Убрал птичку -нет столбца. Поставил птичку - есть столбец ... Да спрятать или показать колонку не сложно. я высказал свое отношение к спрятанным колонкам. Мне проще её удалить, чем тянуть в бровсе лишнее. Да и от удаления колонки поле в базе никуда не денется. В качестве абсурда можно сделать пример бровса из 200 колонок и скрыть от 5 и далее все остальное , потом сдвинуться вправо дальше 5. Такой пример скорее не логичен, но демонстрирует хорошо. Кстати то что делает Андрей ( перестраивает бровс по колонкам удаляя лишние и добавляя нужные) Я тоже использую. К примеру классический бюджет подразделения по статьям, левая часть названия, статьи, коды. Правая часть движение денег по периодам. При этом периоды произвольные, если за год по дням то их 365, если по месяцам 12, если по неделям то 52(53). Тупо строю SQL запрос на нужное число периодов, удаляю правую часть бровса и подсунув ему новую рабочую область добавляю колонки. Бюджет из поквартального с 4 колонками превращается в недельный с 52 за 2 секунды. В подням на тригода вперёд за 5 сек, а это 1000 полей. Ясно что практически такая детализация не нужна, но эффект впечатляет. Так это я к тому, если бы я прятал колонки, то сколько мне их нужно было заранее держать в бровсе

SergKis: MMK пишет Правый клик по шапке и в меню. Убрал птичку -нет столбца. Поставил птичку - есть столбец ... избегаю такие режимы давать пользователю, предпочитаю дать ему возможность поставить галочки в вертикальном списке шапок и отметить нужные шапки, расположив в нужной последовательности, при необходимости сохранить как отчет с названиями и ... В дальнейшем работа это выбор отчета из списка. SergKis пишет т.е. достаточно сменить шапку и остальное не трогать, где то смысл есть в этом. Имел ввиду, что поля не вошедшие в таблицу отображаются рядом в вертикальной развертке (режим "карточка") и кликами можно переключать с табличного на "карточный" режим

Andrey: Хрень получается при очистке таблицы. Один раз чистит от записей, второй нет. Или я опять что то не то делаю. Команда oBrw1:DeleteRow( .T. ) делает полную очистку таблицы для SetArrayTo() ? Ещё что-то нужно делать для очистки таблицы ? Вывожу таблицу (функция допустим TsbView(aDim,.F.) ) первый раз с условиями (допустим код колонки 7 < 11) . На чекбокс делаю показ этой же самой функции в зависимости от чекбокса TsbView(aDim,lFilter). Если чекбокс равет .T. то показываю записи - код колонки 7 == 11. При повторном показе записей в таблице остаются записи от первого показа + новые. Если ещё раз кликнуть чекбоксом, записи в таблице прибавляются... Почему ? Я же делаю для SetArrayTo() : [pre2] oBrw1:DeleteRow( .T. ) // Delete All oBrw1:Reset()[/pre2] и только потом делаю добавление построчно: [pre2]oBrw1:AddItem( aRows[1] ) [/pre2] ---- P.S. И первый раз не чистит. Кажись если колонки удалили - оператор oBrw1:DeleteRow( .T. ) перестаёт работать ...

gfilatov2002: Andrey пишет: что-то нужно делать для очистки таблицы ? Посмотри рабочий пример ниже [pre2] #include "minigui.ch" #include "tsbrowse.ch" Procedure Main () Public oBrw1 Public aDatos_origen DEFINE WINDOW Form1 ; AT 0,0 ; WIDTH 640 ; HEIGHT 480 ; TITLE "TsBrowse Array Test" ; MAIN ; FONT 'Tahoma' SIZE 9; ON INIT Sample1() END WINDOW ACTIVATE WINDOW Form1 RETURN *-------------------------------------------------------------- Function Sample1() Local bColor := { || If( Val(oBrw1:aArray[oBrw1:nAt,4]) < 200, CLR_RED, CLR_WHITE ) } aDatos_origen := {} AADD( aDatos_origen, {"Ena ", "Art01", "Mod01", "200"} ) AADD( aDatos_origen, {"Dyo ", "Art02", "Mod01", "200"} ) AADD( aDatos_origen, {"Tria ", "Art03", "Mod01", "200"} ) AADD( aDatos_origen, {"Tessera ", "Art04", "Mod01", "200"} ) AADD( aDatos_origen, {"Pente ", "Art05", "Mod01", "200"} ) AADD( aDatos_origen, {"Exi ", "Art06", "Mod01", "200"} ) AADD( aDatos_origen, {"Epta ", "Art07", "Mod01", "200"} ) AADD( aDatos_origen, {"Okto ", "Art08", "Mod01", "200"} ) AADD( aDatos_origen, {"Ennea ", "Art09", "Mod01", "100"} ) AADD( aDatos_origen, {"Deka ", "Art10", "Mod02", "200"} ) AADD( aDatos_origen, {"Enteka ", "Art11", "Mod02", "200"} ) AADD( aDatos_origen, {"Dodeka ", "Art12", "Mod02", "200"} ) AADD( aDatos_origen, {"Dekatria ", "Art13", "Mod02", "200"} ) AADD( aDatos_origen, {"Dekatessera ", "Art14", "Mod02", "200"} ) AADD( aDatos_origen, {"Dekapente ", "Art15", "Mod02", "200"} ) AADD( aDatos_origen, {"Dekaexi ", "Art16", "Mod02", "200"} ) AADD( aDatos_origen, {"Dekaepta ", "Art17", "Mod02", "200"} ) AADD( aDatos_origen, {"Dekaokto ", "Art18", "Mod02", "200"} ) DEFINE TBROWSE oBrw1 ; AT 60,10 ; OF Form1 ; WIDTH 330 ; HEIGHT 340 ; FONT "Verdana" ; SIZE 9 ; GRID oBrw1:SetArray( aDatos_origen ) ADD COLUMN TO TBROWSE oBrw1 ; DATA ARRAY ELEMENT 1; TITLE "Rubro" SIZE 120 ADD COLUMN TO TBROWSE oBrw1 ; DATA ARRAY ELEMENT 2; TITLE "Articulo" SIZE 80 ADD COLUMN TO TBROWSE oBrw1 ; DATA ARRAY ELEMENT 3; TITLE "Marca" SIZE 80 ADD COLUMN TO TBROWSE oBrw1 ; DATA ARRAY ELEMENT 4; TITLE "M" SIZE 30 ; COLORS CLR_BLACK, bColor oBrw1:lNoVScroll := .t. End TBROWSE oBrw1:Refresh(.T.) @ 110,355 BUTTON Button_1 OF Form1; CAPTION "Change"; ACTION Change() ; WIDTH 80; HEIGHT 28 ; FONT "Arial" SIZE 9 RETURN Nil Function Change() Local aArray := {}, n AADD( aArray, {"Ena ", "Art01", "Mod01", "200"} ) AADD( aArray, {"Dyo ", "Art02", "Mod01", "200"} ) AADD( aArray, {"Tria ", "Art03", "Mod01", "200"} ) AADD( aArray, {"Tessera ", "Art04", "Mod01", "200"} ) AADD( aArray, {"Pente ", "Art05", "Mod01", "200"} ) AADD( aArray, {"Exi ", "Art06", "Mod01", "200"} ) AADD( aArray, {"Epta ", "Art07", "Mod01", "200"} ) AADD( aArray, {"Okto ", "Art08", "Mod01", "200"} ) AADD( aArray, {"Ennea ", "Art09", "Mod01", "100"} ) AADD( aArray, {"Deka ", "Art10", "Mod02", "200"} ) oBrw1:aArray:={} for n:=1 to len(aArray) ADD ITEM aArray[n] TO oBrw1 OF Form1 next oBrw1:Refresh(.T.) Return Nil [/pre2] Надеюсь, что вопросы по очистке массива отпадут

SergKis: gfilatov2002 пишет По итогу обсуждения добавил такие строки наверно надо добавить в :DelColumn и удаление элементов из ::aJustify и ::aDefValue

gfilatov2002: SergKis пишет: надо добавить в :DelColumn Благодарю за помощь Добавил эти массивы и убрал лишние проверки, как предложил ранее Петр...

Andrey: gfilatov2002 пишет: Надеюсь, что вопросы по очистке массива отпадут Точно, не хватало oBrw1:aArray:={} !!! Это называется - нужно учить матчасть...

ММК: Haz пишет: Так это я к тому, если бы я прятал колонки, то сколько мне их нужно было заранее держать в бровсе Извините , виноват . Мне надо было сразу написать, что это пример на FW. А там это просто опция бровса ( встроенная ), как поиск, фильтр, экспорт в эксель.... ну и много еще что :)) Выложил просто в виде подсказки ( как вариант) , как в будущем можно будет доработать ( или переписать ) бровс Думаю Сергей прав - удобнее работать с столбцами на уровне шапки.

Andrey: Осталась мелочёвка по SetArrayTo(): 1) Пропадает нижняя стрелка в строке скролинга: 2) Отключаю показ горизонтального скролинга, а он всё равно отображается: 3) Не убирается дырка внизу таблицы (один раз срабатывает, второй нет). Может быть из за показа горизонтального скролинга ? 4) В конце функции делаю фокус на таблицу. Не срабатывает ! Вот код в конце функции, которая выводит SetArrayTo(): [pre2] oBrw1:HideColumns( {6,7,8} ,.t.) // скрыть колонки oBrw1:Reset() oBrw1:SetNoHoles(2) oBrw1:lNoHScroll := .T. // нет показа горизонтального скролинга oBrw1:Display() oBrw1:Refresh(.T.) // перечитывает данные в таблице oBrw1:GoPos(1,4) // передвинуть МАРКЕР на Х строку и Х колонку ItogoNN(oBrw1) oBrw1:SetFocus() [/pre2] Что не так делаю ?

Dima: Andrey пишет: Что не так делаю ? Спишь мало Проспись и все получится !

SergKis: Dima пишет Проспись и все получится ! Возможно ты уже поборол такую ситуевину ? У меня получилось так [pre2] DEFINE TBROWSE &cBrw ; AT 1 + iif( IsVistaOrLater(), GetBorderWidth()/2, 0 ), ; 1 + iif( IsVistaOrLater(), GetBorderHeight()/2, 0 ) ; OF &cForm ; WIDTH ThisWindow.WIDTH - 2 * GetBorderWidth() ; HEIGHT ThisWindow.HEIGHT - GetTitleHeight() - ; This.StatusBar.Height - 2 * GetBorderHeight() ; // ENUMERATOR ; FONT cFontName SIZE nFontSize ; GRID // EDIT oBrw := _HMG_aControlIds [ GetControlIndex(cBrw, cForm) ] oBrw:Hide() aFontHF := aFont[2] // bold Header, Footer oBrw := SetArrayTo( cBrw, cForm, aArray, aFontHF, aHead, aSize, aFoot, aPict, aAlign, aName ) WITH OBJECT oBrw :aColumns[1]:nAlign := DT_CENTER :aColumns[2]:nAlign := DT_CENTER :aColumns[3]:nWidth += 20 // колонку даты расширили :aColumns[4]:nAlign := DT_RIGHT AEval(:aColumns, {|oc| oc:lEmptyValToChar := .T. }) :lNoHScroll := .T. :nWheelLines := 1 :nClrLine := COLOR_GRID :nHeightCell += 5 :nHeightHead += 5 IF ! Empty( aFoot ) :nHeightFoot += 5 ENDIF IF :lEnum :nHeightSpecHd := :nHeightCell ENDIF END WITH MyTsbColor( oBrw ) END TBROWSE oBrw:SetNoHoles() oBrw:Show() oBrw:SetFocus() _PushKey(VK_PRIOR) [/pre2] или отказаться от :lNoHScroll := .T.

SergKis: Andrey пишет Отключаю показ горизонтального скролинга, а он всё равно отображается: При первом отображении тсб, у него нет HScroll, после переформирования array, он проявляется и не убирается, потому получается дырка. Т.к. колонок больше экрана, то смысла убирать HScroll нет. Если поставить oBrw1:lNoVScroll := .F. // TRUE oBrw1:lNoHScroll := .F. // нет показа горизонтального скролинга то дырки не будет. В данном случае логично работать с HScroll.

SergKis: PS oBrw1:oHScroll := Nil не помогает, HScroll проявляется

Andrey: Всем привет ! Сделал менюшку показа адреса через COMBOBOX. Выбор города, улицы, номер дома - отлично показывается. А список квартир бывает большой, листать юзеру неудобно будет. Решил переделать через SetArrayTo() Можно ли убрать показ заголовка таблицы и как ?

SergKis: Andrey пишет Можно ли убрать показ заголовка таблицы и как ? 1. DATA lDrawHeaders AS LOGICAL INIT .T. // condition for headers drawing DATA lDrawFooters // condition for footers drawing 2. сделать высоту header, footer в пару пикселей, если они цветные , будут полоски.

Andrey: Сделал менюшку показа списка квартир через SetArrayTo(). Вроде красивенько получилось. А как можно закрасить Tsbrowse в "шашечку" ? Ну чтобы была как шахматная доска. Это не для показа юзеру, просто для себя. У себя раскраску делаю так: [pre2] // ---- cтавим по всем колонкам ----( oCol:nClrBack = oBrw:SetColor( {2} ...) ---- AEval(oBrw1:aColumns, {|oCol| oCol:nClrBack := { |a,b,o| a:=b, MyColorTsb( o:nAt ) } } ) ........... //////////////////////////////////////////////////////////// STATIC FUNCTION MyColorTsb(nAt) LOCAL nColor IF nAt % 2 == 0 nColor := CLR_HGRAY ELSE nColor := CLR_WHITE ENDIF RETURN nColor[/pre2]Вот что получается:

SergKis: Andrey пишет А как можно закрасить Tsbrowse в "шашечку" ? Ну чтобы была как шахматная доска 1. переведи на русский (словами) из функции[pre2] IF nAt % 2 == 0 nColor := CLR_HGRAY ELSE nColor := CLR_WHITE ENDIF [/pre2] 2. также словами напиши\расшифруй "шахматная доска" Получишь ответ, как сделать

Andrey: SergKis пишет: 2. также словами напиши\расшифруй "шахматная доска" Выбор по ячейки - четная/не четная. Не знаю как вместо nAt указать ячейку. Пробовал ставить oBrw1:nCell - не получается.

Haz: Andrey пишет: У себя раскраску делаю так: // ---- cтавим по всем колонкам ----( oCol:nClrBack = oBrw:SetColor( {2} ...) ---- AEval(oBrw1:aColumns, {|oCol| oCol:nClrBack := { |a,b,o| a:=b, MyColorTsb( o:nAt ) } } ) Андрей, а сможешь объяснить выделенное красным в твоем коде ? Возможно когда сможешь ,то и шахматка получится

Andrey: Haz пишет: Андрей, а сможешь объяснить выделенное красным в твоем коде ? Это делалось для того, чтобы компиляция проходила. Без этого ехе-ник не собирается. Я использую ключи при компиляции: -prgflag=-w2 -es2 Сделал ранее так и забыл... Понял в какую сторону нужно глядеть. Спасибо !

Haz: Andrey пишет: Это делалось для того, чтобы компиляция проходила. Тогда тебе повезло, что бровс не реагирует на присвоение значения в ::nAt, кстати ты не так давно огорчался по этому поводу

Andrey: Опять непонятки... Делаю: [pre2] AEval(oBrw1:aColumns, {|oCol| oCol:nClrBack := { |a,b| MyColorTsb(a,b) } } ) .... //////////////////////////////////////////////////////////// STATIC FUNCTION MyColorTsb(nA,nB) .... nColCount := oBrw1:nColCount() ? "a,b=(",nA,nB,")", "nColCount=", nColCount[/pre2] Получаю:[pre2] a,b=( 1 18 ) nColCount= 18 a,b=( 1 2 ) nColCount= 18 a,b=( 1 3 ) nColCount= 18 a,b=( 1 4 ) nColCount= 18 a,b=( 1 5 ) nColCount= 18 a,b=( 1 6 ) nColCount= 18 a,b=( 1 7 ) nColCount= 18 a,b=( 1 8 ) nColCount= 18 a,b=( 1 9 ) nColCount= 18 a,b=( 1 10 ) nColCount= 18 a,b=( 1 11 ) nColCount= 18 a,b=( 1 11 ) nColCount= 11 a,b=( 1 1 ) nColCount= 11 a,b=( 1 2 ) nColCount= 11 a,b=( 1 3 ) nColCount= 11 a,b=( 1 4 ) nColCount= 11 a,b=( 1 5 ) nColCount= 11 a,b=( 1 6 ) nColCount= 11 a,b=( 1 7 ) nColCount= 11 a,b=( 1 8 ) nColCount= 11 a,b=( 1 9 ) nColCount= 11 a,b=( 1 10 ) nColCount= 11[/pre2] У меня таблица из 11 колонок. Откуда берётся 18 ?

SergKis: Andrey пишет nColCount := oBrw1:nColCount() У меня таблица из 11 колонок. Откуда берётся 18 ? метод простой METHOD nColCount() INLINE Len( ::aColumns )

Andrey: SergKis пишет: метод простой METHOD nColCount() INLINE Len( ::aColumns ) А почему он сначала выдает 18 ? У меня 11 колонок в таблице. Кажется, я понял почему у меня 18 столбцов сначала выдаёт ! Я же таблицу пере создаю на основе готовой: [pre2]oBrw1:DeleteRow( .T. ) // Delete All oBrw1:aArray:={} // очистить массив[/pre2] Первоначально таблица была из 18 столбцов. Т.е. этот параметр нужно тоже где-то переопределять в исходниках h_tbrowse.prg Григорий посмотри пожалуйста, где его нужно переопределить до выхода новой версии !

SergKis: Andrey :Reset()

Andrey: SergKis пишет: :Reset() Делаю. Не срабатывает !

Haz: Andrey пишет: Я же таблицу пере создаю на основе готовой: oBrw1:DeleteRow( .T. ) // Delete All oBrw1:aArray:={} // очистить массив Не надо ничего переопределять в новой версии , надо пересоздавать таблицу ( как бы это сказать ... по литературно ) ... творчески от того что ты в бровсе убил все строки и массив данных, количество колонок в нем не изменится. Андрюха, тебя уже пятый год посылают исходники глянуть, хотя бы ознакомительно . в следующий раз так переопределишь таблицу по DBF и будешь удивляться кто тебе базу грохнул

Haz: Чуть дополню Andrey пишет: oBrw1:DeleteRow( .T. ) // Delete All oBrw1:aArray:={} // очистить массив ну во первых ::DeleteRow(.T.) для бровса по массиву сам делает ::aArray := {} т.е. вторая строка бессмысленна. во вторых ::DeleteRow(.T.) при бровсе по массиву проверяет длину этого массива и если она нулевая восстанавливает пустую строку ::aArray := { AClone( ::aDefValue ) } ( это чтоб не было ошибки времени исполнения при доступе к массиву по индексу ). всякие ::aArray := {} как недокументированные инструменты бровса желательно использовать когда есть понимание как это работает, для остальных есть только методы класса. К слову сказать ::DelColumn() и тот не трогает ::aArray, так как считает это источником данных ( иначе при бровсе по базе надо было бы в базе удалять поле ... ). ну и ради чего я это написал , ради следующего предложения Перед использованием любого метода желательно влезть в исходники и посмотреть что этот метод делает , а перед использованием недокументированных возможностей в исходники лезть обязательно. Тем более, что скорее всего какая то часть кода выльется в пример для новичков. Новичкам будет крайне неприята потеря данных из-за копирования стиля из примера.

Andrey: Haz пишет: ну во первых ::DeleteRow(.T.) для бровса по массиву сам делает ::aArray := {} т.е. вторая строка бессмысленна. Не согласен с этим. Сам налетел на эти грабли. Если делаешь перечитку массива без удаления/создания нового, таблица добавляется, т.е. старые элементы остаются. Григорий предложил oBrw1:aArray:={} // очистить массив и добавление прекратилось. Если не веришь, то могу пример сделать и показать как это происходит. Haz пишет: во вторых ::DeleteRow(.T.) при бровсе по массиву проверяет длину этого массива и если она нулевая восстанавливает пустую строку ::aArray := { AClone( ::aDefValue ) } ( это чтоб не было ошибки времени исполнения при доступе к массиву по индексу ). Да это есть такое. Все пытался убрать это при перечитывании массива. В исходнике увидел и понял, что первую строчку не удалить. А всё таки после перечитки массива, oBrw:nColCount() на первом шаге возвращает 18 колонок (из старого массива), а потом нормально показывает 11. Вот листинг: [pre2] // ---- cтавим по всем колонкам ----( oCol:nClrBack = oBrw:SetColor( {2} ...) ---- AEval(oBrw1:aColumns, {|oCol| oCol:nClrBack := { |nr,nc,ob| MyColorTsb(nr,nc,ob) } } ) //////////////////////////////////////////////////////////// STATIC FUNCTION MyColorTsb( nAt, nCol, oBrw) LOCAL nColor, nColCount := oBrw:nColCount() ? nAt, nCol,"nColCount=",nColCount --------------------------------------- 1 18 nColCount= 18 1 2 nColCount= 18 1 3 nColCount= 18 1 4 nColCount= 18 1 5 nColCount= 18 1 6 nColCount= 18 1 7 nColCount= 18 1 8 nColCount= 18 1 9 nColCount= 18 1 10 nColCount= 18 1 11 nColCount= 18 1 11 nColCount= 11 1 1 nColCount= 11 1 2 nColCount= 11 1 3 nColCount= 11 1 4 nColCount= 11 [/pre2]

Haz: Andrey пишет: Если не веришь, то могу пример сделать и показать как это происходит Я тебе верю. Но в исходнике метода написано ::aArray := {} при ::DeleteRow(.T.) и исходникам я тоже верю. Так же верю что в случае с DBF ::DeleteRow() вызывает dbDelete() со всеми вытекающими. По этому, для переопределения бровса этот метод слишком рискован, надо понимать что он делает. Сам подход в снаряду не верен. Как ранее писал Сергей, самое простое это релизннуть бровс и создать новый. Но раз легкие пути не для нас, то начинать надо с изучения что делает с бровсом :: SetArray (), как устанавливаются при этом внутренние переменные, как назначаются ::nLen, ::aColumns, ::aDefValues. В случае с DBF ::cAlias, ::bLogicPos и ещё куча всего. Только после этого все корректно переопределять. Рубить сразу ::aArray := {}, а остальное само рассосётся это костыли, которые всегда ломаются в самый нужный момент. Это и есть причина твоих 18. По параметрам в MyColorTsb() вижу что ты изучил таки тему и понял что их в nClrBack должно быть три и разобраться какие. Значит не зря. Шахматку мог бы и не постить, понимая что за параметры ждёт блок, задача уже решена. Если хочешь сделать действительно стоящий пример, то избавься от костылей. К сожалению с телефона я тебе помочь не могу. После праздников выйду на работу, гляну на компе. Но уверен ты и сам справишся

Andrey: Haz пишет: По параметрам в MyColorTsb() вижу что ты изучил таки тему и понял что их в nClrBack должно быть три и разобраться какие. Значит не зря. Шахматку мог бы и не постить Параметры понял, не понял почему nColCount := oBrw:nColCount() , а дальше пошла у меня фигня от этого... Шахматку, сознаюсь не одолел - Сергей помог. Я там такой алгоритм фиговый писал, а обошлось всего 2 доп.IF Haz пишет: самое простое это релизннуть бровс и создать новый. Да это я понял. Но пример насчёт этого всё равно сделаю, уже придумал какой.

Haz: Andrey пишет: е понял почему nColCount := oBrw:nColCount() , а дальше пошла у меня фигня Затрахался на смарте пример набирать. Не проверял разумеется. Взял за основу тест Григория. В примере тупо подмена массива в бровсе. При простом переприсвоении ::aArray был бы вылет по типам данных. Здесь надеюсь все работает. [pre2] #include "minigui.ch" #include "tsbrowse.ch" Procedure Main () Public oBrw1 Public aDatos_origen DEFINE WINDOW Form1 ; AT 0,0 ; WIDTH 640 ; HEIGHT 480 ; TITLE "TsBrowse Array Test" ; MAIN ; FONT 'Tahoma' SIZE 9; ON INIT Sample1() END WINDOW ACTIVATE WINDOW Form1 RETURN *-------------------------------------------------------------- Function Sample1() Local bColor := { || If( Val(oBrw1:aArray[oBrw1:nAt,4]) < 200, CLR_RED, CLR_WHITE ) } Local aNew := {} Local lNew := .T. aDatos_origen := {} AADD( aDatos_origen, {"Ena ", "Art01", "Mod01", "200"} ) AADD( aDatos_origen, {"Dyo ", "Art02", "Mod01", "200"} ) AADD( aDatos_origen, {"Tria ", "Art03", "Mod01", "200"} ) AADD( aDatos_origen, {"Tessera ", "Art04", "Mod01", "200"} ) AADD( aDatos_origen, {"Pente ", "Art05", "Mod01", "200"} ) AADD( aDatos_origen, {"Exi ", "Art06", "Mod01", "200"} ) AADD( aDatos_origen, {"Epta ", "Art07", "Mod01", "200"} ) AADD( aDatos_origen, {"Okto ", "Art08", "Mod01", "200"} ) AADD( aDatos_origen, {"Ennea ", "Art09", "Mod01", "100"} ) AADD( aDatos_origen, {"Deka ", "Art10", "Mod02", "200"} ) AADD( aDatos_origen, {"Enteka ", "Art11", "Mod02", "200"} ) AADD( aDatos_origen, {"Dodeka ", "Art12", "Mod02", "200"} ) AADD( aDatos_origen, {"Dekatria ", "Art13", "Mod02", "200"} ) AADD( aDatos_origen, {"Dekatessera ", "Art14", "Mod02", "200"} ) AADD( aDatos_origen, {"Dekapente ", "Art15", "Mod02", "200"} ) AADD( aDatos_origen, {"Dekaexi ", "Art16", "Mod02", "200"} ) AADD( aDatos_origen, {"Dekaepta ", "Art17", "Mod02", "200"} ) AADD( aDatos_origen, {"Dekaokto ", "Art18", "Mod02", "200"} ) AADD( aNew, {"A1", "B1", .T., "D1", 1 , date() } ) AADD( aNew, {"A2", "B2", .F., "D2", 2 , date() } ) AADD( aNew, {"A3", "B3", .F., "D3", 3 , date() } ) AADD( aNew, {"A4", "B4", .T., "D4", 4 , date() } ) AADD( aNew, {"A5", "B5", .F., "D5", 5 , date() } ) AADD( aNew, {"A6", "B6", .T., "D6", 6 , date() } ) AADD( aNew, {"A7", "B7", .F., "D7", 7 , date() } ) AADD( aNew, {"A8", "B8", .T., "D8", 8 , date() } ) DEFINE TBROWSE oBrw1 ; AT 60,10 ; OF Form1 ; WIDTH 530 ; HEIGHT 340 ; FONT "Verdana" ; SIZE 9 ; GRID oBrw1:SetArray( aDatos_origen ) ADD COLUMN TO TBROWSE oBrw1 ; DATA ARRAY ELEMENT 1; TITLE "Rubro" SIZE 120 ADD COLUMN TO TBROWSE oBrw1 ; DATA ARRAY ELEMENT 2; TITLE "Articulo" SIZE 80 ADD COLUMN TO TBROWSE oBrw1 ; DATA ARRAY ELEMENT 3; TITLE "Marca" SIZE 80 ADD COLUMN TO TBROWSE oBrw1 ; DATA ARRAY ELEMENT 4; TITLE "M" SIZE 30 ; COLORS CLR_BLACK, bColor oBrw1:lNoVScroll := .t. End TBROWSE oBrw1:Refresh(.T.) @ 10,455 BUTTON Button_1 OF Form1; CAPTION "Change"; ACTION { || Change( IF( lNew, aNew, aDatos_origen ), lNew := !lNew ) }; WIDTH 80; HEIGHT 28 ; FONT "Arial" SIZE 9 RETURN Nil Function Change( aArray ) local aHead := {} local aSize := {} AEVAL( oBrw1:aColumns, {|oCol, x| AADD( aSize, oBrw1:aColSizes[x] ), AADD( aHead, oCol:cHeading ) } ) oBrw1:aColumns := {} oBrw1:aArray := {} if Len(aHead) < Len(aArray[1]) while Len(aHead) < Len(aArray[1]);aadd( aHead, "");end else while Len(aHead) > Len(aArray[1]); hb_ADel( aHead, len(aHead), .T.);end end oBrw1:SetArray( aArray, .T., aHead, aSize ) oBrw1:Reset() Return Nil [/pre2] Такой же фокус можно делать с подменой рабочей области используя ::SetDbf()

Andrey: Haz СПАСИБО ! Я глянул пример, пытался подключить свою ситуацию, не получилось. Не так ты делаешь, в смысле ты правильно делаешь, а мой подход к снаряду отличается от твоего. Буду свой пример делать, только не просто так, а жизненный, по работе. Доделаю только ещё другой и займусь.

Andrey: В SetArrayTo() делаю экспорт в Excel через &oBrw:Excel2(...) Символьные поля в Экселе появляются нормально, а цифирь нет. Как так ? Или что-то с форматом цифр не то ? Блин... Опять те же Нашёл свой комментарий в MiniGUI\SAMPLES\Advanced\Tsb_config2 [pre2] //IF aPole[nI,6] <> "N" // не использовать шаблон для числовых полей, т.к. // при печати в Excel поле будет пустое !!! // oBrw:aColumns[nJ]:cPicture := aPole[nI,4] // шаблон колонки //ENDIF[/pre2] И как тогда делать ?

Haz: Andrey пишет: И как тогда делать Не пользоваться :Excel2() Метод хоть и интересный по скорости, но на деле на короткой выгрузке теряет все преимущества. Как альтернатива можно использовать как минимум 5 способoв 1. Это просто OLE. Из минусов только скорость выгрузки. Остальные способы соизмеримы по скорости с :Excel2() 2. Тот же OLE с использованием вариантного массива 3. Выгружать через ADO 4. Писать сразу в xml формат ( Excel его прекрасно понимает) 5. Испльзовать специальную библиотеку ( есть здесь на форуме ссылка)

Andrey: Спасибо Haz !

Andrey: Пока обошёлся так (если кому интересно): При построении массива для SetArrayTo()[pre2] FOR nI := 1 To oBrw:nColCount() .... IF ValType(Eval(oBrw:aColumns[ nI ]:bData)) == "N" oBrw:aColumns[ nI ]:cDataType := 'N' // не использовать шаблон для числовых полей, oBrw:aColumns[ nI ]:cPicture := '' // т.к. при экспорте в Excel поле будет пустое !!! ELSE oBrw:aColumns[ nI ]:cPicture := aPict[ nI ] ENDIF ....[/pre2] Работает отлично ! Блин, а нельзя из Fivewin тиснуть экспорт в Эксель и прикрутить к МиниГуи ?

SergKis: Haz пишет Не пользоваться :Excel2() Если метод есть, надо что бы работал или убирать. Предложение, что бы работал Excel2 такие (в моей версии работает)[pre2] METHOD Excel2( cFile, lActivate, hProgress, cTitle, lSave, bPrintRow ) CLASS TSBrowse ... nOldCol := ::nCell Local nCntCols := ::nColCount(), oCol, ; aFntLine := array(nCntCols), ; aFntHead := array(nCntCols), ; aFntFoot := array(nCntCols) Default nInstance := 0 ... CursorWait() For i := 1 To nCntCols oCol := ::aColumns[ i ] aFntLine[ i ] := oCol:hFont aFntHead[ i ] := oCol:hFontHead aFntFoot[ i ] := oCol:hFontFoot If HB_ISBLOCK(oCol:hFont) oCol:hFont := hFont EndIf If HB_ISBLOCK(oCol:hFontHead) oCol:hFontHead := hFont EndIf If HB_ISBLOCK(oCol:hFontFoot) oCol:hFontFoot := hFont EndIf Next ::lNoPaint := .F. ... hFont := ::aColumns[ nCol ]:hFontHead If hFont != Nil aFontTmp := GetFontParam( hFont ) IF AScan( aFont, {|e| e[ 1 ] == aFontTmp[ 1 ] .and. e[ 2 ] == aFontTmp[ 2 ] .and. ; e[ 3 ] == aFontTmp[ 3 ] .and. e[ 4 ] == aFontTmp[ 4 ] .and. ; e[ 5 ] == aFontTmp[ 5 ] .and. e[ 6 ] == aFontTmp[ 6 ] } ) == 0 AAdd( aFont, aFontTmp ) endif EndIf hFont := ::aColumns[ nCol ]:hFontFoot If hFont != Nil aFontTmp := GetFontParam(hFont) IF AScan( aFont, {|e| e[ 1 ] == aFontTmp[ 1 ] .and. e[ 2 ] == aFontTmp[ 2 ] .and. ; e[ 3 ] == aFontTmp[ 3 ] .and. e[ 4 ] == aFontTmp[ 4 ] .and. ; e[ 5 ] == aFontTmp[ 5 ] .and. e[ 6 ] == aFontTmp[ 6 ] } ) == 0 AAdd( aFont, aFontTmp ) endif EndIf Next If Len( aFont ) > 4 ASize( aFont, 4 ) EndIf ... For nRow := 1 To ( ::nLen ) ... For nCol := 1 To Len( ::aColumns ) uData := If( ValType( ::aColumns[ nCol ]:cHeading ) == "B", ; Eval( ::aColumns[ nCol ]:cHeading, nCol, Self ), ; ::aColumns[ nCol ]:cHeading ) If ValType( uData ) != "C" Loop EndIf ... Next If ::lDrawFooters For nCol := 1 To Len( ::aColumns ) uData := If( ValType( ::aColumns[ nCol ]:cFooting ) == "B", ; Eval( ::aColumns[ nCol ]:cFooting, nCol, Self ), ; ::aColumns[ nCol ]:cFooting ) If ValType( uData ) != "C" uData := " " EndIf uData := Trim( StrTran( uData, CRLF, Chr( 10 ) ) ) nAlign := Min( LoWord( ::aColumns[ nCol ]:nFAlign ), 2 ) nAlign := If( Chr( 10 ) $ uData, 4, nAlign ) hFont := ::aColumns[ nCol ]:hFontFoot aFontTmp := GetFontParam( hFont ) nFont := AScan( aFont, {|e| e[ 1 ] == aFontTmp[ 1 ] .and. e[ 2 ] == aFontTmp[ 2 ] .and. ; e[ 3 ] == aFontTmp[ 3 ] .and. e[ 4 ] == aFontTmp[ 4 ] .and. ; e[ 5 ] == aFontTmp[ 5 ] .and. e[ 6 ] == aFontTmp[ 6 ] } ) FWrite( nHandle, BiffRec( 4, uData, nLine - 1, nCol - 1, .T., nAlign + 1,, ; Max( 0, nFont - 1 ) ) ) If hProgress != Nil If nCount % nEvery == 0 SendMessage(hProgress, PBM_SETPOS, nCount, 0) EndIf nCount ++ EndIf Next ++nLine EndIf FWrite( nHandle, BiffRec( 10 ) ) FClose( nHandle ) For i := 1 To nCntCols oCol := ::aColumns[ i ] oCol:hFont := aFntLine [ i ] oCol:hFontHead := aFntHead [ i ] oCol:hFontFoot := aFntFoot [ i ] Next If hProgress != Nil SendMessage(hProgress, PBM_SETPOS, nTotal, 0) EndIf ... [/pre2]

Haz: SergKis пишет: метод есть, надо что бы работал Сергей, метод работает. Я о том что просто не пользуюсь им. т. к бровс у меня всегда по базе, то выгружаю из базы а не из бровс объекта. Для прямой выгрузки идеально подходит ADO, и быстро и с названием колонок русскими словами. Для отчёта в Excel Оля с вариантным массивам и быстро и красоту навести можно.

Andrey: Haz пишет: Для отчёта в Excel Оля с вариантным массивам и быстро и красоту навести можно. Что то я сомневаюсь что быстро написать можно... Быстро не у всех получается. Может класс такой в исходники добавить можно ? Это было бы хорошее подспорье для всех. Как правило отчёты бывают небольшие через SetArrayTo(), Оля с ними быстро справиться.

Andrey: SergKis пишет: Предложение, что бы работал Excel2 такие (в моей версии работает) Я за добавление этого в исходники ! Григорий, посмотри это пожалуйста.



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