Форум: "Начинающим";
Текущий архив: 2006.02.19;
Скачать: [xml.tar.bz2];
ВнизКак прервать цикл While? Найти похожие ветки
← →
dera (2006-02-01 14:36) [0]В цикле while not Table1.Eof do ищется запись в довольно большой таблице. Таблица выведена в гриде. Как можна сделать:
1) по нажатию на ESC прервать поиск и выйти из цикла
2) на время поиска "отключить" таблицу от грида (возможно так будет быстрей искать)
← →
Ega23 © (2006-02-01 14:39) [1]
> 1) по нажатию на ESC прервать поиск и выйти из цикла
В цикле поставь Application.ProcessMessages
> 2) на время поиска "отключить" таблицу от грида (возможно
> так будет быстрей искать)
Table1.DisableControls
While
.....
end;
Table1.EnableControls;
← →
ZeroDivide © (2006-02-01 14:46) [2]
> 1) по нажатию на ESC прервать поиск и выйти из цикла
Варианты:
1. Сделать поиск в отдельном потоке
2. Ловить сообщения
← →
stone © (2006-02-01 14:49) [3]
> В цикле while not Table1.Eof do ищется запись в довольно
> большой таблице.
А не проще использовать метод Locate?
← →
Ega23 © (2006-02-01 14:50) [4]
> А не проще использовать метод Locate?
Вообще-то проще использовать запрос с фильтрами, а не всякие Table, но это уже Дзен... :о)
← →
dera (2006-02-01 15:02) [5]>>2. Ловить сообщения
а можна подробнее?
← →
Ega23 © (2006-02-01 15:03) [6]
> а можна подробнее?
Можно. Но это будет долго. Лучше почитай про многопоточность в книжке.
← →
КиТаЯц © (2006-02-01 15:10) [7]
var BRK: boolean = falsle;
...
Table1.DisableControls
while условие do begin
Application.ProcessMessages; // иначе форме все нажатия на клавиши до одного места пока цикл не отработает
...
if BRK then begin
BRK:= False; // переменную сразу на место
break; // прерывание цикла
end;
...
end;
Table1.EnableControls;
procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
if Key = VK_ESCAPE then BRK:= True;
end;
← →
msguns © (2006-02-01 15:13) [8]>Ega23 © (01.02.06 15:03) [6]
>Можно. Но это будет долго. Лучше почитай про многопоточность в книжке.
Зачем в этом контексте многопоточность ?
>dera
Твои ошибки:
1. Использование TXXTable (таблицу в 100000 записей ни один юзер не в силах даже просто просмотреть, не говоря уж о каком-то внимании)
2. Поиск собственно в датасете во всех случаях вместо того, чтобы разбить его на мин. 2 части: поиск первого (Locate) и поиск в список (отдельный динамический запрос с получением списка найденных записей в виде указателей (UID) на них).
Причем, судя по всему, на время поиска грид не "освобождается" датасетом от реакции на его события (DisableControls).
← →
Shirson © (2006-02-01 15:14) [9]А вариант
while (условие) and (not BRK) do begin
Не прокатит?
← →
evvcom © (2006-02-01 15:21) [10]прокатит
← →
dera (2006-02-01 15:30) [11]>>КиТаЯц © (01.02.06 15:10) [7]
>>Shirson © (01.02.06 15:14) [9]
Спасибо, понял
>>msguns © (01.02.06 15:13) [8]
Использование TXXTable (таблицу в 100000 записей ни один юзер не в силах даже просто просмотреть, не говоря уж о каком-то внимании)
Можно было бы и не показывать таблицу, но дело в том, что я делаю просмотрщик таблиц и тут никуда не деться :-(
Нащет 2). Я тоже думал, что можна сначала найти первую запись, и от нее плясать. Но поиск может происходить не по одному полю, то что, для каждого кол-ва полей писать Locate?
← →
ZeroDivide © (2006-02-01 15:34) [12]Locate можно делать по нескольким полям, разделенным ";"
← →
Ega23 © (2006-02-01 15:34) [13]В методе Locate можно список полей указать.
← →
msguns © (2006-02-01 15:34) [14]>dera (01.02.06 15:30) [11]
Какие форматы БД (парадокс, дибэйз, склXXX..) будут обрабатываться ?
Выбор компонент BDE жестко фиксирован ?
← →
dera (2006-02-01 15:41) [15]>>msguns © (01.02.06 15:34) [14]
СУБД Brtieve
Получилось только к Table подключить таблицу через ист.данных в ОДБС.
C Query не получается.
← →
Ega23 © (2006-02-01 15:47) [16]
> Получилось только к Table подключить таблицу через ист.
> данных в ОДБС.
> C Query не получается.
Не верю. Select * from не проходит???
← →
Asail (2006-02-01 15:54) [17]
> Не верю. Select * from не проходит???
И я тоже. Table.Open выполняет тот-же SELECT насколько я понимаю.
← →
dera (2006-02-01 15:56) [18]>>Не верю. Select * from не проходит???
при попытке подключить Query пишет
"Query1: No SQL statement available"
← →
Ega23 © (2006-02-01 15:57) [19]А
Query.SQL.Text:="Select * from Table1";
Query.Open;
делать пробовал?
:о)
← →
Digitman © (2006-02-01 15:59) [20]
> dera (01.02.06 15:56) [18]
> при попытке подключить Query пишет
Что значит "подключить" ?
Телепатировать будем по поводу "подключить" ?
Давай потелепатируем.
Чему у тебя равно зн-е св-ва Query.SQL.Text ?
← →
Asail (2006-02-01 16:02) [21]
> Что значит "подключить" ?
Видимо, автор пытался в Object Inspector"е для Query Active=True выставить, а в SQL тело запроса прописать и забыл...
← →
dera (2006-02-01 16:06) [22]под "подключить" я понимаю Query.Open;
я все неправильно делал :-(
теперь получилось! Благодарю, мастера!
← →
msguns © (2006-02-01 16:06) [23]Переключись с BDE на ADO - там другой SQL с куда большими возможностями. В частности там есть волшебное слово TOP
← →
Kolan © (2006-02-01 16:08) [24]Как прервать цикл While
Самое простое:
Заводишь переменную:var
FIsBreakLoop: Boolean;while () do
begin
{ Любые действия}
{Те проверяешь. Если переменная = True то надо цикл оборвать}
if FIsBreakLoop then
begin
FIsBreakLoop := False;
Break;
end;
end;
А в программе пишешь в OnKeyDown:procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
if Key = VK_ESCAPE then
FIsBreakLoop := True;
end;
← →
dera (2006-02-01 16:12) [25]>>Asail (01.02.06 16:02) [21]
Совершенно правильно. :-)
Но мне как раз надо редактировать найденную запись. Как можна реализовать? Ведь Query этого не позволяет.
← →
Ega23 © (2006-02-01 16:13) [26]
> Kolan © (01.02.06 16:08) [24]
>
> Как прервать цикл While
>
> Самое простое:
> Заводишь переменную:
> var
> FIsBreakLoop: Boolean;
>
> while () do
> begin
> { Любые действия}
> {Те проверяешь. Если переменная = True то надо цикл оборвать}
> if FIsBreakLoop then
> begin
> FIsBreakLoop := False;
> Break;
> end;
> end;
>
> А в программе пишешь в OnKeyDown:
> procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
>
> Shift: TShiftState);
> begin
> if Key = VK_ESCAPE then
> FIsBreakLoop := True;
> end;
Ты забываешь, что цикл выполняется В ОСНОВНОМ ПОТОКЕ ПРОГРАММЫ.
Попробуй сам такой код написать. Без Applicatio.ProcessMessages в теле цикла.
И тогда ты увидишь, что твой вариант нихрена не работает.
← →
Kolan © (2006-02-01 16:17) [27]Где и как выполняется цикл неважно.
Как боротся с "зависание" главного потока - другой вопрос. И решений несколько - доп. поток, Applicatio.ProcessMessages ...
Я ответил на вопрос...
← →
ZeroDivide © (2006-02-01 16:17) [28]
> Но мне как раз надо редактировать найденную запись. Как
> можна реализовать? Ведь Query этого не позволяет.
Возможно все что ты хочешь сделать можно написать одним Update Statement"ом.
Напиши алгоритм, который у тебя в теле цикла.
← →
evvcom © (2006-02-01 16:19) [29]
> Ведь Query этого не позволяет.
Позволяет. См. TUpdateSQL
← →
msguns © (2006-02-01 16:22) [30]>dera (01.02.06 16:12) [25]
>Но мне как раз надо редактировать найденную запись. Как можна реализовать? Ведь Query этого не позволяет.
Даже на этом ресурсе есть статьи по работе с BDE, которые тебе просто необходимо прочитать.
Query вполне позволяет, если к нему "прикрутить" TUpdateSQL. Кроме того ничто не мешает другим квери апдэйтить таблицу, после чего отображающий просто переоткрывать с позиционированием на обновленную запись (сейчас уже меня запинают ;))
Помимо этого можно уйти от BDE в пользу ADO, где есть "универсальная" компонента, сочетающая в себе достоинства и Table, и Query,- TADODataSet.
Можно остановить выбор на dbExpress вообще практически с неорграниченными возможностями.
← →
Ega23 © (2006-02-01 16:23) [31]
> (сейчас уже меня запинают ;))
Почему? Я обычно так и делаю...
← →
dera (2006-02-01 16:27) [32]>>Напиши алгоритм, который у тебя в теле цикла.
while not table1.eof do begin
Application.ProcessMessages;
if pos(Edit1.Text,Table1.FieldByName(ComboBox2.Text).AsVariant)>0 then begin
r:=MessageDLG("Запись найдена! Продолжить поиск?", mtConfirmation,[mbYes,mbNo],0);
if r=mrNo then break;
end;
Table1.Next;
end;
← →
msguns © (2006-02-01 16:36) [33]Где DisableControls ?
← →
dera (2006-02-01 16:39) [34]>>Где DisableControls ?
в приведенном примере его нет, т.к. он стоит до и после цикла
← →
ZeroDivide © (2006-02-01 16:50) [35]Но мне как раз надо редактировать найденную запись.
Мм... я думал ты прямо в цикле собираешься редактировать что-то... тогда Update прокатил бы...
И как долго этот поиск выполняется? Вроде как тормозить особо нечему. Единственное, можно поставить сразу AsString, вместо AsVariant. И AnsiUpperCase, но это уже не для ускорения, а для улучшения поиска.
← →
msguns © (2006-02-01 16:53) [36]Не нравится мне вот это
FieldByName(ComboBox2.Text).AsVariant
Замени его на AsString
Другого криминала в теле цикла не узрел. Так в чем проблема-то ?
← →
Asail (2006-02-01 16:57) [37]А какой размер таблицы?
Может и нет смысла мучаться? При DisableControls такой цикл на не слишком больших таблицах выполняется почти мгновенно, пользователь и кнопку Esc на клаве найти не успеет. Если теоретический размер таблицы не превышает нескольких десятков мегабайт, то можно и необрабатывать сообщения в цикле. Только, надо учесть, что вычисляемые поля и lookup-поля в таблице тоже могут сильно тормозить процесс, поэтому их лучше избегать в больших таблицах.
← →
dera (2006-02-01 16:58) [38]>>И как долго этот поиск выполняется?
В таблице 1.27 млн. строк. Поиск выполняется оч-ч-чень долго!
>>Единственное, можно поставить сразу AsString, вместо AsVariant.
а если поле не стринг попадется для поиска.
Это программа просмотра/редактирования записей. Юзер выбирает название поля, вводит искомое значение и ищет. Когда нашел - возможно, редактирует. Но в этом примере поиск только по одному полю, а я хочу сделать поиск макс. по 5 полям. Но сейчас это неважно. Главное - как ускорить энтот поиск по одному полю.
← →
dera (2006-02-01 17:03) [39]размер таблицы 109Мб
← →
Asail (2006-02-01 17:07) [40]В таблице, я так понимаю, должен быть PrimaryKey.
1. Так-что можно реализовать поиск через SQL с возвратом списка значений ключей записей, соответствующих запросу. А потом, с помощью GotoKey прыгать по таблице только на соответствуюшие записи.
2. По причине того, что названия полей каждый раз разные, в SQL-запросе можно использовать параметры.
← →
msguns © (2006-02-01 17:10) [41]>dera (01.02.06 16:58) [38]
>В таблице 1.27 млн. строк. Поиск выполняется оч-ч-чень долго!
С тебя причитается на ремонт стула. Сломался ибо. Когда я упал, прочитав это.
>>Единственное, можно поставить сразу AsString, вместо AsVariant.
>а если поле не стринг попадется для поиска.
Давай все ж-таки сделаем так: ты нормально исследуешь хотя бы один, но базовый класс TDataSet вместе с TFields/TField, а только потом придешь сюда с вопросами. Ибо читать тебе тут целый курс лекций никто не будет.
А без этого (а ведь это только основы !) нечего и думать о "программе просмотра/редактирования записей"
Либо у тебя получится уродище еще то. Самому же и стыдно будет.
← →
msguns © (2006-02-01 17:13) [42]Кстати, а чем не нравится для этих целей стандартные борландовсие "шаровары" типа десктопа. Там все делается, только, думаю, бОльше, быстрее и лучше, чем в твоей программе.
Зачем изобретать велосипед ?
← →
dera (2006-02-01 17:18) [43]>>Либо у тебя получится уродище еще то. Самому же и стыдно будет.
согласен... маловато знаю по сравнению с вами. Но пытаюсь...
Спасибо. Вы и так много помогли.
← →
Asail (2006-02-01 17:19) [44]
> а чем не нравится для этих целей стандартные борландовсие
> "шаровары" типа десктопа
А борланд десктоп может работать с таблицами Btrieve? Сомневаюсь...
Хотя, конечно, если пошарить по сети хорошенько, можно найти неплохой viewer.
← →
evvcom © (2006-02-01 17:21) [45]сгенерить sql запрос и выполнить. Имхо, лучшей производительности (скорости) не добьешься.
← →
Asail (2006-02-01 17:25) [46]
> сгенерить sql запрос и выполнить
А я про что?!! см. 40
← →
dera (2006-02-01 17:27) [47]>А борланд десктоп может работать с таблицами Btrieve? Сомневаюсь...
правильно сомневаетесь. Не работает.
А вот SQL Explorer отлично видит и выполняет sql запросы для таблиц Btrieve. Но! Есть одно но. Если человек (обычный пользователь) не знает sql, он не сможет ничего найти. Вот я и хочу упростить ему работу - выбрал имя поля, ввел искомое значение, нажал батон - и есть результат.
← →
dera (2006-02-01 17:30) [48]>1. Так-что можно реализовать поиск через SQL с возвратом списка значений ключей записей, соответствующих запросу.
Это я знаю ка сделать.А вот это...
>А потом, с помощью GotoKey прыгать по таблице только на соответствуюшие записи.
...нет. Подскажите.
← →
Ega23 © (2006-02-01 17:36) [49]
> ...нет. Подскажите.
Попробуй покопай в сторону TBookmark
← →
Asail (2006-02-01 18:00) [50]Примерно так:
Положим, что поле с ключом называется PK_Field. Query должен вернуть таблицу из записей ,соответствующих условию. Каждая запись состоит из одного поля PK_Field.
Теперь, проходим циклом по Query:
...
Query.Open;
while not Query.Eof
do begin
Table.SetKey;
Table.FieldByName("PK_Field").AsVariant:=
Query.FieldByName("PK_Field").AsVariant;
Table.GotoKey;
//здесь мы оказались на следующей искомой записи в основной таблице
if MessageDLG("Запись найдена! Продолжить поиск?",
mtConfirmation,[mbYes,mbNo],0)=mrNo then break;
Query.Next;
end;
понятно, что Table.IndexFieldNames:="PK_Field"
иначе SetKey, GotoKey работать не будут.
← →
dera (2006-02-01 18:23) [51]>Asail (01.02.06 18:00) [50]
спасибо!
Страницы: 1 2 вся ветка
Форум: "Начинающим";
Текущий архив: 2006.02.19;
Скачать: [xml.tar.bz2];
Память: 0.58 MB
Время: 0.047 c