В таблице необходимо отсортировать данные по дате таким образом: 31.11.2002 02.07.2003 12.01.2004 07.12.2005 20.05.2006 использовал следующий код:
procedure TForm1.N8Click(Sender: TObject); begin DataModule1.BookTable.IndexFieldNames:= 'Дата'; end;
но он сортирует данные в таком порядке: 02.07.2003 07.12,2005 12.01.2004 20.05.2006 31.11.2002 т.е. сортировка происходит по первым числам а не по фактической величине даты. Пробовал таким образом:
procedure TForm1.N8Click(Sender: TObject); begin DataModule1.BookTable.sort:= 'Дата'; end;
но результат тот же самый. Подскажите, как правильно отсортировать данные по дате как описано выше
Зачем тебе сортировать данные в таблице, если можно отсортировать их при отображении (в том же DBGrid-е, например)? Что за база? Способ подключения? Как описано поле "Дата"?
данные в таблице нужно сортировать по дате в том случае, если была использована сортировка по фамилии, чтобы привести таблицу в исходное состояние. MS Access, ADO. Дата-widestring
... Данные из поля "Дата" трактуются как строка (и сортируются как строка, заметь, совершенно правильно), а не как DateTime.
Еще раз: я не совсем понимаю, зачем надо сортировать ТАБЛИЦУ, а не ее отображение? Ну, смотри: есть у меня DBGrid, который отображает мои данные. По щелчку на заголовке пользователь хочет получить данные отсортированные по возрастанию имени. И что, мне из-за этого пересортировывать таблицы? Оно мне надо? А не проще поменять SQL Query для этого DBGrid-а на SELECT ... FROM ... ORDER BY 'Имя' ? А потом, когда надо привести данные в первоначальный вид - просто убрать ORDER BY.
В общем, единственное, что могу посоветовать - поменять тип поля на DataTime (как там он называется-то в Access-е?), чтобы сортировка (и по ORDER BY в том числе) работала правильно. И пересмотри то, как ты взаимодействуешь с базой, не надо лишних действий делать. База ни при чем, работай с отображением.
На форме лежит ADOQuery1, в поле SQL которой прописано: "SELECT * from table1" Она связана с DataSource, а к этому DataSource-у привязан DBGrid. Это начальная ситуация.
Теперь, допустим, мне надо сортировать данные по дате рождения. Что я делаю? Правильно, выполняю вот это:
AdoQuery1.SQL.Clear; AdoQuery1.SQL.Text := 'SELECT * from table1 order by DateOfBirth'; ADOQuery1.Open;
Этого достаточно, чтобы DBGrid стал показывать данные, отсортированные по возрастанию DateOfBirth. Что надо сделать, чтобы вернуться к изначальному состоянию? Правильно, поставить назад SELECT-запрос без части ORDER BY... Вот и все...
После заполнения поля SQL - "SELECT * from table1" при попытке активировать ADOQuery возникает ошибка. В чем тут может быть дело? И получается что для сортировки и возврата в изначальное состояние нужно воспользоваться например двумя кнопками да?
(наверное такой ответ может ввести в заблуждение-я действительно вводил с кавычками). Теперь вроде все правильно, вот только при нажатии кнопки, все данные из таблицы пропадают
(в принципе, можно сделать еще какой-нибудь чекбокс, выбирающий направление сортировки), а вот для возврата в неотсортированное состояние воспользоваться кнопкой.
Добавлено через 59 сек.
Цитата
вот только при нажатии кнопки, все данные из таблицы пропадают
Значит, что-то не так делаешь... ничего не должно пропадать. Тем более из таблицы.
после изменения типа "Дата" с widestring на data/time в MSAccess, перестал работать поисковый фильтр в программе по данным содержащимся в этом столбце. Фильтр построен таким образом:
procedure TForm1.Edit3Change(Sender: TObject); begin if Length(Edit3.Text) > 0 then begin form1adotable1.Filtered := false; form1.adotable1.Filter := '[Дата] LIKE *' + Form1.Edit3.Text + '*'; form1.adotable1.Filtered := true; end else form1.adotable1.Filtered := false; end;
Для полей типа data/time нужно по-другому организовывать условия поиска, или я ошибочно считаю что проблема в этом?
Для полей типа data/time нужно по-другому организовывать условия поиска
Естественно... LIKE работает именно с текстом, с датами работают при помощи других функций. Но "мы пойдем другим путем" (С):
1) OnChange Эдита чуть-чуть меняешь:
procedure TForm1.Edit1Change(Sender: TObject); begin if Length(Edit1.Text) > 0 then begin ADOTable1.Filtered := false; // Отключаешь фильтрацию ADOTable1.Filtered := true; // И тут же опять включаешь... Зачем - чуть ниже поймешь end else ADOTable1.Filtered := false; end;
2) А теперь - зачем нам понадобилось делать столь неразумно: отключать фильтр и тут же его опять включать, ничего не меняя. А вот зачем: есть у TADOTable такое событие - OnFilterRecord, в котором ты можешь задать для активного фильтра критерий, допускать ли запись или фильтровать ее. Вот для того, чтобы при каждом изменении содержимого Edit-а перефильтровывались данные, и надо отключить/включить Filtered. Ну, и сам обработчик:
procedure TForm1.ADOTable1FilterRecord(DataSet: TDataSet; var Accept: Boolean); begin Accept := Pos(Edit1.Text, DataSet.FieldByName('DateOfBirth').AsString) > 0; end;
(я везде оставил свои названия компонентов, поменяешь потом на то, что у тебя...)
Теперь можно в Эдите набирать любые сочетания, хоть так: 10/10/ (что выдаст тебе все данные с датой = 10 октября), хоть вот так: /12/ (что покажет все декабрьские даты). Ну, в общем, как и LIKE
чтото я заметил что такой поиск по дате лишил меня возможности осуществлять поиск по другим, текстовым полям. При вводе в них какого-либо значения из DBGrid пропадают все данные. Это удалось исправить изменив код:
procedure TForm5.IKEFilterRecord(DataSet: TDataSet; var Accept: Boolean); begin if edit1.Focused then Accept := Pos(Edit1.Text, DataSet.FieldByName('DateOfBirth').AsString) > 0; if edit2.Focused then Accept := Pos(Edit2.Text, DataSet.FieldByName('Names').AsString) > 0; end;
Но в этом случае, если я хочу найти имена, начинающиеся с большой буквы, то в поисковое поле я также должен вводить имя с большой буквы. При этом поиск отфильтровывает те же самые имена но начинающиеся с маленькой буквы. Т. е. необходимо учитывать регистр. Как бы исправить эту ситуацию, ничего не потеряв при этом?
Во-первых, не надо делать несколько условий. Дельфи позволяет всегда объединить их в одно. А во-вторых, Приводи обе сравниваемые строки к одному регистру, и сравнивай. Итого:
Accept := (Edit1.Focused and (Pos(Edit1.Text, DataSet.FieldByName('DateOfBirth').AsString) > 0)) or (Edit2.Focused and (Pos(AnsiLowerCase(Edit2.Text), AnsiLowerCase(DataSet.FieldByName('Names').AsString)) > 0));
Можешь использовать AnsiUpperCase вместо ...Lower...
Во-первых, не надо делать несколько условий. Дельфи позволяет всегда объединить их в одно.
Ну, во-первых, не Делфи, а алгебра логики. Делфи просто поддерживает правила, принятые в этой математической дисциплине. А во-вторых, тезис об объединении условий не может быть принят как универсальная рекомендация. В данном конкретном случае это оправдано, но внутри вложенного цикла я бы порекомендовал, наоборот, разделять условия, ставя в начало те, которые чаще всего НЕ будут выполняться (если их вычисление сравнимо по ресурсоемкости). Правильная компоновка условий может в отдельных случаях привести к экономии времени выполнения в тысячи раз.
А во-вторых, тезис об объединении условий не может быть принят как универсальная рекомендация.
А в третьих, разницу между тем, что процитировал ты и "Поскольку Дельфи позволяет объединить несколько условий в одно, то это нужно делать всегда" чувствуешь? Я не призывал (что ты мне приписываешь) использовать данный прием ВСЕГДА.
Я (в отличие от некоторых) говорю только о данном конкретном случае. Пространные рассуждения о "сферических конях в вакууме" (С) - не мой стиль... Всегда что-нибудь пойдет не так: либо вакуум не тот, либо конь не сферическим получится... Так что каждый случай разбирается отдельно.
Ну именно так и надо было написать: "в данном случае я бы порекомендовал...". Твоего авторитета достаточно, чтобы новички любое твое высказывание воспринимали как истину в последней инстанции. На все времена. И это откладывалось на подсозналке. А потом, возможно, через годы на каком-нибудь другом форуме человек будет искренне недоумевать, почему ему советуют разделить условия, тогда как он совершенно точно знает, что в Делфи их нужно, наоборот, объединять. Как в программировании вообще, так и в каждом конкретном языке есть ряд правил, которых надо придерживаться ВСЕГДА, а есть ряд конкретных решений оптимальных для частной задачи. Так вот, хотелось бы, чтобы непосредственно из текста сообщения было ясно, к которому из этих двух случаев относится данное замечание.
Приводи обе сравниваемые строки к одному регистру, и сравнивай
Нет ли каких-нибудь других вариантов? С поиском теперь все в порядке, но при переходе в DBGrid для редактирования найденной записи, стоит только нажать кнопку, запись пропадает. Хотя дело не в этом похоже. Если переходить в найденную запись с помощью мыши, все в порядке. У меня в Edit1 в событии OnKeyPress такой код:
if key=#13 then AdoTable1.FieldByName('Names').FocusControl;
Вот при использовании нажатия Enter при переходе в Dbgrid и начинает все пропадать. Почему переход в DBGrid мышью и Enterом влечет за собой такие разные последствия? Нет. с мышью тоже проблемы, похоже несоответствие гдето раньше(. Всетаки мне кажется что проблемы начались после приведения строк к одному регистру. Все я совершенно запутался... Оставил только поиск по дате (а там без приведения к одному регистру), из DBGrida всеравно все пропадает
Опять начинается то же самое... Это не из-за нововведений, у меня прекрасно отрабатывает:
procedure TForm1.Edit2KeyPress(Sender: TObject; var Key: Char); begin if Key = #13 then begin // Key := #0; // На всякий случай можно бы и это сделать DBGrid1.SelectedField := DBGrid1.DataSource.DataSet.FieldByName('txt'); DBGrid1.SetFocus; end; end;
, а у тебя, как видно, еще что-то, что навешано, мешает нормальной работе обработчика. Здесь я бессилен... Надо во-первых иметь исходники проекта, чтобы найти причину. А во-вторых - время в них копаться. У меня нет ни первого ни второго...