Доброго времени суток дорогие читатели блога. Хочу поздравить Вас с прошедшими праздниками, пожелать в Новом Году всего самого наилучшего, выполнению всех желаний, чтобы у Вас было все, как Вы задумали. Теперь давайте вернемся непосредственно к самой статье.
Давайте продолжим нашу тему по работе с checkboxes в TDBGrid с использованием вычисляемого поля (предлагаю вспомнить первую часть статьи). В данной статье мы рассмотрим, как можно вообще работать с отмеченными записями подобным образом. То есть, когда у нас значение поля checkboxes хранилось в поле таблицы (True или False, 1 или 0), можно было циклом или запросом выбрать нужные нам записи, здесь ситуация почти похожая.
В данной статье мы рассмотрим следующие нюансы:
- Поиск нужного значения (отмечаем запись checkboxes)
- Удаление отмеченных записей
- Выборка отмеченных записей
- Отметка всех записей отображенных в TDBGrid
- Снятие отметки всех записей отображенных в TDBGrid
На самом деле, подобным образом с отмеченными записями можно производить любые операции. Это связано с тем, что идентификатор этих записей у нас хранятся в универсальном списке TList. А если у нас есть идентификатор записи, то можно его и удалить с таблицы и найти и так далее.
Давайте начнем с того, что нам необходимо поместить идентификаторы отмеченных записей в сам список TList (у меня переменная списка – ListSelect). Тут необходимо определиться, по какому событию мы будем добавлять в наш список идентификаторы записей. Обычно это делается, когда пользователь нажимает на сам checkboxes, но у меня еще сделано таким образом, что выделять (отмечать) запись можно и клавишей пробел (Space) с переходом на последующую строку. Поэтому, отмечать записи можно по любому событию, как будет удобно.
Мы сделаем все стандартно – по нажатию (клику) на запись (самому checkboxes). Для этого выделяем TDBGridEh, переходим во вкладку события и находим событие OnCellClick. Затем на данное событие пишем следующий код:
procedure TForm2.DBGridEh1CellClick(Column: TColumnEh);
var Value : Integer;
begin
if CompareText(Column.Field.FieldName , 'SEL') = 0 then begin
Value := Column.Field.DataSet.FieldByName('ID').AsInteger;
if ListSelect.Count > 0 then
if ListSelect.IndexOf(Pointer(Value)) >=0 then
ListSelect.Delete(ListSelect.IndexOf(Pointer(Value)))
else begin
ListSelect.Add(Pointer(Value));
end else begin
ListSelect.Add(Pointer(Value));
end;
DBGridEh1.Columns[0].Footer.Value:=IntToStr(ListSelect.Count);
Column.Grid.Refresh;
end;
end;
Давайте немного разберем код. Вы помните, что согласно прошлой статье у нас ListSelect: TList;
Код у нас самый простой. Мы получаем идентификатор нашей записи — это поле ID — в моей таблице – уникальное (простым языком – поле-счетчик). Затем проверяем наличие этого идентификатора в нашем списке, если есть и пользователь снимает галочку (отметку) checkboxes, то нам необходимо удалить его и из списка, если в списке его нет, то необходимо добавить в список, чтобы в дальнейшем производить определенные действия с этой записью.
Этот код Вы можете применить на любое событие, чтобы отмеченная запись добавлялась в наш список (ее идентификатор). Я уже говорил, что у меня еще данные код написан на событие TDBGridEh – OnKeyDown. Там я проверяю, если была нажата клавиша Пробел, то также отмечаю запись checkboxes.
Теперь, давайте также добавим идентификатор записи в список при поиске. Например, имеется у нас TEdit, в нем мы будем вводить данные, а программа будет искать совпадения, если имеется, то переходить на эту запись и ставить отметку checkboxes. На событие OnChange компонента TEdit мы напишем следующий код:
procedure TForm2.cxTextEdit1PropertiesChange(Sender: TObject);
var
Value:integer;
begin
try
if ADOQuery1.Active=True then
begin
if ADOQuery1.Locate('JARLIK', cxTextEdit1.Text, [loCaseInsensitive]) then
begin
if CompareText(DBGridEh1.Columns.Items[0].Field.FieldName , 'SEL') = 0 then begin
Value := DBGridEh1.Columns.Items[0].Field.DataSet.FieldByName('ID').AsInteger;
if ListSelect.Count > 0 then
if ListSelect.IndexOf(Pointer(Value)) >=0 then
ListSelect.Delete(ListSelect.IndexOf(Pointer(Value)))
else begin
ListSelect.Add(Pointer(Value));
end else begin
ListSelect.Add(Pointer(Value));
end;
DBGridEh1.Columns[0].Footer.Value:=IntToStr(ListSelect.Count);
DBGridEh1.Columns.Items[0].Grid.Refresh;
end;
end;
except
on e:Exception do
end;
end;
То есть, у нас опять же, все тоже самое, только добавляется условие поиска. Если есть совпадения, то переходим к данной строке и ставим отметку для записи, при повтором поиске этой записи, отметка убирается. Но если не хотите, чтобы отметка убиралась, то достаточно закомментировать или убрать строчку ListSelect.Delete(ListSelect.IndexOf(Pointer(Value))), где из списка удаляется идентификатор записи, при снятии галочки.
Идем дальше. Определить количество отмеченных записей не составит труда. Это можно вытащить из ListSelect.Count. То есть, просто выводим количество элементов в нашем списке.
Теперь переходим к самому интересному. Как же нам обработать все отмеченные записи. Например, давайте сделаем выборку всех записей, которые у нас отмечены checkboxes в нашем TDBGridEh.
Код у нас будет примерно следующим:
procedure TForm4.cxButton1Click(Sender: TObject);
var
s:string;
i:integer;
begin
try
s:='';
for i:=0 to ListSelect.Count-1 do
s:=s+IntToStr(Integer(ListSelect.Items[i]))+',';
if s='' then
Exit;
s:='('+Copy(s, 1, Length(s)-1)+')';
ADOQuery1.SQL.Clear;
ADOQuery1.SQL.Add('SELECT * FROM DOSTAVKA WHERE ID IN '+S);
ADOQuery1.Active:=True;
except
on e:Exception do
end;
end;
Итак, давайте немного разбираться. Я уже Вам говорил, что в списках у нас хранятся уникальные идентификаторы записей в таблице. Зная их, мы можем делать в запросах с записями что угодно. Мы в цикле проходим по всем элементам списка и формируем строку, состоящую из наших идентификаторов записей. Строка будет иметь примерно следующий вид:
100,20,1,101
Далее мы просто делаем запрос, в котором в условии задаем, что необходимо выбирать все записи, поле ID которых содержится в нашей строке s, которая равна s=’100,20,1,101′
В итоге запрос нам должен вернуть 4 записи, идентификаторы (поле ID), которых равняется 100, 20, 1 и 101.
Ну а с записями в запросе можно делать, что Вам захочется. Таким же образом формируются и другие запросы: DELETE, UPDATE. Если надо удалить эти 4 записи, то запрос будет примерно таким:
ADOQuery1.SQL.Clear;
ADOQuery1.SQL.Add('DELETE FROM DOSTAVKA WHERE ID IN '+S);
ADOQuery1.ExecSQL;
В итоге запрос удалит 4 записи. Если необходимо обновить данные, то будет тоже самое с запросом UPDATE. Главное в условие запроса добавлять ID IN (либо другое ваше поле, которое соответствует уникальной записи таблицы)
Ну, давайте уже плавно подходить к концу нашей статьи и напоследок рассмотрим, как можно отметить все записи таблицы (проставить checkboxes) и снять выделение всех записей. Во многих программных продуктах замечали подобный функционал. Например, на панели инструментов имеется кнопка: выделить все и рядом – снять выделение для всех, у меня это выглядит примерно так:
Например, функция, которая у меня отмечает все записи, выглядит следующим образом:
function GridSelectAll(Grid: TDBGridEh): Longint;
var
value:integer;
begin
Result:=0;
Grid.SelectedRows.Clear;
ListSelect.Clear;
with Grid.Datasource.DataSet do
begin
First;
DisableControls;
try
while not EOF do
begin
if CompareText(Form2.DBGridEh1.Columns.Items[0].Field.FieldName , 'SEL') = 0 then begin
Value := Form2.DBGridEh1.Columns.Items[0].Field.DataSet.FieldByName('ID').AsInteger;
if ListSelect.Count > 0 then
if ListSelect.IndexOf(Pointer(Value)) >=0 then
ListSelect.Delete(ListSelect.IndexOf(Pointer(Value)))
else begin
ListSelect.Add(Pointer(Value));
end else begin
ListSelect.Add(Pointer(Value));
end;
end;
inc(Result);
Next;
end;
finally
EnableControls;
Form2.DBGridEh1.Columns[0].Footer.Value:=IntToStr(ListSelect.Count);
end;
end;
end;
Все просто. В цикле проходим по всем записям, отображенных в TDBGridEh и проставляем для них галочки, параллельно занося идентификаторы записей в наш список. Функция снятия отметок со всех записей похожая на предыдущую и выглядит следующим образом:
function GridNotSelectAll(Grid: TDBGridEh): Longint;
var
value:integer;
begin
Result:=0;
Grid.SelectedRows.Clear;
ListSelect.Clear;
with Grid.Datasource.DataSet do
begin
First;
DisableControls;
try
while not EOF do
begin
if CompareText(Form2.DBGridEh1.Columns.Items[0].Field.FieldName , 'SEL') = 0 then begin
Value := Form2.DBGridEh1.Columns.Items[0].Field.DataSet.FieldByName('ID').AsInteger;
if ListSelect.Count > 0 then
if ListSelect.IndexOf(Pointer(Value)) >=0 then
ListSelect.Delete(ListSelect.IndexOf(Pointer(Value)))
end;
inc(Result);
Next;
end;
finally
EnableControls;
Form2.DBGridEh1.Columns[0].Footer.Value:=IntToStr(ListSelect.Count);
end;
end;
end;
Все тоже самое, в цикле проходимся, если запись отмечена, то удаляем из списка и так далее. Хотя я думаю можно сделать намного проще:
ListSelect.Clear;
DBGridEh1.Columns.Items[0].Grid.Refresh;
Очищаем список и обновляем наш грид.
Использовать функции можно: GridNotSelectAll(DBGridEh1) и GridSelectAll(DBGridEh1)
Вот такие вышли у нас две статьи. Мы рассмотрели, как можно отображать checkboxes в гриде с использованием вычисляемого поля и универсального списка. При использовании такой комбинации, пользователи не будут мешать друг другу при работе с отмеченными записями и будут видеть только свои отметки.
Также тут в комментариях сказали, что для чего использовать списки и вычисляемое поле, если есть компонент TMemTableEh из Ehlib и он отлично справляется с этой задачей. Возможно, но не забывайте, что данный способ работает на всех гридах, необязательно устанавливать компоненты Ehlib. Да и не непонятно еще, что больше грузит память: списки или TMemTableEh.
Удачи Вам и до новых встреч!
Похожие записи
Метки: checkboxes, DBGrid, dbgrideh, ehlib
Спасибо!
Всегда пожалуйста! Обращайтесь, если что непонятно, то пишите. Также если хотите, чтобы я рассмотрел какие-то темы определенные по Delphi, то также пишите, предлагайте!
Спасибо.
1. Можно ли ето же сделать в стандартном гриде?
2. Давно интересует пример как создать програму, которая работает на нескольких пк и совместно использует одну базу (mdb). Понимаю, что на центральном пк нужно создать сервер, на локальних клиенты, которые обращаются к серверу и он уже передает в базу. Но нигде нет примера как это реализовать. Желательно еще, чтоб клиенти сами в сети нашли сервер а не прописывать ip адрес на клиентах в ручную.
Постараюсь накидать пример и расписать в статье
«данный способ работает на всех гридах, необязательно устанавливать компоненты Ehlib»
И как на обычном dbgrid такое реализовать не покажете?