Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

как найти и подсветить компоненты


Страницы:   1 2 3

Александр_2012 ©   (2013-02-04 16:18:00) 

Доброго дня.
Задача: есть компонент PageControl, на нескольких страницах которого расположены компоненты DBEdit. Программа проверяет логику заполнения (зависимости между различными полями БД) и выводит сообщения в Memo обо всех несоответствиях. Есть StringList куда прописываются наименования полей, в которых допущена ошибка в логике заполнения. Это всё работает. Хотелось бы при двойном щелчке на сообщении в Memo чтобы производился поиск по всем страницам PageControl компонентов DBEdit, которые относятся к полям неправильно заполненным (с нарушением логики заполнения) и чтобы эти компоненты были подсвечены, например цветом шрифта, чтобы пользователь сразу мог определить где сделана ошибка. Не могу сообразить как это сделать, но уверен, что вполне возможно.


Александр_2012   (2013-02-07 16:22:00) [21]


> KilkennyCat ©   (07.02.13 16:06) [26]
>
> > Событие OnChange будет происходить при каждом изменении
>
> > значения вводимого в DBEdit, т.е., если мне надо ввести
>
> > 12345, событие произойдёт 5 раз
>
>
> оно в любом случае происходит, даже если ты в обработчике
> ничего не напишешь.


Это я понимаю, но если при каждом нажатии будет выполняться порядка 60 SQL-запросов... У меня проверка происходит один раз на BeforePost и то комп задумывается примерно на 0,5 секунды. В базе есть поля 10-значные - это что ж ввод поля будет затягиваться на 50-60 секунд?


sniknik   (2013-02-07 16:20:00) [22]

> ну, это вообще то можно представить/может быть но
вообще, если это критично. что одно от другого зависит то проверка должна идти на сервере, либо база локальная (а тогда проблем с пере запросами на каждую нажатую кнопку не должно быть).


sniknik   (2013-02-07 16:17:00) [23]

> Так вся информация для проверки есть же в контролах.
она должна быть в контрролах, иначе что то не так в "консерватории", оно получается либо частями пишется, либо зависит от ранее введенного. ... ну, это вообще то можно представить/может быть но, вот прямо тут, такой случай? из какого поста это можно прочитать?

если боятся "онченжа"  можно добавить свое событие, и посылать его броадкастом (хотя тут придется перебрать все панельки/формы на которых компоненты разбросаны, ну или придумать "аналог" инициирующийся рекордсетом... но это уже сложновато получается ).


KilkennyCat   (2013-02-07 16:06:00) [24]


> Событие OnChange будет происходить при каждом изменении
> значения вводимого в DBEdit, т.е., если мне надо ввести
> 12345, событие произойдёт 5 раз


оно в любом случае происходит, даже если ты в обработчике ничего не напишешь.


Inovet   (2013-02-07 15:49:00) [25]

> [22] Александр_2012   (07.02.13 14:27)
> выдать сообщение об ошибке и вернуть фокус ввода

Так можно в клинч войти.

> [22] Александр_2012   (07.02.13 14:27)
> осуществлять проверку с помощью SQL-запросов на BeforePost,

Так вся информация для проверки есть же в контролах. Или уже нет и часть сохранена в БД?


Александр_2012   (2013-02-07 15:47:00) [26]


> > зависимости могут быть не только между двумя полями, но
> и пятью и десятью.
> так это же замечательно, меняешь одно и сразу видишь сломанную
> "цепочку" от этих действий.


Что ж... Звучит неплохо. У меня порядка 60 вариантов проверок зависимостей между полями в виде SQL-запросов. Т.е. при каждом нажатии (при вводе данных) будут прогоняться эти 60 запросов? И потом, я к сожалению, не очень представляю принципы работы компонентов, но обращаться SQL-запросом к БД, если не отрабатывается Post мне кажется бессмысленным, т.к. в БД находятся старые данные или ещё пустые данные - как тут проверить? (или я ошибаюсь?)


sniknik   (2013-02-07 15:27:00) [27]

> при каждом изменении значения вводимого в DBEdit
и что? экономишь компьютерные тики? нет проблем сделать 2...2000 раз, если это не тормозит (не в тиках, а чтобы на глаз заметно) процесс (а в случае ручного ввода основной "тормоз" перед монитором, даже если комп из прошлого века...)

> то на вводе 1 получит сообщение об ошибке (на OnChange). Хорошо ли это?
у меня нет сообщения, у меня если неправильно меняется фон.

> зависимости могут быть не только между двумя полями, но и пятью и десятью.
так это же замечательно, меняешь одно и сразу видишь сломанную "цепочку" от этих действий.

