Components for Delphi and C++ Builder.

Перейти в английский форум
Перейти на EhLib.com
Текущее время: 28 мар 2024, 18:23

Часовой пояс: UTC




Начать новую тему Ответить на тему  [ Сообщений: 14 ] 
Автор Сообщение
 Заголовок сообщения: SearchPanel новые возможности
СообщениеДобавлено: 03 окт 2016, 07:44 
Не в сети

Зарегистрирован: 21 дек 2012, 09:32
Сообщений: 53
Добрый день.

Предлагаю подумать над такими возможностями SearchPanel:
1. Поиск по таймеру. Т.е., пока идет набор символов, искать не надо, лучше подождать. Актуально на больших наборах данных.
2. Прерывание поиска нажатием Esc. Бывает, напишешь в поиск всякий ерунды (забыл переключить раскладку) и ждешь, пока ничего не найдется, чтобы снова искать.
3. Поиск нескольких слов, разделенных пробелом. Тут возможны варианты как искать: ищем любое из слов в любой из колонок или ищем записи, в которых присутствуют все слова (могут быть в разных колонках).


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: SearchPanel новые возможности
СообщениеДобавлено: 04 окт 2016, 16:58 
Не в сети

Зарегистрирован: 27 янв 2012, 09:40
Сообщений: 65
Откуда: Питер
Полностью поддерживаю по все пунктам.


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: SearchPanel новые возможности
СообщениеДобавлено: 04 окт 2016, 17:46 
Не в сети
Администратор

Зарегистрирован: 19 дек 2011, 17:40
Сообщений: 837
Добрый день.

Цитата:
1. Поиск по таймеру. Т.е., пока идет набор символов, искать не надо, лучше подождать. Актуально на больших наборах данных.

В текущей версии примерно так работает. Если во время поиска грид определяет наличие нажатой клавиши, то поиск прерывается.

Цитата:
2. Прерывание поиска нажатием Esc. Бывает, напишешь в поиск всякий ерунды (забыл переключить раскладку) и ждешь, пока ничего не найдется, чтобы снова искать.

Примем к рассмотрению.

Цитата:
3. Поиск нескольких слов, разделенных пробелом. Тут возможны варианты как искать: ищем любое из слов в любой из колонок или ищем записи, в которых присутствуют все слова (могут быть в разных колонках).

Уже реализовано в виде Демо проекта. См. <EhLib>\Demos\DBGridEh.SearchPanel\
закладка Demo3


Вложения:
sshot-1.png
sshot-1.png [ 25.24 KiB | Просмотров: 4859 ]

_________________
Best regards
Admin
Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: SearchPanel новые возможности
СообщениеДобавлено: 05 окт 2016, 06:00 
Не в сети

Зарегистрирован: 21 дек 2012, 09:32
Сообщений: 53
1. Не совсем такое поведение подразумевалось.
Попробуйте на примере MainDemo.Exe - Working with huge data.
Если в searchpanel написать что-то по-русски (в dataset нет данных на русском), то хорошо видно, что на каждую букву происходит поиск (заметно торможение).
Если бы поиск запускался по таймеру, то этого можно было бы избежать.


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: SearchPanel новые возможности
СообщениеДобавлено: 11 ноя 2016, 10:53 
Не в сети
Администратор

Зарегистрирован: 19 дек 2011, 17:40
Сообщений: 837
Добрый день.

В новой сборке 9.0.031 изменили способ прерывания при поиске в SearchPanel.

* Изменение: В DBGridEh в SearchPanel изменен режим поиска. При поиске в таблице с большим количеством данных, поиск автоматически прерывается и возобновляется по мере набора текста в редакторе. Долгий поиск можно прервать клавишей Esc.

Проверьте, пожалуйста, насколько получилось удобно.

_________________
Best regards
Admin


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: SearchPanel новые возможности
СообщениеДобавлено: 22 дек 2016, 11:31 
Не в сети

Зарегистрирован: 21 дек 2012, 09:32
Сообщений: 53
Ваших правок недостаточно. Прерывание поиска всё еще тормозит.
Могу предложить на рассмотрение наше решение:
Код:
procedure TCustomDBGridEh.SetSearchFilter(const FilterStr: String);
...
begin
  FSearchFilter := FilterStr;
  if IsAnyKeyPress then  // добавлено
    Exit;                // добавлено
...
end

procedure TCustomDBGridEh.SearchFilterEvent(DataSet: TDataSet; var Accept: Boolean);
begin
...
  Accept := False;
  if IsAnyKeyPress then  // добавлено
    Exit;                // добавлено
...
end

или вы можете сами решить куда еще нужно поставить проверки.

