Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Форум «Всё о Паскале» _ Делфи _ повторяющиеся данные в dbgrid - ?

Автор: 1147 20.07.2009 4:00

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

Автор: volvo 20.07.2009 4:43

Проверяй наличие введенного значения в БД по событию 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;

Автор: 1147 20.07.2009 5:28

при выходе из dbedita, данные заносятся в grid. таким образом получается что они уже там были и выдается сообщение что запись уже существует

Автор: volvo 20.07.2009 16:12

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

Автор: volvo 20.07.2009 22:44

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

Автор: 1147 20.07.2009 23:46

С индексируемым полем здесь как раз и не получится потому что в ячейке может быть:
135,557,437р
а вводится например 557. Так база не покажет что набранный элемент существует среди других

Автор: volvo 20.07.2009 23:55

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

Автор: 1147 21.07.2009 0:43

Понятно.. может быть можно как нибудь таким образом- не полное соответствие, а '[text] LIKE *' + Form1.dbEdit1.Text + '*'; ?

Автор: volvo 21.07.2009 0:59

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

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

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

Автор: 1147 21.07.2009 2:56

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

Автор: volvo 21.07.2009 4:45

Ну, смотри, чего я наваял:
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;
Больше пока ничего в голову не пришло.

Автор: 1147 2.08.2009 21:11

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

Автор: volvo 2.08.2009 21:45

Цитата
в приведенном выше коде совпадающий фрагмент никак не обозначается?
Нет, но обозначить - не проблема:
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 все повторно введенные значения.

Автор: 1147 2.08.2009 22:21

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

Автор: volvo 2.08.2009 22:59

Запрос на фильтрацию правильно составь... Вот это у меня только что отработало (при вводе заведомо повторяющихся данных отфильтровало все строки, кроме тех, в которых они присутствуют):

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...

Автор: 1147 3.08.2009 0:21

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

Автор: volvo 3.08.2009 0:37

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


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


Прикрепленные файлы
Прикрепленный файл  code.pas ( 1.14 килобайт ) Кол-во скачиваний: 314

Автор: 1147 3.08.2009 0:54

Ошибка появляется при нажатии кнопки с кодом:

if form5.adotable1.Modified then
form5.adotable1.Post;

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


Эскизы прикрепленных изображений
Прикрепленное изображение

Автор: volvo 3.08.2009 1:16

Слушай, а у тебя поле тоже txt называется? Или может ты просто забыл сменить название поля на свое? Я сейчас попробовал изменить здесь:

    for i := 0 to findSL.Count - 1 do begin
filterStr := filterStr + ORstr[i = 0] +
'([myTxt] LIKE *' + findSL.Strings[i] + '*) '; // <--- название поля на заведомо неверное
end;
- так тут же схватил такую же ошибку. Проверь.

Автор: 1147 3.08.2009 1:27

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

Автор: volvo 3.08.2009 2:39

Цитата
Программа как бы сама обнаруживает, есть ли повторения, и если есть, выдает эти строки
ADOQuery в помощь:
// настроишь AdoQuery1 в Design-е: Connection + DataSource
procedure TForm1.ButtonDuplicatedClick(Sender: TObject);
begin
with AdoQuery1 do
begin
SQL.Text :=
' SELECT Table1.index' + // Index у меня - это поле, дубликаты которого надо найти
' FROM Table1' +
' GROUP BY Table1.index' +
' HAVING (((Count(Table1.index))>1));';
Open;
while not EOF do
begin
memo1.lines.add(FieldByName('index').AsString); // для поверки - пишу найденные значения в Memo
// вместо этого можешь сразу заполнять строку для фильтрации
Next;
end;
close;
end;

// Ну, а тут - уже фильтрация
end;
Хотя, по-моему, твою программу надо полностью переделать, и она будет гораздо проще. Ты все делаешь вручную, не пользуясь никакими средствами работы с БД. Оно тебе надо? smile.gif

