Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C++ Builder > Поиск в таблице


Автор: ksili 11.4.2006, 08:00
Есть большая таблица (несколько тысяч строк на 6 столбцов). Нужно осуществлять поиск по значению в выбранном столбце. Хотелось бы ещё, чтобы поиск был индексный (или как он там называется), т.е. как в стандартном Help'e - по мере ввода строки поиска отсеиваются все неподходщие значения.

Так вот у меня вопрос. Всё это можно сделать и вручную, проверяя значение из каждой строки. Но лень. Нет ли стандартного класса или компонента типа списка, в котором бы была функция поиска? И/или сортировки, что тоже пригодится.

Хотел, конечно, использовать StringGrid чтоб таблицу легче было отображать, но там поиск точно вручную придётся делать. smile

Автор: Ctrl_Alt_Del 11.4.2006, 18:19
ksili, создай базу данных. В ней таблицу проиндексируешь, загонишь данные, а дальше поиск и все остальное делается элементарно.
Тем более существуют TDBGrid, TDBEdit...
ИМХО оптимальный вариант

Автор: docwar 19.11.2006, 13:47
А как быть, если до бд мне еще далеко, а поиск данных в StringGrid сделать надо?
Пробовал по-простому: организовывал цикл проверки for, где проверяется текст из эдита с данными первой колонки. Если же совпадений по таблице много, то занесенные действия при успешном поиске программа просто не выполняла.
Есть-ли стандартные алгоритмы поиска?

Автор: SenkraD 19.11.2006, 14:53
Ну в библиотеке STL есть, только я ими ещё не пользовался так, что более подробно помочь не могу

А так не пробовал:  
Код

TStringList *RowsID = new TStringList();
String FindText = Edit1->Text;
int IndexCol = 0;//Или какой тебе надо - определи как-то
for(int i = 1; i < StringGrid1->RowCount - 1; i ++)//Первая строка я полагаю зафиксина
   if(FindText == StringGrid1->Cells[IndexCol][i])
      RowsID->Add(IntToStr(i));//явная конвертация для пущей уверености

if(RowsID->Count > 0)
   for(int i = 0; i < RowID->Count; i ++)
   {
      //Тут делаеш нужный действия на строкой  из StringGrid'a номер,
      //которой записан в списке по номером i
   }

Автор: docwar 19.11.2006, 15:33
Спасибо за ответ!
Минус такого алгоритма - не выполняет никаких действий, если нашел несколько совпадений!!!
Причем, i=0 при успешном поиске... странно...

Автор: docwar 19.11.2006, 16:56
Код для поиска написал! =) Осталось только выделить строку StringGrid или ячейку (все равно у меня выделяется целая строка при нажатии на ячейку этой строки)!
Искал на форуме, но ничего не нашел...
Заранее спасибо!

Добавлено @ 17:06 
Нужно выделить строку, зная номер строки и столбца таблицы.

Автор: Reptile 20.11.2006, 13:28
Ну Ты ведь знаеш номер строки smile  Пиши
Код

StringGrid1->Row = n;//n - номер строки

Или я что-то не так понял?

Автор: docwar 20.11.2006, 13:59
Именно это мне и нужно было! Спасибо! =)  =)

Автор: docwar 20.11.2006, 14:28
Написал вот такой код для поиска в StringGrid:
Код

AnsiString poisk;

Poisk = Edit1 -> Text;
for ( int i = 0; i < Form1->StringGrid1 -> RowCount; i++ )
{
for ( int j = 0; j < Form1->StringGrid1 -> ColCount; j++ )
{
if ( Form1->StringGrid1 -> Cells[j][i] == poisk )
Form1->StringGrid1->Row = i;
}
}

Но как сделать, чтобы выделялись все строки (результат поиска в которых положителен), а не только последняя???

Автор: Reptile 20.11.2006, 15:40
Цитата(docwar @  20.11.2006,  14:28 Найти цитируемый пост)
Но как сделать, чтобы выделялись все строки (результат поиска в которых положителен), а не только последняя???

Никак  smile
Как вариант можно делать найденые слова жирным, можно попробовать отсеять не нужные строки(т.е. удалить их). 


Автор: docwar 20.11.2006, 16:39
Можно тогда, правда, делать фон у строк как у выделенных.
только как же вызвать OnDrawCell по нажатию кнопки, если учесть, что у меня в прорисовке есть еще и другой код?

Автор: Reptile 20.11.2006, 17:02
Так и вызываеш, но лучше(наверное) всетаки сделать жирным smile 