Про поиск по таймеру думали? Когда пользователь знает что ищет и хочет ввести слово для поиска целиком, то не надо пытаться искать каждую букву и прерывать поиск, потому что нажата следующая буква. Гораздо проще выждать n-ное количество времени и один раз поискать.


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: SearchPanel новые возможности
СообщениеДобавлено: 01 янв 2017, 03:43 
Не в сети

Зарегистрирован: 21 дек 2011, 18:48
Сообщений: 1546
Добрый день.

Цитата:
Если в searchpanel написать что-то по-русски (в dataset нет данных на русском), то хорошо видно, что на каждую букву происходит поиск (заметно торможение).


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

_________________
Best regards
EhLib support Team


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: SearchPanel новые возможности
СообщениеДобавлено: 03 янв 2017, 08:07 
Не в сети

Зарегистрирован: 21 дек 2012, 09:32
Сообщений: 53
Понял в чем отличие вашего теста от нашего.
Если вы включите FilterOnTyping в примере "Working with huge data", то получите тормоза во всей красе.

Кстати, наших правок тоже оказалось недостаточно, так что вопрос остается открытым.


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: SearchPanel новые возможности
СообщениеДобавлено: 07 янв 2017, 11:58 
Не в сети

Зарегистрирован: 21 дек 2011, 18:48
Сообщений: 1546
Добрый день.

Мы добавили возможность прерывания фильтрации в сборку EhLib 9.0 Build 9.0.037.
Теперь возможность изменения текста без задержки в SearchPanel должна работать и в режиме FilterOnTyping.

_________________
Best regards
EhLib support Team


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: SearchPanel новые возможности
СообщениеДобавлено: 24 янв 2017, 10:57 
Не в сети

Зарегистрирован: 21 дек 2012, 09:32
Сообщений: 53
Добрый день.
Чтобы закончить тему с поиском хотелось бы уточнить вопрос
Код:
3. Поиск нескольких слов, разделенных пробелом. Тут возможны варианты как искать: ищем любое из слов в любой из колонок или ищем записи, в которых присутствуют все слова (могут быть в разных колонках).

Насколько я понял, ваш advanced поиск находится еще в стадии концепта (в виде демо). Он реализован в варианте, когда под условие попадают любые данные, где есть хотя бы одно из слов. Назовем вариант "ИЛИ".
Хочется еще вариант "И", где слова задаются так же через пробел, но ищутся только те строки данных, где есть все эти слова, причем они могут встречаться в разных колонках.
Смысл такого поиска в том, что мы может поискать "инженер Иван", что покажет нам всех по фамилии Иванов или по имени Иван, должность которых содержит "инженер". Ну это упрощенно.


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: SearchPanel новые возможности
СообщениеДобавлено: 25 янв 2017, 01:01 
Не в сети

Зарегистрирован: 21 дек 2011, 18:48
Сообщений: 1546
Добрый день.

Через события
SearchPanel.OnSearchEditChange
SearchPanel.OnCheckCellHitSearch
SearchPanel.OnGetHighlightStrings
можно реализовать почти любой логически-обоснованный метод поиска в гриде.

Ниже приведен пример реализации событий для поиска по описанному вами алгоритму в примере
<EhLib archive>\Demos\DBGridEh.SearchPanel

Код:
unit Frame3;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Types,
  Dialogs, StrUtils, DBGridEhGrouping, ToolCtrlsEh, DBGridEhToolCtrls,
  MemTableDataEh, Db, StdCtrls, MemTableEh, GridsEh, DBGridEh, ExtCtrls,
  Mask, DBCtrlsEh, DynVarsEh, EhLibVCL, DBAxisGridsEh, ComCtrls;

type
  TfrFrame3 = class(TFrame)
    MemTableEh1: TMemTableEh;
    DataSource1: TDataSource;
    PageControl1: TPageControl;
    TabSheet1: TTabSheet;
    TabSheet2: TTabSheet;
    DBMemoEh1: TDBMemoEh;
    DBGridEh1: TDBGridEh;
    Panel2: TPanel;
    Label2: TLabel;
    procedure DBGridEh1SearchPanelCheckCellHitSearch(Grid: TCustomDBGridEh;
      Column: TColumnEh; var Accept: Boolean);
    procedure DBGridEh1SearchPanelGetHighlightStrings(
      Grid: TCustomDBGridEh; Column: TColumnEh;
      var Strings: TStringDynArray);
    procedure DBGridEh1SearchPanelSearchEditChange(Grid: TCustomDBGridEh;
      SearchEdit: TDBGridSearchPanelTextEditEh);
  private
    { Private declarations }
  public
    { Public declarations }
    FSearchStrArr: TStringDynArray;
    function WordPresentInRecord(s: String): Boolean;
    constructor Create(AOwner: TComponent); override;
  end;

implementation

{$R *.dfm}

