IPB
ЛогинПароль:

> ВНИМАНИЕ!

Прежде чем задать вопрос, смотрите FAQ.
Рекомендуем загрузить DRKB.

Наладить общение поможет, если вы подпишитесь по почте на новые темы в этом форуме.

3 страниц V  1 2 3 >  
 Ответить  Открыть новую тему 
> повторяющиеся данные в dbgrid - ?
сообщение
Сообщение #1


Бывалый
***

Группа: Пользователи
Сообщений: 205
Пол: Мужской
Реальное имя: Евгений

Репутация: -  0  +


Подскажите пожалуйста, как можно сделать с помощью фильтра, чтобы при вводе в dbedit, например номера 128-ас, и если такой же номер уже есть в gride, то указывалось что этот номер уже существует?
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #2


Гость






Проверяй наличие введенного значения в БД по событию OnExit (используя Locate или Lookup):
procedure TForm1.DBEdit2Exit(Sender: TObject);
var myDbE: TDbEdit;
begin
myDbE := (Sender as TDbEdit);
if myDbE.DataSource.DataSet.Locate('txt', myDbE.Text, []) then begin
ShowMessage('Already exists');
// тут - дополнтельные действия, например, очистка Text
end;
end;
 К началу страницы 
+ Ответить 
сообщение
Сообщение #3


Бывалый
***

Группа: Пользователи
Сообщений: 205
Пол: Мужской
Реальное имя: Евгений

Репутация: -  0  +


при выходе из dbedita, данные заносятся в grid. таким образом получается что они уже там были и выдается сообщение что запись уже существует
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #4


Гость






Цитата
при выходе из dbedita, данные заносятся в grid
Ага, особенно если при выходе ты проверишь и удалишь повторяющееся данное из DBEdit-а, правда? Ты комментарии в коде никогда не читаешь?
 К началу страницы 
+ Ответить 
сообщение
Сообщение #5


Гость






Кстати, самый правильный вариант решения этой задачи - возложить подобную проверку на саму БД, то есть в базе нужное тебе поле сделать индексируемым и уникальным, тогда при попытке продублировать его значение будет выброшено исключение EDatabaseError, по которому система тебе сообщит об ошибке, или ты можешь подменить системное сообщение (и принять решение, что делать после ошибки - через переменную Action) в методе OnPostError для AdoTable.
 К началу страницы 
+ Ответить 
сообщение
Сообщение #6


Бывалый
***

Группа: Пользователи
Сообщений: 205
Пол: Мужской
Реальное имя: Евгений

Репутация: -  0  +


С индексируемым полем здесь как раз и не получится потому что в ячейке может быть:
135,557,437р
а вводится например 557. Так база не покажет что набранный элемент существует среди других
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #7


Гость






Цитата
С индексируемым полем здесь как раз и не получится потому что в ячейке может быть:
135,557,437р
а вводится например 557.
Так тебе НИКТО не покажет, что такое значение уже есть. Телепаты - в отпуске. Я тестировал на обычном текстовом поле, на ПОЛНОЕ совпадение.
 К началу страницы 
+ Ответить 
сообщение
Сообщение #8


Бывалый
***

Группа: Пользователи
Сообщений: 205
Пол: Мужской
Реальное имя: Евгений

Репутация: -  0  +


Понятно.. может быть можно как нибудь таким образом- не полное соответствие, а '[text] LIKE *' + Form1.dbEdit1.Text + '*'; ?
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #9


Гость






И чего тебе это даст? Вот в таком случае, например: есть запись "135,557,437р", а вводится 55. Неполное соответствие найдено, но оно тебе на фиг не нужно. Тут надо совсем по-другому. Я бы например, делал список (StringList какой-нибудь) всех значений, записанных в этом поле (во всех записях), а потом, при вводе в DBEdit, проверял бы на наличие введенного значения в этом списке.

Ты мне другое скажи. Зачем тебе понадобилось делать такие финты (т.е., записывать через запятую значения)? Что, без этого обойтись нельзя было?

Еще один вопрос: вводимое тобой в DBEdit значение гарантированно не будет содержать запятые? То есть, двойные/тройные и так далее значения вводится не будут? Как же ты тогда те, первые, через запятую вводишь? А если понадобится подредактировать?
 К началу страницы 
+ Ответить 
сообщение
Сообщение #10


Бывалый
***

Группа: Пользователи
Сообщений: 205
Пол: Мужской
Реальное имя: Евгений

Репутация: -  0  +


Просто с запятыми удобнее всего было в одну ячейку вводить все необходимые значения через запятую. Что тут можно еще придумать?
Вводимое в DBEdit значение в большинстве случаев будет содержать запятую, т.е. будут двойные, тройные и тд значения. Получается в данном случае единственный вариант-проверять значения между запятыми?
Я просто объяснил непонятно... Допустим что в строчке значений, указанных через запятую при вводе в DBEdit, одно из них совпадает со значением, также возможно указанным через запятую которое уже существует в таблице. В этом случае и выдается ошибка

