O.Lena |
Отправлено: 27.12.2004, 10:15 |
|
Ученик-кочегар
Группа: Участник
Сообщений: 21
|
Здравствуйте, все! С Наступающим Новым Годом
Подскажите, пожалуйста как можно сделать поиск в заданном поле по фрагменту. Есть база MS SQLServer. В ней таблица с организациями-клиентами. Есть поле name, в котором хранятся названия организаций.
Есть DBGrid, Edit и кнопка. В коде программы ввела
TVarRec q(Edit1->Text);
DM->TableUL->FindNearest(&q, 0);
Поиск идет только по первым сиволам. А как сделать чтобы искала введенный текст и в середине названия организации и в конце? И чтобы было что-то типа "Найти дальше" |
|
AVC |
Отправлено: 27.12.2004, 10:32 |
|
Ветеран
Группа: Модератор
Сообщений: 1583
|
В вашем случае поможет только программирование "руками" (по опыту — пишется за пол-дня используется не один год)
А вообще если уж вы работаете с SQL'ским сервером, то такие задачки нужно ставить ему. Он для этого просто предназначен. |
|
olegenty |
Отправлено: 27.12.2004, 11:14 |
|
Ветеран
Группа: Модератор
Сообщений: 2412
|
это когда записей много.
а когда с гарантией мало, то всё это делается локально на клиенте. например, с помощью свойства STFilter компонента TDBGridEh (при этом надо не забыть включить соответствующий *.hpp и залинковать (pragma link) соответствующий *.obj из подкаталога DataService библиотеки EhLib)
всю жизнь работал только ограничением выборки с сервера, но в данном случае — просто тащусь от EhLib. И тебе локальная сортировка, и тебе сортировка по нескольким колонкам, и тебе и фильтрация — и всё это БЕЗ НАПИСАНИЯ ПРОГРАММНОГО КОДА.
|
|
avc* |
Отправлено: 27.12.2004, 11:22 |
|
Не зарегистрирован
|
Абсолютно согласен. Универсального решения не бывает. Но в вопросе было DBGrid
|
|
O.Lena |
Отправлено: 27.12.2004, 11:27 |
|
Ученик-кочегар
Группа: Участник
Сообщений: 21
|
AVC! Извините, но знаний у меня по этой части маловато. Подскажите, пожалуйста, что именно надо сделать? |
|
AVC |
Отправлено: 27.12.2004, 11:47 |
|
Ветеран
Группа: Модератор
Сообщений: 1583
|
Определить два события Искать и Продолжить поиск. Сделать под них кнопку / пункт контекстного меню / "горячую клавишу" (у меня все сразу).
Обработать события примерно так:
Искать
CODE |
void __fastcall TF_UniEdit::QryMain_Seek (void) // Seek
{
if (!FQryMain_PK) return;
TField *fld = Grd_Main->SelectedField;
if (!fld) return;
AnsiString fname = fld->FieldName.Trim().UpperCase();
AnsiString title = Grd_Main->CurColumn()->Title->Caption.Trim();
if (title.IsEmpty()) title = fname;
if (fname == "???CAN_WORK" ) return;
FSeekFieldName = fname;
AnsiString str;
TStringField *sfld = dynamic_cast<TStringField*>(fld);
TDateTimeField *dtfld = dynamic_cast<TDateTimeField*>(fld);
TNumericField *nfld = dynamic_cast<TNumericField*>(fld);
TBooleanField *bfld = dynamic_cast<TBooleanField*>(fld);
//str += "\r\n<" + title + ">";
//----
if (sfld ) str = "Искать по началу текста (*текст — по фрагменту)";
else if (dtfld) str = "Искать по началу текста (*текст — по фрагменту)";
else if (nfld ) str = "Искать по значению (*цифры — по началу)";
else if (bfld ) str = "Искать по значению";
else return;
str += "\r\nполя <" + title + ">";
//----//
if (AskString (str, FSeekString, "Искать") <= 0)
{ FSeekString = "";
FSeekFieldName = "";
SetToolBars();
return;
}
FSeekString = FSeekString.Trim();
LblSeekInfo_Sinxr(1, "Ищу");
FInfosRecord->UpdAdd("Time_SeekRecord", double(0))->Format = "0.00";
TDateTime tmbeg = Now();
TWaitSQL wcur;
QryMain->DisableControls();
try {
QryMain_SeekNext(false);
}
//catch (Exception& xcp) { ShowMessage(xcp.Message); }
catch (Exception& xcp) { OEMessage_Show(xcp.Message); }
QryMain->EnableControls ();
FInfosRecord->UpdAdd("Time_SeekRecord", (double)(Now() — tmbeg) * (24*60*60));
LblSeekInfo_Sinxr (0);
SetToolBars ();
Grd_Main->SetFocus ();
}
|
Продолжить поиск
QUOTE |
void __fastcall TF_UniEdit::QryMain_SeekNext (bool isnext)
{
if (!FQryMain_PK ) return;
if (FSeekFieldName.IsEmpty()) return;
if (FSeekString.IsEmpty() ) return;
if (QryMain->Eof ) return;
TField *fld = QryMain->FindField(FSeekFieldName);
if (!fld) return;
TStringField *sfld = dynamic_cast(fld);
TDateTimeField *dtfld = dynamic_cast(fld);
TNumericField *nfld = dynamic_cast(fld);
TNumericField *snfld = NULL;
TBooleanField *bfld = dynamic_cast(fld);
//----
AnsiString sval = FSeekString.UpperCase();
double nval;
bool bval;
bool isaster = false;
bool ok = true;
if (sval[1] == '*' && sval.Length()> 1)
{ isaster = true;
sval = sval.SubString(2,sval.Length());
}
if (sfld ) ;
else if (dtfld) ;
else if (nfld )
{ if (isaster) { snfld = nfld; nfld = NULL; }
else
{ try { nval = sval.ToDouble(); }
catch (...) { ok = false; }
}
}
else if (bfld )
{ if (sval.Length() < 1) ok = false;
else bval = AnsiString("1TYДXХ").Pos(sval[1])> 0;
}
else ok = false;
if (!ok) return;
ok = true;
int oldpk = FQryMain_PK;
QryMain->DisableControls();
try {
if (isnext) QryMain->Next ();
else QryMain->First();
for (NULL; !QryMain->Eof; QryMain->Next())
{ ok = true;
if (IsBreakPoint() ) break;
if (sfld )
{ if (isaster){ if (sfld->AsString.UpperCase().Pos(sval)> 0) break; }
else { if (sfld->AsString.UpperCase().Pos(sval) == 1) break; }
}
else if (dtfld)
{ if (isaster){ if (dtfld->AsString.Pos(sval)> 0) break; }
else { if (dtfld->AsString.Pos(sval) == 1) break; }
}
else if (nfld )
{ if (nval == nfld->AsFloat ) break;
}
else if (snfld )
{ if (snfld->DisplayText.Trim().Pos(sval) == 1) break;
}
else if (bfld )
{ if (bval == bfld->AsBoolean ) break;
}
ok = false;
}
}
//catch (Exception& xcp) { ShowMessage(xcp.Message); }
catch (Exception& xcp) { OEMessage_Show(xcp.Message); }
if (!ok) QryMain->Locate(FQryMain_PKName, oldpk, TLocateOptions());
QryMain->UpdateCursorPos();
QryMain->EnableControls ();
if (!ok) ShowMessage("Строка не найдена");
Grd_Main->SetFocus ();
}
|
Извиняюсь за лень. Это рабочий, не причесанный код, выдранный из окна редактирования Builder'а |
|
olegenty |
Отправлено: 27.12.2004, 13:12 |
|
Ветеран
Группа: Модератор
Сообщений: 2412
|
читаю я его, и думаю: если ты не посвятишь в свои соглашения, то хрен там вопрошающий разберётся, он же грит — опыта мало.
if (fname == "???CAN_WORK" ) return; — пахнет внутренним соглашением.../заплаткой/использованием св-в не по прямому назначению.
жестокий ты
|
|
O.Lena |
Отправлено: 27.12.2004, 13:20 |
|
Ученик-кочегар
Группа: Участник
Сообщений: 21
|
Да-а Без некоторых разъяснений я здесь разобраться не смогу, это точно. |
|
AVC |
Отправлено: 27.12.2004, 13:29 |
|
Ветеран
Группа: Модератор
Сообщений: 1583
|
Согласен дать любые разъяснения. Я же извинислся за рабочий код
if (fname == "???CAN_WORK" ) return; — означает заготовку, куда я подставлю имя поля для которого этот алгоритм работать не должен.
В коде соглашения практически не используются, а на всякую мишуру типа
FInfosRecord->UpdAdd("Time_SeekRecord", (double)(Now() — tmbeg) * (24*60*60)); — подсчет времени, затраченного на поиск
LblSeekInfo_Sinxr (0); — вывод какой то информации о прохождении поиска
SetToolBars (); — красивый поджиг и гашение кнопок и прочие синхронизации
не стоит обращать внимание. Важен принцип.
1. Определиться по какому полю искать (можно и по нескольким)
2. Как искать — по части / по началу или еще как-то
3. Откуда искать — с начала или от текущей записи
4. Сам поиск — сравнение и анализ
Отредактировано AVC — 27/12/2004, 13:32 |
|
AVC |
Отправлено: 27.12.2004, 13:40 |
|
Ветеран
Группа: Модератор
Сообщений: 1583
|
"Лишние" строки
LblSeekInfo_Sinxr(1, "Ищу");
SetToolBars ();
TWaitSQL wcur;
Показывают в каких местах можно "навести красоту" на экране
FInfosRecord->UpdAdd("Time_SeekRecord", double(0))->Format = "0.00";
TDateTime tmbeg = Now();
Замеры времени
"Нужные" функции:
if (AskString (str, FSeekString, "Искать") <= 0)
Форма, задающая вопрос и ожидающая ответа
IsBreakPoint() — проверяет, а не надоело ли пользователю ждать (в простом случае — нажимался ли ESC с последней проверки)
Кажется все. |
|
olegenty |
Отправлено: 27.12.2004, 13:49 |
|
Ветеран
Группа: Модератор
Сообщений: 2412
|
короче я всё равно тащусь от TDBGridEh + примочки, и для себя лучше разберусь, как встроить поиск/фильтрацию на больших наборах прямо в грид, чем сделаю что-то ещё. уж зело мне нравиться ничего не делать, а только св-ва компонентов выставлять. я от этого делаюсь умиротворённый и производительность отнюдь не падает.
правда, для этого нужно один раз родить рабочий универсальный код. )
|
|
AVC |
Отправлено: 27.12.2004, 14:04 |
|
Ветеран
Группа: Модератор
Сообщений: 1583
|
QUOTE | всё равно тащусь от TDBGridEh + примочки, и для себя лучше разберусь, как встроить поиск/фильтрацию на больших наборах прямо в грид |
Так я и не спорю. Ну жалко мне бросать свою сетку (по возможностям она не хуже DBGridEh). А поисковый механизм просто поленился в неё вставить (делается же для личного использования). |
|
olegenty |
Отправлено: 27.12.2004, 14:10 |
|
Ветеран
Группа: Модератор
Сообщений: 2412
|
если своё универсально — нечего и дёргаться.
я сейчас такой расслабленный ТОЛЬКО потому, что у меня максимальное число записей в выборке по текущей задаче < 4000. я их нагло лью на клиента, и он над ними выколбашивается, как хочет
|
|
O.Lena |
Отправлено: 28.12.2004, 12:44 |
|
Ученик-кочегар
Группа: Участник
Сообщений: 21
|
Спасибо за помощь AVC и Olegenty!!! Я сделала поиск с DBGridEh. Так оказалось очень просто. А как можно сделать, чтобы окно диалога поиска было на русском? Вариант, предложенный AVC, наверно был бы очень полезен для дальнейшего использования, но к сожалению разобраться в нем мне не по силам. |
|
avc* |
Отправлено: 28.12.2004, 12:55 |
|
Не зарегистрирован
|
Послал вам письмо с разъяснениями. Вы его не получили или там то же плохо изложено? |
|
avc* |
Отправлено: 28.12.2004, 12:57 |
|
Не зарегистрирован
|
Все. Получил подтверждение о получении. |
|