function FindDelimiter(const Delimiters, S: string; StartIdx: Integer = 1): Integer;
var
  Stop: Boolean;
  Len: Integer;
begin
  Result := 0;

  Len := Length(S);
  Stop := False;
  while (not Stop) and (StartIdx <= Len) do
    if IsDelimiter(Delimiters, S, StartIdx) then
    begin
      Result := StartIdx;
      Stop := True;
    end
    else
      Inc(StartIdx);
end;

function SplitString(const S, Delimiters: string): TStringDynArray;
var
  StartIdx: Integer;
  FoundIdx: Integer;
  SplitPoints: Integer;
  CurrentSplit: Integer;
  i: Integer;
begin
  Result := nil;

  if S <> '' then
  begin
    SplitPoints := 0;
    for i := 1 to Length(S) do
      if IsDelimiter(Delimiters, S, i) then
        Inc(SplitPoints);

    SetLength(Result, SplitPoints + 1);

    StartIdx := 1;
    CurrentSplit := 0;
    repeat
      FoundIdx := FindDelimiter(Delimiters, S, StartIdx);
      if FoundIdx <> 0 then
      begin
        Result[CurrentSplit] := Copy(S, StartIdx, FoundIdx - StartIdx);
        Inc(CurrentSplit);
        StartIdx := FoundIdx + 1;
      end;
    until CurrentSplit = SplitPoints;

    Result[SplitPoints] := Copy(S, StartIdx, Length(S) - StartIdx + 1);
  end;
end;

constructor TfrFrame3.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
//  Text := 'Use Full Filter Panel facilities when the Grid is connected to TMemTableEh. Filtering in a selected area is supported';
end;

function TfrFrame3.WordPresentInRecord(s: String): Boolean;
var
  i: Integer;
  ColText: String;
  Pos: Integer;
begin
  Result := False;
  s := NlsUpperCase(s);
  for i := 0 to DBGridEh1.Columns.Count-1 do
  begin
    ColText := NlsUpperCase(DBGridEh1.Columns[i].DisplayText);
    Pos := PosEx(s, ColText);
    if Pos > 0 then
    begin
      Result := True;
      Break;
    end;
  end;
end;

procedure TfrFrame3.DBGridEh1SearchPanelCheckCellHitSearch(
  Grid: TCustomDBGridEh; Column: TColumnEh; var Accept: Boolean);
var
  S, SubStr: String;
  Pos: Integer;
  i: Integer;
begin
  Accept := False;
  if Length(FSearchStrArr) = 0 then Exit;
  S := NlsUpperCase(Column.DisplayText);
  Accept := True;
  for i := 0 to Length(FSearchStrArr)-1 do
  begin
    if not WordPresentInRecord(FSearchStrArr[i]) then
    begin
      Accept := False;
      Break;
    end;
  end;
  if Accept then
  begin
    for i := 0 to Length(FSearchStrArr)-1 do
    begin
      SubStr := NlsUpperCase(FSearchStrArr[i]);
      Pos := PosEx(SubStr, S);
      if Pos > 0 then
      begin
        Accept := True;
        Break;
      end else
        Accept := False;
    end;
  end;
end;

procedure TfrFrame3.DBGridEh1SearchPanelGetHighlightStrings(
  Grid: TCustomDBGridEh; Column: TColumnEh; var Strings: TStringDynArray);
var
  Accept: Boolean;
  i: Integer;
begin
  Accept := True;
  for i := 0 to Length(FSearchStrArr)-1 do
  begin
    if not WordPresentInRecord(FSearchStrArr[i]) then
    begin
      Accept := False;
      Break;
    end;
  end;
  if Accept then
    Strings := FSearchStrArr;
end;

//procedure TfrFrame3.DBGridEh1SearchPanelCheckCellHitSearch(
//  Grid: TCustomDBGridEh; Column: TColumnEh; var Accept: Boolean);
//var
//  S, SubStr: String;
//  Pos: Integer;
//  i: Integer;
//begin
//  S := NlsUpperCase(Column.DisplayText);
//  for i := 0 to Length(FSearchStrArr)-1 do
//  begin
//    SubStr := NlsUpperCase(FSearchStrArr[i]);
//    Pos := PosEx(SubStr, S);
//    if Pos > 0 then
//    begin
//      Accept := True;
//      Break;
//    end else
//      Accept := False;
//  end;
//end;

//procedure TfrFrame3.DBGridEh1SearchPanelGetHighlightStrings(
//  Grid: TCustomDBGridEh; Column: TColumnEh; var Strings: TStringDynArray);
//begin
//  Strings := FSearchStrArr;
//end;

procedure TfrFrame3.DBGridEh1SearchPanelSearchEditChange(
  Grid: TCustomDBGridEh; SearchEdit: TDBGridSearchPanelTextEditEh);