Автор: 1147 3.08.2009 5:31

Вынужден вернуться к первому вопросу( Обнаружились ошибки в процессе работы: при вводе данных в таблицу, все пропадает, при нажатии сохранить, опять же все пропадает, курсор прыгает на другую строку. Вот такие вот симптомы..

Значит тут все дело в том что при перемещении по таблице, данные оттуда попадают в DBEdit, отсюда путаница.
Поставил для проверки на событие OnKeyPress DBGrida -DBEdit2.clear; Прежнее противоречие изчезло, но стали пропадать данные из другого столбца.
Как бы по-другому избавить DBEdit от отображения данных во время перемещения по таблице? Похоже это единственное решение проблемы...

Автор: volvo 3.08.2009 16:26

Все, мои телепатические способности иссякли, я не знаю, что с чем ты там связывал, что на что устанавливал, и как это все взаимодействует. Хочешь - высылай проект или сюда или volvo71@gmail.com вместе с ТЗ, тогда возможно что-то и получится. А так - я делаю, проверяю на своей базе, а у тебя не работает, потому что понавешано еще сторонних обработчиков море, которые конфликтуют между собой. Здесь я бессилен.

Автор: Гость 3.08.2009 18:28

Большое спасибо, но проблему удалось решить своими силами)
В самом начале, после begin в OnBeforePost поставил условие что поиск совпадений выполняется только в том случае, если DBEdit3.focused

Автор: 1147 6.08.2009 3:50

Вопрос по дубликатам:
при нажатии на кнопку появляется такое сообщение : параметр Table1.index не имеет значения по умолчанию.
как это исправить?

Автор: volvo 6.08.2009 4:25

Добавить значение по умолчанию. Или в самой базе, или в Object Inspector-е, Table1 -> Fields -> index -> установить в Default Expression нужное значение

Автор: 1147 6.08.2009 17:50

Index-это получается столбец "Фамилия" например в котором производится поиск дубликатов. В БД установил для него значение-индексированное поле, совпадения допускаются, но это не помогло, ошибка таже.
В Object Inspector-е, Table1, defaul expression тоже менял значения, но безрезультатно. Хотя тут я наверное не правильно делал, т.к. не понял что в строке "Object Inspector-е, Table1 -> Fields -> index -> установить в Default Expression нужное значение" означает index, нужно ли его тоже менять и какое должно быть "нужное значение"?

Автор: volvo 6.08.2009 19:14

Цитата
не понял что в строке "Object Inspector-е, Table1 -> Fields -> index -> установить в Default Expression нужное значение" означает index
Заметь, это ты написал:
Цитата
при нажатии на кнопку появляется такое сообщение : параметр Table1.index не имеет значения по умолчанию.
, откуда я знаю, что там у тебя за поля в базе, и какое из них нужно снабдить дефолтным значением. И при нажатии на КАКУЮ кнопку у тебя это все вылетает. В общем, читай пост №23.

Автор: 1147 26.08.2009 16:01

При обнаружении повторяющегося значения, программа его находит, я удаляю его (т.к. старые повторные не нужны), затем снова ввожу это же значение, но программа снова выдает мне что такой номер уже существует и демонстрирует в DBGride пустую строку. Строка получается пустая т.к. поиск ничего не находит поскольку из DBGrid мы ее удалили. Но в списке который создается при запуске программы, этот номер все еще есть. изза этого невозможно ввести нужный номер. Можно как-то решить эту проблему?

Автор: volvo 26.08.2009 16:30

При удалении значения заодно просматривай список, и удаляй значение оттуда тоже. Еще 2 строки кода.

Автор: 1147 26.08.2009 17:07

удалять сразу в formshow или на кнопку удаления повесить? даже не знаю как правильно это сделать.

Автор: volvo 26.08.2009 17:23

В тот момент, когда удаляешь значение из базы - удаляй его же из списка:

  Index := sL.Lines.IndexOf(удаляемая_строка);