> поэтому даже ошибочная информация сохраняется
проверка это не сохранение, про него речи пока не было, ничто не мешает и в "моем" варианте сохранить не взирая на "глючноввод".

> то объясните свою логику.
проверять и отображать результат проверки сразу, не откладывая в "Memo" (нет Memo можно оставить, и даже продолжать писать туда на выходе из компонент, как "хистори" пойдет)


Александр_2012   (2013-02-07 14:27:00) [28]


> sniknik ©   (04.02.13 18:18) [11]
> другое условие, для понимания...
procedure TForm1.DBEdit25Change(Sender:
>  TObject);begin  with TDBEdit(Sender) do    if Field.FieldName
> = 'TOVAR'      then Color:= clRed      else Color:= clWindow;
> end;


Уважаемый sniknik ©. Вы пишите, что предложили заведомо лучшее решение. Я действительно хочу его понять...
Событие OnChange будет происходить при каждом изменении значения вводимого в DBEdit, т.е., если мне надо ввести 12345, событие произойдёт 5 раз. На OnChange возможно ввести проверку на допустимость вводимого значения кодификатору, но разумно ли это? Сделав проверку на OnExit, можно обойтись однократной проверкой и, если надо, выдать сообщение об ошибке и вернуть фокус ввода. Так сделано у меня. Затем, если в кодификаторе есть, например значение 12 и пользователь начинает его вводить, то на вводе 1 получит сообщение об ошибке (на OnChange). Хорошо ли это? Проверять на допустимость заполнения конкретным значением одного поля, при условии, что другое поле получило определённое значение на OnChange вообще бессмысленно, а если одно из полей ещё не заполнено? Добавить проверку на ноль или null? А ведь, как я уже писал, зависимости могут быть не только между двумя полями, но и пятью и десятью. Я думаю, что в этом случае наиболее простое решение осуществлять проверку с помощью SQL-запросов на BeforePost, что и сделано у меня. Все сообщения об ошибках выводятся на отдельную форму в Memo. Задача у меня полностью работает. Хотелось просто облегчить жизнь пользователей, чтобы щёлкнув дважды на сообщении об ошибке они получили на основной форме подсвеченные DBEdit ы, которые к этой ошибке относятся, чтобы пользователь мог посмотреть не его ли это ошибка (вбил не то или не туда). И ещё, данные в БД вводятся с бумажных носителей и тот, кто их заполнял тоже человек и мог ошибиться, поэтому даже ошибочная информация сохраняется, а предоставивший бумажный носитель предупреждается о необходимости исправления, т.к. оператор просто вводит и не может знать, что реально должно быть заведено.


> например мне пофигу теперь на этот код, когда я уже привел
> пример лучший (ИМХО)... по логике


Если Вам будет несложно, то объясните свою логику.


Александр_2012   (2013-02-07 12:06:00) [29]


> Кщд   (07.02.13 09:58) [19]
> >Александр_2021   (06.02.13 22:46) [17]
> ОФОМС или страховая?
> <Цитата>


Не относимся ни к тем ни к другим. И там пользуются обычно программами, написанными профессиональными программистами.


sniknik   (2013-02-07 10:42:00) [30]

>> Привёл код и тишина...
> у людей (в т.ч. программистов) есть свои дела
мало того, программисты тоже люди... со своими "бзиками".

например мне пофигу теперь на этот код, когда я уже привел пример лучший (ИМХО)... по логике, не по "копипастовскому" признаку.
и ожидаю его развития, а не продолжения от автора "бодания запертых ворот". ну вот нафига? когда есть открытые. хочешь назначать со стороны? да без проблем сделай массив/набор из порядковых номеров или названий полей "неправильных" назначь "со стороны" а проверяй  вхождение в самом компоненте (инициировать событие онченж элементарно, например просто вызвав функцию поиска чтобы найти текущую же запись). элементарно. никакого поиска... оно и не терялось чтобы искать.
вот показал бы его раньше, сказал что с ним не так (сейчас и этого нет) можно было бы обсудить, или можно было бы обсудить почему "мой" метод автору не подходит, причина, если она адекватная. а также почему свой вариант автору кажется более правильным тоже можно было поговорить. а так, нет, не охота.


Кщд   (2013-02-07 09:58:00) [31]

>Александр_2021   (06.02.13 22:46) [17]
ОФОМС или страховая?


anonimus   (2013-02-07 09:00:00) [32]


> Привёл код и тишина...

у людей (в т.ч. программистов) есть свои дела

FindComponent F1

