Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > БД в Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 24.01.2016, 19:49   #1
edsjeka
Пользователь
 
Регистрация: 01.01.2016
Сообщений: 98
По умолчанию Как в Delphi реализовать связь многие-ко-многим

Есть таблица по учету заправленных картриджей, в которой есть обычные поля, которые вводит пользователь, есть поля данные для которых берутся из других справочных таблиц (тут я использую поля подстановки для ADOTable и все нормально), но есть одно поле Raboti, которое связано с другой таблицей многие-ко-многим. Использую таблицу DBGrid. Вопрос как можно сделать так, чтобы при нажатии на это поле двойным щелчком мыши или Enter, открывалась справочная таблица, в которой можно было бы выбрать нужные пункты, желательно установив галки на нужных значениях, т.к. вариантов там не много и после закрытия справочной таблицы, все данные сохранились в связывающей таблице и в основной.
Изображения
Тип файла: jpg Снимок3.jpg (18.6 Кб, 149 просмотров)
edsjeka вне форума Ответить с цитированием
Старый 24.01.2016, 20:33   #2
come-on
Участник клуба
 
Регистрация: 21.10.2015
Сообщений: 1,361
По умолчанию

Что конкретно не понятно?
как двойной клик ловить или энтер?
или как отрыть справочник?
или как подставить в поле выбраное значение?
другое?
come-on вне форума Ответить с цитированием
Старый 24.01.2016, 20:40   #3
edsjeka
Пользователь
 
Регистрация: 01.01.2016
Сообщений: 98
По умолчанию

Цитата:
Сообщение от come-on Посмотреть сообщение
Что конкретно не понятно?
как двойной клик ловить или энтер?
или как отрыть справочник?
или как подставить в поле выбраное значение?
другое?
Для начала, не пойму как по нажатию на поле энтер или двойной клик что-то открыть. Как ловить двойной клик или энтер, у меня получается только изменение значения поля, потом нажатие энтер, потом открывается справочник.
edsjeka вне форума Ответить с цитированием
Старый 25.01.2016, 00:59   #4
Dvoishnik
Форумчанин
 
Регистрация: 12.02.2011
Сообщений: 808
По умолчанию

On1DblClick- событие есть такое на DBgrid. по двойному клику будет выполняться что там напишешь.

П.С.и что то не вижу я у вас связи многое ко многим не где.
Терпение!Дежурный экстрасенс скоро свяжется с вами!

Последний раз редактировалось Dvoishnik; 25.01.2016 в 01:02.
Dvoishnik вне форума Ответить с цитированием
Старый 25.01.2016, 06:13   #5
phomm
personality
Старожил
 
Аватар для phomm
 
Регистрация: 28.04.2009
Сообщений: 2,882
По умолчанию

Это, наверное, для видов работ, у единицы обрабатываемой сущности может быть много записей о проделанных работах, в то же время виды проделанных работ не ограничены той единицей, могут быть применимы ко многим. В реальности такая структура делается просто 3й таблицей, где 1 запись на пару объект-работа, но таких записей по одному с разной работой может быть несколько.

Я бы сделал так - завёл проперти (или просто поле или переменную) гласящее, что в данный момент работаем со списком работ по выбранной единице.
Свойство это устанавливать по тому же даблклику, например, проверяя что кликнули в нужной ячейке, и показывал бы TCheckListBox (о нём подробней ниже). По смене фокуса ячейки бокс скрываем и свойство сбрасываем, например, по событию OnColExit. Также может понадобиться свойство - айдишник текущей записи (например, привязываемся к TDataSet.AfterScroll)
При показе бокса (созданого заранее и скрытого) надо вызвать код, который бы получил список всех работ, а также список всех работ данного объекта, заполняем список строками с именами работ, а работы у данного объекта ещё и помечаем галочкой (массивовое свойство Checked у бокса). При скрытии бокса (а лучше по выключению свойства) вызываем код переустановки записей о работах текущего объекта - пробегаем по "массиву" Checked и для добавленных записей инсертим в базу, для убраных - удаляем.
Операции по селекту, инсерту и делиту неплохо бы оформить отдельно - на стороне приложения запросами или на стороне бд хранимыми процедурами.
Например, вот селектящий запрос
Код:
SELECT job.Name, CASE WHEN oj.ID IS NULL THEN 0 ELSE 1 END AS Checked
FROM Objects AS obj 
CROSS JOIN Jobs AS job 
LEFT JOIN ObjectJobs AS oj ON oj.ID_Job = job.ID AND obj.ID = oj.ID_Object
WHERE obj.ID = _нужный_айдишник_объекта_
По инсерту и делиту по желанию надо смотреть - либо отдельно список запоминать в программе что изменилось (это меньше нагрузка на базу, зато менее надёжно при многопользовательском режиме) и только с ним работать, либо циклом по всем работам гнать и сверять с базой (для многопользовательского режима надо ещё некий маркер времени изменений и его проверять, при конфликте можно откатить всю транзакцию и уведомить пользователя)
phomm вне форума Ответить с цитированием
Старый 25.01.2016, 18:58   #6
edsjeka
Пользователь
 