if Index <> -1 then sL.Lines.Delete(Index);

Автор: 1147 26.08.2009 18:27

Удалять значения из списка при удалении из базы не совсем удобно, т.к. вместо удаления возможно просто корректировка найденного значения. Таким образом из списка оно не будет удалено.
Лучше наверное это сделать в OnbeforePost:

...
else begin
filterStr := '';
for i := 0 to findSL.Count - 1 do begin
filterStr := filterStr + ORstr[i = 0] +
'([txt] LIKE *' + findSL.Strings[i] + '*) ';
Index := sL.Lines.IndexOf(удаляемая_строка);
if Index <> -1 then sL.Lines.Delete(Index);
end;
DataSet.Cancel;

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

Abort;

end;

Вот только не совсем понятно с index и lines - эти переменные нужно описывать? и как обозначить "(удаляемую строку)"?

Автор: 1147 28.08.2009 22:26

кто-нибудь объясните, что такое index и lines! я исчерпал свои возможности !smoke2.gif

Автор: volvo 28.08.2009 22:59

Что значит "что такое"? Ну, смотри: в StringList-е данные хранятся в виде строк, так? Каждый sL.Strings[ i ] - отдельная строка. Как узнать, присутствует ли в СтрингЛисте определенная строка? Можно, конечно, сделать:

Found := -1; // Если искомой строки не будет, Found останется равным (-1)
for i := 0 to sL.Count do
begin
if sL.Strings[ i ] = 'нужная строка' then Found := i;
end;
// Вот теперь смотрим, если Found = -1, то 'нужная строка' в СтрингЛисте
// отсутствует, иначе Found содержит индекс того элемента Strings, в котором
// она содержится
Это все, конечно, хорошо, но у StringList-а есть готовый метод IndexOf, который получает строку, и выдает индекс элемента, в котором она хранится, или (-1), если строка не была найдена. То есть, код, написанный выше - это реализация того самого IndexOf. Теперь понятно, что значит Index? Это индекс элемента, который надо удалить. Да, это обычная переменная типа Integer, ее надо описывать.

Про Lines забудь, это мой недочет. Я просто проверял кое-что на Memo (для визуализации), а там, чтобы добраться до СтрингЛиста, надо обратиться к свойству Lines. Ну, и забыл удалить... Итого имеем:
var index: Integer;
...
Index := sL.IndexOf(удаляемая_строка);
if Index <> -1 then sL.Delete(Index);

Автор: 1147 30.08.2009 0:36

Еще с удаляемой строкой не совсем понятно. В создаваемом списке она представляет собой номер, который в BDEdit перечисляется через запятую, да? Значит в скобках, вместо "удаляемой_строки" должна быть какая то переменная, обозначающая найденный повторный номер?
Или удаляемая строка-это строка индексов в DBEdit, которые, если <>-1 удаляются?

Автор: volvo 30.08.2009 0:41

Ну, ты ж выше написал:

Цитата
При обнаружении повторяющегося значения, программа его находит, я удаляю его (т.к. старые повторные не нужны)
, то есть, значение, которое является повторным, ты уже нашел, раз удаляешь? Вот ЕГО ЖЕ и удаляй из СтрингЛиста... Пойми, я уже давно потерял нить твоей программы, я не знаю, что на что у тебя навешано, что И КАК ВООБЩЕ работает, поэтому ответа "надо переменную такую-то взять и подставить туда-то" можешь не ждать. То, что удаляешь (из твоей же цитаты), то же самое удаляй из sL...

Автор: 1147 2.09.2009 7:46

еще 1 вопрос по поводу дупликатов:
в случае если есть 3 AdoTable, а не 1, возникает некоторая проблема. В TForm1.FormShow у нас следующий код:

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;