begin
  FSearchStrArr := SplitString(SearchEdit.Text, ' ');
end;

end.

_________________
Best regards
EhLib support Team


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: SearchPanel новые возможности
СообщениеДобавлено: 27 авг 2018, 11:14 
Не в сети

Зарегистрирован: 21 дек 2012, 09:32
Сообщений: 53
Подниму старую тему.

Вы сделали хорошие обработчики SearchPanel для организации всевозможного поиска. Почему бы не сделать еще один шаг и добавить пропертю в SearchPanel которая бы говорила какой режим поиска использовать: стандартный, продвинутый по "или" (ищутся строки, в который присутствует хотя бы одно слово из SearchPanel), продвинутый по "и" (ищутся строки, в который присутствуют все слова из SearchPanel). Примеры реализации этих поисков вы сами приводили в этой ветке. Если бы они были встроены в сам грид, было бы просто здорово.

Второе. Во вложенном файле демонстрация некорректного поведения при фильтрации данных. Пояснение в видео: В SearchPanel включен FilterOnTyping. Попеременно зажимаем любую букву и Backspace. Повторяем несколько раз. Последним зажимаем Backspace. Наблюдаем тормоза. Такое ощущение, что SearchPanel применяет фильтрацию несколько раз, не дожидаясь окончания изменения строки поиска. Хочется, чтобы фильтрация запускалась по окончании изменений в строке поиска.


Вложения:
search.avi.7z [240.38 KiB]
Скачиваний: 110
Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: SearchPanel новые возможности
СообщениеДобавлено: 24 дек 2018, 10:13 
Не в сети

Зарегистрирован: 21 дек 2012, 09:32
Сообщений: 53
Господа разработчики.
Был бы вам ужасно благодарен, если бы вы реализовали вот это:
Цитата:
Вы сделали хорошие обработчики SearchPanel для организации всевозможного поиска. Почему бы не сделать еще один шаг и добавить пропертю в SearchPanel которая бы говорила какой режим поиска использовать: стандартный, продвинутый по "или" (ищутся строки, в который присутствует хотя бы одно слово из SearchPanel), продвинутый по "и" (ищутся строки, в который присутствуют все слова из SearchPanel). Примеры реализации этих поисков вы сами приводили в этой ветке. Если бы они были встроены в сам грид, было бы просто здорово.


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: SearchPanel новые возможности
СообщениеДобавлено: 23 дек 2022, 13:28 
Не в сети

Зарегистрирован: 23 дек 2022, 12:36
Сообщений: 1
Предложенный 25.01.2018 EhLibSupport способ поиска нескольких вхождений неплохо работает, правда, с оговоркой: приведенная функция StringSplit наивно полагает, что число слов в строке всегда равно числу разделителей плюс 1. И если в строке присутствуют два-три пробела подряд, или есть пробелы в начале или конце строки, она выдает мусорный результат. Так что я ее переписал, заодно можно выкинуть ненужную теперь функцию FindDelimiter:
Код:
function SplitString(const S: string; const Delimiters: string=' '): TStringDynArray;
var
   argLength, i, WordCount, StartIdx: Integer;
begin
  Result:=nil;
  argLength:=Length(S);
  if argLength=0 then Exit;

  StartIdx:=1; // Пропускаем начальные пробелы
  while (StartIdx<=argLength) and IsDelimiter(Delimiters, S, StartIdx) do Inc(StartIdx);
  if StartIdx>argLength then Exit;

  WordCount:=0; // Считаем слова, разделенные пробелами или чем там еще
  i:=StartIdx;
  repeat
    while (i<=argLength) and (not IsDelimiter(Delimiters, S, i)) do Inc(i);
    Inc(WordCount);
    while (i<=argLength) and IsDelimiter(Delimiters, S, i) do Inc(i);
  until i>argLength;
  SetLength(Result, WordCount);

  WordCount:=0; // Заполняем выходной массив
  i:=StartIdx;
  repeat
    while (i<=argLength) and (not IsDelimiter(Delimiters, S, i)) do Inc(i);
    Result[WordCount]:=Copy(S, StartIdx, i-StartIdx);
    Inc(WordCount);
    while (i<=argLength) and IsDelimiter(Delimiters, S, i) do Inc(i);
    StartIdx:=i;
  until i>argLength;
end;

Так оно лучше.


Вернуться наверх
 Профиль  
 
Показать сообщения за:  Сортировать по:  
Начать новую тему Ответить на тему  [ Сообщений: 14 ] 

Часовой пояс: UTC


Кто сейчас на форуме

Сейчас этот форум просматривают: Bing [Bot] и гости: 4


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  
cron
Powered by phpBB® Forum Software © phpBB Group
Русская поддержка phpBB