Сообщение отредактировано: 1147 -
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #11


Гость






Ну, смотри, чего я наваял:
1) в классе формы есть
  private
{ Private declarations }
SL: TStringList;
, который создается и уничтожается в OnCreate/OnDestroy формы, а заполняется - в OnShow:
procedure TForm1.FormCreate(Sender: TObject);
begin
SL := TStringList.Create;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
SL.Free;
end;

procedure TForm1.FormShow(Sender: TObject);
var s: string;
begin
ADOTable1.First;
while not ADOTable1.Eof do begin
s := s + ',' + ADOTable1.FieldByName('txt').AsString;
ADOTable1.Next;
end;

SL.Duplicates := dupIgnore;
SL.Delimiter := ',';
SL.DelimitedText := s;
end;

2) ну заполнить-то мы StringList заполнили, теперь надо проверять содержимое DBEdit-а после заполнения. Будем делать это в OnBeforePost таблицы:
procedure TForm1.ADOTable1BeforePost(DataSet: TDataSet);
var
dbSL: TStringList;
i: integer;
isOK: boolean;
begin
dbSL := TStringList.Create;
dbSL.Delimiter := ',';
dbSL.DelimitedText := DBEdit2.Text; // разбили содержимое DBEdit-а на составляющие

isOK := true;
for i := 0 to dbSL.Count - 1 do begin
if SL.IndexOf(dbSL.Strings[i]) > -1 then isOk := false;
end; // проверяем, встречается ли в SL хоть одна из этих составляющих

if isOK then begin
// нет, не встретилась, ошибки не будет, добавляем новые значения в список
for i := 0 to dbSL.Count - 1 do begin
SL.Add(dbSL.Strings[i]);
end;
end
else begin
// ага !!! что-то повторяется !!! сообщаем и откатываем обновление записи ...
ShowMessage('Duplicate value detected !!!');
DataSet.Cancel;
Abort;
end;
dbSL.Free;
end;
Больше пока ничего в голову не пришло.
 К началу страницы 
+ Ответить 
сообщение
Сообщение #12


Бывалый
***

Группа: Пользователи
Сообщений: 205
Пол: Мужской
Реальное имя: Евгений

Репутация: -  0  +


Все работает замечательно.
1 вопрос: когда обнаруживается совпадение, можно ли сделать так чтобы вместо того чтобы сообщать об этом, программа показала это совпадение?
Например так: label1.caption:=совпадение
Если я правильно понял, в приведенном выше коде совпадающий фрагмент никак не обозначается?

Сообщение отредактировано: 1147 -
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #13


Гость






Цитата
в приведенном выше коде совпадающий фрагмент никак не обозначается?
Нет, но обозначить - не проблема:
procedure TForm1.ADOTable1BeforePost(DataSet: TDataSet);
var
dbSL: TStringList;
i: integer;
isOK: boolean;
begin
dbSL := TStringList.Create;
dbSL.Delimiter := ',';
dbSL.DelimitedText := DBEdit2.Text; // разбили содержимое DBEdit-а на составляющие
isOK := true;

Label1.Caption := ''; // ******
for i := 0 to dbSL.Count - 1 do begin
if SL.IndexOf(dbSL.Strings[i]) > -1 then begin
isOk := false; Label1.Caption := Label1.Caption + dbSL.Strings[i] + ' | '; // ******
end;
end; // проверяем, встречается ли в SL хоть одна из этих составляющих
if isOK then begin
// нет, не встретилась, ошибки не будет, добавляем новые значения в список
for i := 0 to dbSL.Count - 1 do begin
SL.Add(dbSL.Strings[i]);
end;
end
else begin
// ага !!! что-то повторяется !!! сообщаем и откатываем обновление записи ...
ShowMessage('Duplicate value detected !!!');
DataSet.Cancel;
Abort;
end;
dbSL.Free;
end;

По-моему, должно сработать. Не проверял, исправил прямо здесь, потестируй. Должно в случае совпадения выбрасывать в Label1 все повторно введенные значения.
 К началу страницы 
+ Ответить 
сообщение
Сообщение #14


Бывалый
***

Группа: Пользователи
Сообщений: 205
Пол: Мужской
Реальное имя: Евгений

Репутация: -  0  +


Да, повторно введенные значения появляются в Label1 таким образом: 1,1, (если заменить | на ,). Это нужно для того чтобы по этим значениям отфильтровать совпадающую и введенную строку в БД. Но при фильтрации возникает ошибка: "Класс не существует". В общем похоже я не самый удачный вариант выбрал.
Нужно чтобы после ввода повторяющегося (ихся) значений, была показана строка (строки) ее (их) содержащая. Мой вариант с фильтром не подошел. Может есть другой способ?
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #15


Гость