> Indicates whether a given component is ownedby the
> component.

Искать надо там где они есть(на нужной форме)!
See AlsoComponents[]

> Lists all components owned by the component.


>  for j:=1 to 247 do // у меня 247 полей привязанных к DBEdit

А если нумерация будет сбита? (добавили 5-ый , потом удалили 2-ой).

> // и как программно определить сколько DBEdit-ов использовано
> в программе вместо того чтобы жестко задавать 247?


See AlsoСomponents

> Indicates the number of components owned by the component.
>

>


Александр_2021   (2013-02-06 22:46:00) [33]


> > Или не поняли меня.
> тебя невозможно понять, ты словами говоришь. понять можно
> код. (слова это куча разных реализаций в итоге делающих
> одно и тоже)
>


Привёл код и тишина...


Александр_2012   (2013-02-06 12:50:00) [34]

Доброго дня.

Конструкция DM.DataQ.FieldByName(masst.Strings[0]).FocusControl,
которую посоветовал Игорь Шевченко, работает, но у меня в masst находится список полей, где возможны ошибки заполнения, а данная конструкция обращается к одному полю (я специально указал Strings[0]), причём фокус я на нём получаю, а вот как его подсветить и, опять же фокус будет передан только в том случае, если PageControl открыт на нужной странице, т.е. где расположен нужный DBEdit.

В качестве пробы я создал простой проект состоящий из PageControl с двумя страницами, на которые набросал несколько DBEdit, компоненты Odac. кнопку и написал такой код

procedure TForm1.Button1Click(Sender: TObject);
var
i: integer;
begin
for i:=1 to OraQuery1.FieldCount do
 if TDBEdit(FindComponent(‘DBEdit’+IntToStr(i))).DataField=’TOVAR’ then
    TDBEdit(FindComponent(‘DBEdit’+IntToStr(i))).Color:=clRed;
end;

Работает на ура. Нужный DBEdit подсвечивается на какой бы странице он не находился. Но в свою программу вставить его не удаётся, т.к. в ней компоненты Odac находятся на DataModule, Memo, куда выводятся сообщения об ошибках на отдельной форме (InForm), DBEditы находятся на основной (mainForm) форме.
Memo заполняется так:

procedure TDM.DataQBeforePost(DataSet: TDataSet);
var
flgerr: boolean;
begin
flgerr:=False;
InForm.Memo1.Clear;
with DM.LUS do //здесь находятся запросы и сообщения, для проверки логики заполнения
 begin
 Close;
 SQL.Clear;
 SQL.Add('select lus, mess from fulllus');
 Open;
 end;
while not DM.LUS.Eof do
 begin
 with DM.Help1 do
   begin
   Close;
   SQL.Clear;
   SQL.Add('select pole1, pole2, pole3 from edds.v_k99');
   SQL.Add('where id='+DM.DataQ.FieldByName('id').AsString);
   SQL.Add(' and '+DM.LUS.FieldByName('lus').AsString);
   try
   Open;
   except