Но AdoTable2, AdoTable3 сюда не добавишь, соответственно нужно выбрать для этого какое-то друго событие.... Перебрал наверное все что только можно, но безрезультатно.
Можно ли тут чтото сделать чтобы обнаружение дубликатов нормально работало с тремя AdoTable?

Автор: volvo 2.09.2009 12:07

Цитата
AdoTable2, AdoTable3 сюда не добавишь, соответственно нужно выбрать для этого какое-то друго событие.
Для начала неплохо бы объяснить, дубликаты ГДЕ будут искаться? Для ADOTable1 - отдельно, для ADOTable2 - отдельно (только внутри этой же таблицы, имеется в виду), и для третьей - тоже? Или эти поля как-то связаны, и это надо будет искать во всех трех таблицах?

То есть, вопрос сводится к тому, будет у тебя в результате один SL, или три разных СтрингЛиста? Как ты потом использовать-то их будешь?

Автор: 1147 2.09.2009 12:25

Поля никак не связаны, поэтому искать нужно в каждой таблице отдельно, соответственно необходимо 3 разных SL. Т.к. если в первой таблице будут обнаружены данные из второй, например, поиск по фильтру ничего не покажет

Автор: volvo 2.09.2009 14:41

Тогда не вижу проблемы. Почти... Потом поймешь, почему "почти":

// Класс формы:
type
TForm1 = class(TForm)
// ...
private
{ Private declarations }
arrSL: array of TStringList;
public
{ Public declarations }
procedure CreateStrList(var T: TADOTable; sFieldName: string; i: integer);
end;

procedure TForm1.CreateStrList(var T: TADOTable; sFieldName: string; i: integer);
var s: string;
begin
T.First;
while not T.Eof do begin
s := s + ',' + T.FieldByName(sFieldName).AsString;
T.Next;
end;
arrSL[i] := TStringList.Create;
arrSL[i].Duplicates := dupIgnore;
arrSL[i].Delimiter := ',';
arrSL[i].DelimitedText := s;
end;

procedure TForm1.FormShow(Sender: TObject);
var i: integer;
begin
SetLength(arrSL, 0);

for i := 0 to Form1.ComponentCount - 1 do
begin
if Form1.Components[i] is TADOTable then
begin
SetLength(arrSL, Length(arrSL) + 1);
CreateStrList(Form1.Components[i] as TADOTable, 'txt', Length(arrSL) - 1);
end;
end;
end;
, и пускай программа сама считает, сколько будет ADOTable, и для каждой создает свой СтрингЛист. Вот теперь должно быть понятно, почему я написал "почти". Это все будет работать, только если во всех этих таблицах нужное тебе поле имеет одинаковое название. Иначе - эти названия надо будет тоже где-то хранить, потеряется гибкость. Ну, в общем дальше уже сам додумывай, тебе лучше знать, в каком виде у тебя это все задается, и как используется.

Автор: 1147 23.10.2009 22:57

Можно ли сделать так чтобы если например номер 555 содержащийся в стринглисте удалялся из него в случае если этот же номер был введен в другом столбце?

Автор: volvo 23.10.2009 23:07

Можно. Как - не спрашивай, я тебе ответить смогу вряд ли. С нуля написать элементарно, со всеми твоими доделками/переделками того, что тут было (теме уже 3 месяца было вообще-то, сколько за это время ты внес корректив в программу по сравнению с первоначальным вариантом - подумать страшно) - скорее всего практически нереально. У тебя налицо ошибка проектирования: тебе надо не "а вот моей правой пятке захотелось, чтобы так...". Сделал. "Ух ты, а вот теперь левой пятке хочется, чтобы еще вот так..." Еще раз сделал, заметь ГОРАЗДО труднее, чем первое. "А теперь вот еще чего хочется..."

Так программы не пишут. Ты должен СРАЗУ, еще до того, как открыл Дельфи, знать, ЧТО и ЗАЧЕМ должна делать твоя программа. И что тебе надо запрограммировать. Если ты этого не знаешь - то будь готов к тому, что для введения каждой новой "фичи" будешь переписывать программу С НУЛЯ заново. Я все сказал. Перелопачивать весь код я не буду. Тебе надо - ты и переделывай, если задачу ставить не научился.