Запрос на фильтрацию правильно составь... Вот это у меня только что отработало (при вводе заведомо повторяющихся данных отфильтровало все строки, кроме тех, в которых они присутствуют):
procedure TForm1.ADOTable1BeforePost(DataSet: TDataSet);
var
dbSL, findSL: TStringList;
i: integer;
isOK: boolean;
filterStr: string;
const
ORstr: array[boolean] of string = (' OR ', '');
begin
dbSL := TStringList.Create;
dbSL.Delimiter := ',';
dbSL.DelimitedText := DBEdit2.Text;

findSL := TStringList.Create;
findSL.Duplicates := dupIgnore;

isOK := true;
for i := 0 to dbSL.Count - 1 do begin
if SL.IndexOf(dbSL.Strings[i]) > -1 then begin
isOk := false;
findSL.Add(dbSL.Strings[i]); // Дубликаты игнорируются
end;
end;

if isOK then begin
for i := 0 to dbSL.Count - 1 do begin
SL.Add(dbSL.Strings[i]);
end;
end
else begin
filterStr := '';
for i := 0 to findSL.Count - 1 do begin
filterStr := filterStr + ORstr[i = 0] +
'([txt] LIKE *' + findSL.Strings[i] + '*) ';
end;
DataSet.Cancel;

ADOTable1.Filtered := False;
ADOTable1.Filter := filterStr;
ADOTable1.Filtered := True;

Abort;

end;
dbSL.Free;
end;
Не забудь потом еще удалить FindSL...
 К началу страницы 
+ Ответить 
сообщение
Сообщение #16


Бывалый
***

Группа: Пользователи
Сообщений: 205
Пол: Мужской
Реальное имя: Евгений

Репутация: -  0  +


добавил в конце findsl.free; но похоже не правильно т.к. возникает ошибка: невозможно найти объект в семействе соответствующий требуемуму имени...
Как правильно удалить FindSL? Или может ошибка по другой причине..
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #17


Гость






Эта ошибка не связана с findSL. Что-то там у тебя в проекте не так. Можно посмотреть скриншот этой ошибки, и куда вываливается? Для того чтобы корректно удалить оба созданных StringList-а, достаточно обернуть все в try ... finally ... end:


Добавлено через 16 мин.
Хм... Меня терзают смутные сомнения... У тебя в этой самой таблице вычисляемых полей нету? Вполне возможно, что отсюда и такая ошибка. Ты пробовал просто, по нажатию кнопки фильтровать данные (уже с вычисляемыми полями, я имею в виду)? Работает?


Прикрепленные файлы
Прикрепленный файл  code.pas ( 1.14 килобайт ) Кол-во скачиваний: 198
 К началу страницы 
+ Ответить 
сообщение
Сообщение #18


Бывалый
***

Группа: Пользователи
Сообщений: 205
Пол: Мужской
Реальное имя: Евгений

Репутация: -  0  +


Ошибка появляется при нажатии кнопки с кодом:
if form5.adotable1.Modified then
form5.adotable1.Post;

Вычисляемые поля есть. Но фильтрация прекрасно производится по трем разным параметрам без каких-либо ошибок

Сообщение отредактировано: 1147 -


Эскизы прикрепленных изображений
Прикрепленное изображение
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #19


Гость






Слушай, а у тебя поле тоже txt называется? Или может ты просто забыл сменить название поля на свое? Я сейчас попробовал изменить здесь:
    for i := 0 to findSL.Count - 1 do begin
filterStr := filterStr + ORstr[i = 0] +
'([myTxt] LIKE *' + findSL.Strings[i] + '*) '; // <--- название поля на заведомо неверное
end;
- так тут же схватил такую же ошибку. Проверь.
 К началу страницы 
+ Ответить 
сообщение
Сообщение #20


Бывалый
***

Группа: Пользователи
Сообщений: 205
Пол: Мужской
Реальное имя: Евгений

Репутация: -  0  +


Совершенно верно good.gif Ошибка возникала по этой причине! Я обратил внимание на [text], но решил что здесь имеется ввиду текст как в findSL.Strings[i]
Все замечательно работает, спасибо!
Если можно, сразу еще 1 вопрос, тоже по совпадению данных в ячейках:
В столбце DBGrig могут появляться одинаковые значения (например Иванов встречается 5 раз в разных ячейках одного столбца, а может встречаться Сидоров 9 раз и тд). Есть кнопка которая должна при нажатии отфильтровывать эти повторяющиеся фамилии. Т.е. после нажатия, в DBGrid остаются только строки где есть несколько Ивановых, Петровых, в общем любая повторяющаяся фамилия.
Сложность в том что фильтр невозможно заранее задать каким-то определенным значением т.к. мы не знаем какая именно фамилия будет повторяться. Программа как бы сама обнаруживает, есть ли повторения, и если есть, выдает эти строки
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 

3 страниц V  1 2 3 >
 Ответить  Открыть новую тему 
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 





- Текстовая версия 3.12.2020 7:16
500Gb HDD, 6Gb RAM, 2 Cores, 7 EUR в месяц — такие хостинги правда бывают
Связь с администрацией: bu_gen в домене octagram.name