Автор: docwar 20.11.2006, 17:10
Что придумать - не вопрос! =)
Но как быть с нажатием на кнопку? Не хватает ведь параметров...

Автор: Reptile 20.11.2006, 17:16
Цитата(docwar @  20.11.2006,  17:10 Найти цитируемый пост)
Не хватает ведь параметров... 

Потому и говорю - не парься изменяй шрифт и/или цвет текста во время поиска.

Автор: docwar 20.11.2006, 17:39
А как цвет текста одной строки поменять?
Так только всей таблицы: Form1->StringGrid1->Font->Color=StringToColor(0x00D0B2AD);
 smile 

Автор: Reptile 20.11.2006, 18:49
Цитата(docwar @  20.11.2006,  17:39 Найти цитируемый пост)
А как цвет текста одной строки поменять?

Оказывается - напрямую никак smile 
Можно хитро smile
Когда находиш нужную ячейку становишся на нее сохраняеш какую нибудь глобальную переменную и перерисовываеш StringGrid
Цитата(docwar @  20.11.2006,  17:10 Найти цитируемый пост)
Но как быть с нажатием на кнопку? Не хватает ведь параметров... 

Код

StringGrid1->Repaint();

В OnDrawCell пишеш 
Код

//если ячейка выделена (Builder-а нет поэтому сам разберешся) и глобал-я переменная в true
{
   StringGrid1->Canvas->Brush=>Color = clBlack; 
   StringGrid1->Canvas->Font->Color = clWhite; 
}

//Теперь закрасим ячейки, но только, если ячейка не Title- Row/Column 
//Естевственно это завит от того, есть у Вас title-Row/Columns или нет. 

If (ACol > 0) and (ARow>0)  
  { 
      //Закрашиваем бэкграунд 
    StringGrid1->canvas->fillRect(Rect); 

      //Закрашиваем текст (Text). Также здесь можно добавить выравнивание и т.д.. 
    StringGrid1->canvas->TextOut(Rect->Left,Rect->Top,StringGrid1->Cells[ACol][ARow]); 
  }  

P.S. Переписывал из Delphi так что могут быть ошибки, но ход мысли, я думаю, ясен.

Автор: docwar 20.11.2006, 19:05
Опять же как передать данные строки? Такой код красит всю таблицу кроме первого столбца первой строки! =)

Автор: Reptile 20.11.2006, 19:23
Цитата(docwar @  20.11.2006,  19:05 Найти цитируемый пост)
Опять же как передать данные строки? Такой код красит всю таблицу кроме первого столбца первой строки! =) 

Не правильно поставил условие в Delphi
Код

if (gdFocused in State) then begin//если ячейка в фокусе      
   StringGrid1.Canvas.Brush.Color := clBlack;  
   StringGrid1.Canvas.Font.Color := clWhite;  
end  


Автор: docwar 20.11.2006, 20:44
А что значит "in State" в строке "gdFocused in State"?

Автор: Reptile 21.11.2006, 10:07
Цитата(docwar @  20.11.2006,  20:44 Найти цитируемый пост)
А что значит "in State" в строке "gdFocused in State"?

Еще раз повторю это в Delphi в Builder-е наверное(не проверял)
Код

if (gdFocused)
{
}

Или что-то похожее.

Автор: docwar 21.11.2006, 19:38
Цитата(Reptile @  21.11.2006,  10:07 Найти цитируемый пост)
Еще раз повторю это в Delphi в Builder-е наверное(не проверял)

Знаю, что Дельфи! Просто хотел разобраться.

Автор: docwar 22.11.2006, 13:38
Я пишу вот так:
Код

if(StringGrid1->Focused())
{
StringGrid1->Canvas->Brush->Color = clBlack;
StringGrid1->Canvas->Font->Color = clWhite;

if((ACol == j) || (ARow == i))
{
StringGrid1->Canvas->FillRect(Rect);
StringGrid1->Canvas->TextOut(Rect.Left,Rect.Top,StringGrid1->Cells[ACol][ARow]);
}
}
}