Регистрация: 01.01.2016
Сообщений: 98
По умолчанию

Цитата:
Сообщение от phomm Посмотреть сообщение
Это, наверное, для видов работ, у единицы обрабатываемой сущности может быть много записей о проделанных работах, в то же время виды проделанных работ не ограничены той единицей, могут быть применимы ко многим. В реальности такая структура делается просто 3й таблицей, где 1 запись на пару объект-работа, но таких записей по одному с разной работой может быть несколько.

Я бы сделал так - завёл проперти (или просто поле или переменную) гласящее, что в данный момент работаем со списком работ по выбранной единице.
Свойство это устанавливать по тому же даблклику, например, проверяя что кликнули в нужной ячейке, и показывал бы TCheckListBox (о нём подробней ниже). По смене фокуса ячейки бокс скрываем и свойство сбрасываем, например, по событию OnColExit. Также может понадобиться свойство - айдишник текущей записи (например, привязываемся к TDataSet.AfterScroll)
При показе бокса (созданого заранее и скрытого) надо вызвать код, который бы получил список всех работ, а также список всех работ данного объекта, заполняем список строками с именами работ, а работы у данного объекта ещё и помечаем галочкой (массивовое свойство Checked у бокса). При скрытии бокса (а лучше по выключению свойства) вызываем код переустановки записей о работах текущего объекта - пробегаем по "массиву" Checked и для добавленных записей инсертим в базу, для убраных - удаляем.
Операции по селекту, инсерту и делиту неплохо бы оформить отдельно - на стороне приложения запросами или на стороне бд хранимыми процедурами.
Например, вот селектящий запрос
Код:
SELECT job.Name, CASE WHEN oj.ID IS NULL THEN 0 ELSE 1 END AS Checked
FROM Objects AS obj 
CROSS JOIN Jobs AS job 
LEFT JOIN ObjectJobs AS oj ON oj.ID_Job = job.ID AND obj.ID = oj.ID_Object
WHERE obj.ID = _нужный_айдишник_объекта_
По инсерту и делиту по желанию надо смотреть - либо отдельно список запоминать в программе что изменилось (это меньше нагрузка на базу, зато менее надёжно при многопользовательском режиме) и только с ним работать, либо циклом по всем работам гнать и сверять с базой (для многопользовательского режима надо ещё некий маркер времени изменений и его проверять, при конфликте можно откатить всю транзакцию и уведомить пользователя)
Спасибо, вот это я и хотел узнать, я представлял как это должно выглядеть, но какими средствами это сделать не знал. Попробую реализовать.
edsjeka вне форума Ответить с цитированием
Старый 27.01.2016, 10:36   #7
edsjeka
Пользователь
 
Регистрация: 01.01.2016
Сообщений: 98
По умолчанию

Я не могу понять у какого объекта мне нужно установить даблклик. У DBGrid.Columns событие только PopupMenu, у поля ADOTable тоже нет события DoubleClick. Не пойму как мне указать что я кликнул по какой-то ячейке.
edsjeka вне форума Ответить с цитированием
Старый 27.01.2016, 11:09   #8
Iron Monk
Форумчанин
 
Аватар для Iron Monk
 
Регистрация: 05.10.2007
Сообщений: 478
По умолчанию

Код:
procedure TForm1.DBGrid1CellClick(Column: TColumn);
begin
ShowMessage(DBGrid1.SelectedField.AsString);
end;
Iron Monk вне форума Ответить с цитированием
Старый 27.01.2016, 11:19   #9
edsjeka
Пользователь
 
Регистрация: 01.01.2016
Сообщений: 98
По умолчанию

Цитата:
Сообщение от Iron Monk Посмотреть сообщение
Код:
procedure TForm1.DBGrid1CellClick(Column: TColumn);
begin
ShowMessage(DBGrid1.SelectedField.AsString);
end;
А если мне нужно по нажатию на одно конкретное поле открыать другую форму или какое-то другое действие производить?
edsjeka вне форума Ответить с цитированием
Старый 27.01.2016, 11:43   #10
Iron Monk
Форумчанин
 
Аватар для Iron Monk
 
Регистрация: 05.10.2007
Сообщений: 478
По умолчанию

Цитата:
Сообщение от edsjeka Посмотреть сообщение
А если мне нужно по нажатию на одно конкретное поле открыать другую форму или какое-то другое действие производить?
Код:
procedure TForm1.DBGrid1DblClick(Sender: TObject);
var
  i, n: Integer;
begin
   i:= DBGrid1.SelectedIndex;
   n:= DataSource1.DataSet.RecNo;
   if (i = 2) and (n = 3) then
   Form3.Show;
end;
Iron Monk вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Связь многие ко многим gbolgov Microsoft Office Access 6 30.05.2013 15:22
Связь многие ко многим serox БД в Delphi 3 06.05.2013 22:45
Связь многие-ко-многим Аллен SQL, базы данных 1 05.11.2012 18:17
Связь многие ко многим %$PROregRAMi$t% Microsoft Office Access 9 11.06.2011 23:30
Связь многие ко многим Dirt БД в Delphi 10 11.05.2010 18:28