ShowMessage('Ошибка'+#13+SQL.Text+#13+#13+'ЛУС'+#13+DM.LUS.FieldByName('mess').AsString);
   exit;
   end; //try
   end; //with
 if DM.Help1.RecordCount>0 then
   begin
   flgerr:=True;
   InForm.Memo1.Lines.Add('*** '+DM.LUS.FieldByName('mess').AsString+' ***');
   InForm.Memo1.Lines.Add('');
   end;
 DM.LUS.Next;
 end;
InForm.Show;
if flgerr then Abort;
end;

procedure TInForm.Memo1DblClick(Sender: TObject);
var
st, buf: string;
i,j: integer;
masst: TStringList;
masnpol: TStringList;
begin
masst:=TStringList.Create;
masnpol:=TStringList.Create;
with DM.LUS do
 begin
 Close;
 SQL.Clear;
 SQL.Add('select * from tavary');
 SQL.Add('where 2<1');
 Open;
 end;
for i:=0 to DM.LUS.FieldCount-1 do
 masnpol.Add(DM.LUS.Fields[i].FieldName);
st:=Memo1.Lines[Memo1.CaretPos.Y];
Delete(st,1,4); // удаляю лишние символы в начале и в конце сообщения
Delete(st,Length(st)-3,4);
with DM.LUS do
 begin
 Close;
 SQL.Clear;
 SQL.Add('select lus from fulllus');
 SQL.Add('where mess='''+st+'''');
 Open;
 end;
st:=DM.LUS.FieldByName('lus').AsString;
for i:=0 to length(st) do
 if st[i] in ['(',')','=','>','<'] then
   st[i]:=' ';
repeat
st:=Trim(st);
if st<>'' then
 begin
 if Pos(' ', st)>0 then
   begin
   buf:=UpperCase(Copy(st, 1, Pos(' ', st)-1));
   delete(st,1,Pos(' ', st)-1);
   end
 else
   begin
   buf:=st;
   st:='';
   end;
 if (masnpol.IndexOf(buf)<>-1) and (masst.IndexOf(buf)=-1) then
   masst.Add(buf);
 end;
until st='';
for i:=0 to masst.Count-1 do
 for j:=1 to 247 do // у меня 247 полей привязанных к DBEdit
// вот как это изменить???, чтобы работало
 if TDBEdit(FindComponent(‘DBEdit’+IntToStr(j))).DataField=masst[i] then
    TDBEdit(FindComponent(‘DBEdit’+IntToStr(j))).Color:=clRed;
// и как программно определить сколько DBEdit-ов использовано в программе вместо того чтобы жестко задавать 247?

masst.Free;
masnpol.Free;
end;

Планировалось, что двойной щелчок на строке Memo1 подсветит все связанные между собой поля по одной ошибке заполнения, двойные щелчки по следующим строкам соответственно подсветит все связанные между собой поля по другим ошибкам заполнения.


Германн   (2013-02-05 01:58:00) [35]


> Программа проверяет логику заполнения (зависимости между
> различными полями БД) и выводит сообщения в Memo обо всех
> несоответствиях. Есть StringList куда прописываются наименования
> полей, в которых допущена ошибка в логике заполнения. Это
> всё работает. Хотелось бы при двойном щелчке на сообщении
> в Memo

Memo надо заменить на что-нибудь более подходящее. Желательно такое, где каждое сообщение было бы отдельной строкой. TListBox, TListView etc.
А дополнительный StringList куда прописываются, имхо вообще лишний.


KilkennyCat   (2013-02-04 23:48:00) [36]


> Поэтому оператор получив сообщение типа "данный товар не
> может иметь указанный артикул" вынужден брать бумажный вариант
> формы и искать какому полям (DBEdit) соответствует данное
> сообщение


странная логика. напоминает некоторые вебформы, которые заполняешь, заполняешь, потом код, потом еще, а потом сообщает что в самом начале неправильно.
не лучше ли проверять сразу?

ну а так -  пример Sniknika


Dennis I. Komarov   (2013-02-04 22:24:00) [37]

Храни массив ссылок на объекты, номер однозначно соответствует строке из Мемо... (а лучше TListView)


Inovet   (2013-02-04 19:57:00) [38]

> [8] Александр_2012   (04.02.13 17:32)
> о допустимых значениях одного поля, если другое приняло
> определённое значение.
...
> Мне нужно программным путём найти компонент (или компоненты)
> типа DBEdit


procedure TForm1.DataSet1BeforePost(DataSet: TDataSet);
begin
 if (DataSet1Field1.AsInteger = 1) and (DataSet1Field2.AsString <> 'a') then
 begin
   DBEdit1.Color:= clRed;
   DBEdit2.Color:= clRed;
 end
 else
 begin
   DBEdit1.Color:= clWindow;
   DBEdit2.Color:= clWindow;
 end;
end;

Или, как ты хочешь, в цикле

for i = 0 to ControlsCount - 1 do

проверяй принадлежность Controls[i] к TDBEdit потом проверяй подключен ли он к нужному полю и меняй цвет. Но зачем так сложно, если контролы и так тебе и так известны?


sniknik   (2013-02-04 18:18:00) [39]

другое условие, для понимания...
procedure TForm1.DBEdit 25Change(Sender: TObject);
begin
 with TDBEdit(Sender) do
   if Field.FieldName = 'TOVAR'
     then Color:= clRed
     else Color:= clWindow;
end;


sniknik   (2013-02-04 18:14:00) [40]

> Я, наверное, не понял кода.
а ты еще немного "повтыкай на код".

> Или не поняли меня.
тебя невозможно понять, ты словами говоришь. понять можно код. (слова это куча разных реализаций в итоге делающих одно и тоже)

> Проверка на допустимость диапазонов
здесь диапазон не важен (ну какое то условие нужно же было ставить), а идея примера в том что искать не надо... один обработчик на все, и проверяй там что угодно и как угодно, хочешь диапазоны, хочешь имя, а хочешь доп запросами (хотя это и накладно будет, проще один раз запросить, а после проверять в результате)


Страницы:   1 2 3

Наверх

Титульная страница Поиск, карта сайта Написать письмо