Удачи.

Автор: 1147 23.10.2009 23:15

да это не я не научился. в процессе работы люди поняли что им нужно коечто изменить. и спрашивают у меня-а вот можно ли сделать так?

Автор: 1147 16.11.2009 20:15

Можно ли обновлять стринг лист нужного столбца чтобы он мог отражать изменения происходящие в процессе работы? Например таким образом: SL.refresh в событии AfterPost?
В строке

CreateStrList(Form5.Components[i] as TADOTable, 'txt', Length(arrSL) - 1);

возникает ошибка Constant object cannot be passed as var parametr. В чем тут дело? Вроде в Var все объявлено

Автор: volvo 16.11.2009 20:52

Цитата
возникает ошибка Constant object cannot be passed as var parametr.
Ну да, там в заголовке надо поменять:
procedure CreateStrList(const T: TADOTable; sFieldName: string; i: integer);

Автор: 1147 18.11.2009 5:20

При вводе заведомо повторяющегося значения программа не обнаруживает повтор. Но если это значение ввести еще раз, программа об этом сообщает. Почему же она выдает ошибку только со второго раза?
Если введено сразу несколько повторов, Label отображает только одно вот так например: 54|
а второго нету..
В этом коде повторение Label1.Caption+ так и должно быть?

isOk := false; Label1.Caption :=Label1.Caption+ dbSL.Strings[i] + ' | ';

Я все сделал вот таким образом:
type
TForm1 = class(TForm)

private
{ Private declarations }
arrSL: array of TStringList;
SL: TStringList;

public
{ Public declarations }
procedure CreateStrList(const T: TADOTable; sFieldName: string; i: integer);
end;

procedure TForm1.CreateStrList(const T: TADOTable; sFieldName: string; i: integer);
var s: string;
begin
T.First;
while not T.Eof do begin
s := s + ',' + T.FieldByName(sFieldName).AsString;
T.Next;
end;
arrSL[i] := TStringList.Create;
arrSL[i].Duplicates := dupIgnore;
arrSL[i].Delimiter := ',';
arrSL[i].DelimitedText := s;
end;

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 i: integer;
begin
SetLength(arrSL, 0);

for i := 0 to Form1.ComponentCount - 1 do
begin
if Form1.Components[i] is TADOTable then
begin
SetLength(arrSL, Length(arrSL) + 1);
CreateStrList(Form1.Components[i] as TADOTable, 'txt', Length(arrSL) - 1);
end;
end;
end;

procedure TForm5.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 := DBEdit3.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; Label1.Caption := dbSL.Strings[i] + ' | ';
findSL.Add(dbSL.Strings[i]);
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;
end;


Большая просьба показать мне в чем я допустил ошибку

Автор: 1147 18.11.2009 5:59

Такое впечатление что данные заносятся в SL не при запуске программы, а при вводе их в БД
Ошибку свою понял: стринглисты не заполнялись в OnFormShow smile.gif

Автор: Крастb 30.11.2009 10:33

Код
If DataModule3.Table5.Locate('St_uch',Edit5.Text,[loCaseInsensitive])=true
then
begin
ShowMessage('В таблице уже имеется данная запись!');
edit5.SetFocus;
DataModule3.Table5.Locate('St_uch',y,[loCaseInsensitive]);
exit;
end;
DataModule3.Table5.Append;
DataModule3.Table5.FieldByName('St_uch').AsString:=edit5.Text;
DataModule3.Table5.Post;

я так делаю например.
только вот проблем почему то одна - везде все работает нормально, но в 1 таблице если есть например запись "Сторонник" а вводишь "сТоронник" то добавляется. А если введешь СтронНик например то нормально тогда.
Но это видимо у меня что-то не так.