Но выделяется таблица неправильно... =(  :'(

Автор: Vyacheslav 22.11.2006, 13:57
Код

if(StringGrid1->Focused())


smile  
Переводим на русский язык
Цитата

Если StringGrid1 в фокусе, то

А Вам нужно, по всей видимости, убедится находится ли в фокусе конкретная ячейка.
Что же делать? 
Ответ простой смотреть хелп
Научить, как правильно это делать?
открываем TCustomDrawGrid::OnDrawCell
Цитата

typedef void __fastcall (__closure *TDrawCellEvent)(System::TObject* Sender, long ACol, long ARow, TRect Rect, TGridDrawState
 State);
__property TDrawCellEvent OnDrawCell = {read=FOnDrawCell, write=FOnDrawCell};



Нас интересует TGridDrawState. Щелкаем по нему(он выделен зеленым цветом)
Получаем 
Цитата

enum Grids__3 { gdSelected, gdFocused, gdFixed };

typedef Set<Grids_3, gdSelected, gdFixed> TGridDrawState;


Если мы обладаем достаточным любопытством, нас конечно за интересует, что такое тип Set(тоже выделен зеленым цветом). Щелкаем по нему, смотрим список методов и , о чудо, видим метод
Цитата

bool __fastcall Contains(const T el) const;

После этого нам сразу становится понятно smile , что дельфийский код 
Код

if (gdFocused in State)

по билеровски будет выглядет так
Код

if (State.Contains(gdFocused) )


Вот так примерно обычно пользуются хелпом

Автор: docwar 23.11.2006, 23:43
Большое спасибо, но тем не менее вопрос не решен... выделяется только последняя строка...

Автор: pandrew 24.11.2006, 15:54
Попробуй при отрисовке выделять не прямоугольником, а меняя цвет кисти:
Код

canvas->Brush->Color=...
 
У меня, по крайней мере, все отлично выделяется.

Автор: docwar 24.11.2006, 19:24
Вообщем, написал вот такой код:
[CODE]void __fastcall TForm6::FillRow(int RowNum)
{
TRect Rec;
for(i=0; i<=Form1->StringGrid1->ColCount; i++)
 {
  Rec=Form1->StringGrid1->CellRect(i,RowNum);
  Form1->StringGrid1->Canvas->Brush->Color=StringToColor(0x00C56A31);
  Form1->StringGrid1->Canvas->FillRect(Rec);
 }
}[CODE]
Вот только как показать текст?! =)

Автор: Reptile 25.11.2006, 12:49
Код

StringGrid1->Сanvas->TextOut(Rect->Left,Rect->Top,StringGrid1->Cells[ACol][ARow]); 

Пробовал?

Автор: docwar 25.11.2006, 13:06
Пробовал, но проблема в том, что написал свою собственную функцию, а при записи 
Код
void __fastcall TForm6::FillRow(int RowNum, TRect &Rect, int ACol,
      int ARow)

возникают ошибки при обращении к функции : FillRow(p); , где p - номер строки...

Автор: Reptile 25.11.2006, 13:14
Какие ошибки?

Автор: docwar 25.11.2006, 13:25
[C++ Error] Unit6.cpp(30): E2193 Too few parameters in call to '_fastcall TForm6::FillRow(int,int,int,TRect &)'
Это на строчке FillRow(p);

Автор: Reptile 25.11.2006, 14:57
Покажи как вызываеш.

Автор: docwar 25.11.2006, 18:07
Цитата
FillRow(p); , где p - номер строки

Автор: Reptile 27.11.2006, 19:32
Что-то я не понял Ты используеш

Код

void __fastcall TForm6::FillRow(int RowNum, TRect &Rect, int ACol,
      int ARow)

 или

Код

void __fastcall TForm6::FillRow(int RowNum)
{
  TRect Rec;
  for(i=0; i<=Form1->StringGrid1->ColCount; i++)
   {
      Rec=Form1->StringGrid1->CellRect(i,RowNum);
      Form1->StringGrid1->Canvas->Brush->Color=StringToColor(0x00C56A31);
      Form1->StringGrid1->Canvas->FillRect(Rec);
   }
}

Если вызывать:
Код

FillRow(p);

То первый вариант выдаст ошибку (Кстати как у Тебя) т.к. не хватает параметров.

Автор: docwar 27.11.2006, 20:44
Спасибо, но вопрос уже не актуален. =) Выбрал другой метод осуществления поиска.

Автор: Vyacheslav 28.11.2006, 12:44
Цитата(docwar @  27.11.2006,  20:44 Найти цитируемый пост)
Спасибо, но вопрос уже не актуален. =) Выбрал другой метод осуществления поиска. 

 smile   smile  smile 

docwar, Вы уж извините, но еще пара таких финтов и здесь перестанут серьезно относится к Вашим вопросам. 

Модератор: тему я закрываю. Тем более, что  это не по теме. Первончально речь шла о поиске в таблице, а не в гриде. Если есть желание все таки выяснить вопрос о поиске в гриде, заведите другой топик 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)