Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Удобная работа с Lookup-полями. 
V
    Опции темы
beresa
Дата 11.9.2008, 09:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 2.7.2007
Где: Чита

Репутация: 1
Всего: 1



Есть главная таблица, с которой связаны внешними ключами справочники. Соответственно для  добавления данных в главную таблицу использую компонент DBLoolupCombobox, который связан с lookup-поля набора данных (Dataset) главной таблицы. 

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

Есть ли какие-нибудь компоненты для работы с lookup-полями, которые при внесении значения, которого ещё нет в справочнике, автоматически создают новую запись в  этом справочнике, а полю главной таблицы (внешний ключ) присваивают id созданной записи? 

PM MAIL WWW   Вверх
Frees
Дата 11.9.2008, 10:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2233
Регистрация: 2.12.2005
Где: Екатеринбург

Репутация: 23
Всего: 54



а что тебе мешает сделать рядом с DBLoolupCombobox кнопку которая будет вызывать диалог добавления новой записи в справочник
помоему это удобнее

еще вариант после открытия дата сета вставить новую запись есл записей 0 



--------------------
Кольцов Виктор Владимирович
PM MAIL ICQ   Вверх
beresa
Дата 11.9.2008, 11:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 2.7.2007
Где: Чита

Репутация: 1
Всего: 1



Цитата(Frees @ 11.9.2008,  10:21)
а что тебе мешает сделать рядом с DBLoolupCombobox кнопку которая будет вызывать диалог добавления новой записи в справочник
помоему это удобнее


Да, у меня сначала так и было -  DBLoolupCombobox, а рядом кнопка. Но, когда на форме около 10 DBLoolupCombobox’ов и столько же кнопок, неуклюже как-то все эти конструкции смотрятся на форме. 
Хочется, конечно, чтобы было всё идеально – минимум манипуляций, максимум удобства при работе с программой.

Цитата(Frees @ 11.9.2008,  10:21)

еще вариант после открытия дата сета вставить новую запись есл записей 0


Немного непонятна идея
PM MAIL WWW   Вверх
pseud
Дата 11.9.2008, 11:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Экспёрт Тыдыщ
***


Профиль
Группа: Завсегдатай
Сообщений: 1175
Регистрация: 18.5.2007
Где: Минск, Беларусь

Репутация: 16
Всего: 40



beresa, придется использовать обычный ComboBox.
если есть желание - говори - опишу алгоритм. а может и код выдумаю.


--------------------
Испытание чужого терпения можно считать успешным, если оно лопнуло...
PM MAIL   Вверх
aleksh
Дата 11.9.2008, 11:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 609
Регистрация: 8.7.2008

Репутация: 2
Всего: 13



надо либо логику пересмотреть, либо дописать автоматическое добавления данных в соответствующий спавочник, тобишь внесение данных в справочник реализуется через автоподстовляемые переменные имя, тип ну т.д.
PM MAIL   Вверх
pseud
Дата 11.9.2008, 11:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Экспёрт Тыдыщ
***


Профиль
Группа: Завсегдатай
Сообщений: 1175
Регистрация: 18.5.2007
Где: Минск, Беларусь

Репутация: 16
Всего: 40



Цитата(pseud @  11.9.2008,  11:17 Найти цитируемый пост)
если есть желание - говори - опишу алгоритм. а может и код выдумаю.


короче что-то типа такого:
Код

procedure CheckSprValue(AComboBox: TComboBox; ASprName: string);
begin
  if AComboBox.ItemIndex > -1 then
    Exit;

  with TQuery.Create(Self) do
  try
    SQL.Add('INSERT INTO ' + ASprName + '(');
    SQL.Add('ID');
    SQL.Add(', NAME');
    SQL.Add(') VALUES (');
    SQL.Add('<тебе виднее>');
    SQL.Add(', ' + AComboBox.Text);
    SQL.Add(')');
    ExecSQL;
  finally
    Free;
  end;

  < обновляем список комбобокса >
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  CheckSprValue(ComboBox1, 'Table1');
  CheckSprValue(ComboBox2, 'Table2');
  CheckSprValue(ComboBox3, 'Table3');

  < дальнейшая проверка и сохранение>
end;


Это сообщение отредактировал(а) pseud - 11.9.2008, 11:56


--------------------
Испытание чужого терпения можно считать успешным, если оно лопнуло...
PM MAIL   Вверх
Frees
Дата 11.9.2008, 12:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2233
Регистрация: 2.12.2005
Где: Екатеринбург

Репутация: 23
Всего: 54



ИМХО не правельно это что бы вот так без подтверждения пользователя записи вбивались, хотя это зависит от того что за справочник


--------------------
Кольцов Виктор Владимирович
PM MAIL ICQ   Вверх
pseud
Дата 11.9.2008, 13:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Экспёрт Тыдыщ
***


Профиль
Группа: Завсегдатай
Сообщений: 1175
Регистрация: 18.5.2007
Где: Минск, Беларусь

Репутация: 16
Всего: 40



Цитата(Frees @  11.9.2008,  12:29 Найти цитируемый пост)
ИМХО не правельно это что бы вот так без подтверждения пользователя записи вбивались, хотя это зависит от того что за справочник


можно при ручном внесении текста в справочное поле и ItemIndex = -1 ненавязчиво сообщать об этом пользователю рядом висящим значком каким-нибудь.


--------------------
Испытание чужого терпения можно считать успешным, если оно лопнуло...
PM MAIL   Вверх
beresa
Дата 11.9.2008, 14:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 2.7.2007
Где: Чита

Репутация: 1
Всего: 1



Цитата(pseud @ 11.9.2008,  11:55)
короче что-то типа такого:
Код

procedure CheckSprValue(AComboBox: TComboBox; ASprName: string);
begin
 ....
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  ....
end;

Да, я такой вариант рассматривал. Думал вместо lookup-ов использовать поля, полученные в результате запроса:


Код

select
  l.id_library,
  pl.s_placepublic,
...
  sub.s_subject
from tb_library l
  left join tbs_placepublic pl on (pl.id_placepublic = l.id_placepablic)
...
  left join tbs_subject sub on (sub.id_subject = l.id_subject)



И соответственно для добавления данных в главную таблицу использовать, как вы и предлагаете, ComboBox.
Тут конечно, возникают некоторые проблемы, но если подумать, то и решение можно найти:
1)    когда редактируем или сохраняем данные, то для каждого поля, связанного внешним ключом со справочником, необходимо определять id записи справочника.  В принципе, эту проблемку можно решить, если вместо обычного ComboBox использовать DBComboBox, который был бы связан с датасетом (набором данных) справочника. Но тогда, когда мы будет открывать форму, необходимо будет для каждого справочника определять запись, связанную с редактируемой записью в главной таблице. Согласен, что тут можно использовать метод Locate набора данных справочника.
2)    Если же мы работаем с lookup-полями, то очень просто становить сохранять изменения, добавлять данные (методы Edit и Append датасетов). Если же сделаем так, что каждый DBComboBox связан с определенным набором данных-справочником, а редактируем и добавляем через них данные в главную таблицу, то здесь уже усложнятся механизм редактирования через такую форму записей главной таблицы.

Да, конечно, при определенных трудозатратах всё это можно реализовать и можно решить вопрос автодобавлении новых записей в подстановочные поля. Но хочется найти уже готовое решение-компонет, который бы позволял просто и легко работать с loolup-полями. 



PM MAIL WWW   Вверх
pseud
Дата 11.9.2008, 14:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Экспёрт Тыдыщ
***


Профиль
Группа: Завсегдатай
Сообщений: 1175
Регистрация: 18.5.2007
Где: Минск, Беларусь

Репутация: 16
Всего: 40



beresa, очень много текста, тем более неформатированного. прочитал - но не вник.

вывод: 
1. реализовать можно и довольно гибко и красиво.
2. такого компонента, который бы позволял просто и легко работать с lookup-полями, на моей памяти нет.
3. такого универсального компонента и быть не может:
- т.к. в оракл записи добавляются по-одному, в информикс по-другому, в парадокс по-третьему
- и откуда ему знать (даже если он и определит что введена отсутствующая запись), что надо написать:
Код

INSERT INTO ... (id...) VALUES (sequence.nextval...);
INSERT INTO ... (id...) VALUES (0...);
INSERT INTO ... (<без ID>...) VALUES (...);
INSERT INTO ... (id...) VALUES ((select max(id) from table1)...);
и т.д.




--------------------
Испытание чужого терпения можно считать успешным, если оно лопнуло...
PM MAIL   Вверх
beresa
Дата 12.9.2008, 02:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 2.7.2007
Где: Чита

Репутация: 1
Всего: 1



pseud, в принципе согласен с вами.
Решил не мучиться и остановиться на кнопочке для добавления новых данных. Как раз в компоненте DBLookupComboboxEh (библиотека Ehlib) есть возможность создания дополнительных кнопок. 

Всем спасибо за ответы!  smile 

Это сообщение отредактировал(а) beresa - 13.9.2008, 07:36
PM MAIL WWW   Вверх
beresa
Дата 16.9.2008, 14:20 (ссылка) |  (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 2.7.2007
Где: Чита

Репутация: 1
Всего: 1



Нашёл оптимальное решение своей проблемы. 
Итак, если вы хотите обеспечить максимум комфорта пользователям при добавлении данных в базу, рекомендую следующее.
Во-первых и самое главное – использоватать обязательно компонент DBLookupComboboxEh (данных компонент входит в библиотеку Еhlib, которая для «нашего брата» бесплатна). Далее в свойствах этого компонента установите следующее:
DataSource – источник данных главной таблицы
DataField– поле внешнего ключа, ссылающегося на справочник, в главной таблице
ListSource – источник данных справочника
KeyField – поле первичного ключа в справочнике
ListField – поле, значение которого будут показываться в выпадающем списке.
Style = csDropDownEh. (в этом случае появляется возможность вводить в поле ввода такие значения, которых нет в справочнике);
DropDownBox->AutoDrop  = true. (по мере ввода данных автоматически будет появляться выпадающий список).

А теперь исходники:
Код
procedure TfMain.lcbEhChange(Sender: TObject);
var
  s: string;
begin
  with TDBLookupComboboxEh(Sender) do begin
    if Tag = 0 then
      exit;

    s := Copy (Text, 0, SelStart);
    //фильтруем
    ListSource.DataSet.Filtered := false;
    ListSource.DataSet.Filter := ListField + ' LIKE ''' + s + '%''';
    ListSource.DataSet.Filtered := true;

    Tag := 0;
end;
end;

procedure TfMain.lcbEhExit(Sender: TObject);
var
  s: string;
begin
with TDBLookupComboboxEh(Sender) do begin
   // если введенного текста нет в справочнике, то добавляем
  if (Text<> ListSource.DataSet.FieldByName(ListField).AsString)
    and (Text <> '') then
  // но сначала спросим у пользователя
  if Application.MessageBox(pChar('Вы действительно хотите' +
    'добавить в справочник "'+ Hint+'" запись "'+Text+'"?'),
    'Подтверждение', MB_ICONINFORMATION + MB_OKCANCEL) = id_ok then
  begin
    // добавляем в справочник
    ListSource.DataSet.Insert;
    ListSource.DataSet.FieldByName(ListField).AsString := Text;
    ListSource.DataSet.Post;
    s := Text;
    ListSource.DataSet.Close;
    ListSource.DataSet.Open;

    // а затем в основную таблицу
    ListSource.DataSet.Locate(ListField, s, [loCaseInsensitive]);
    DataSource.DataSet.FieldByName(DataField).AsInteger :=
      ListSource.DataSet.FieldByName(KeyField).AsInteger;
  end;

    // отмена фильтрации в справочнике
    ListSource.DataSet.Filtered := false;
    ListSource.DataSet.Filter := '';
    ListSource.DataSet.Filtered := true;
end;
end;

procedure TfMain.lcbEhKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
with TDBLookupComboboxEh(Sender) do begin
if Char(key) = #13 then begin
  DataSource.DataSet.FieldByName(DataField).AsString :=
    ListSource.DataSet.FieldByName(KeyField).AsString;
  SelectNext(Sender as TWinControl, True, True);
end;

end;
end;

procedure TfMain.lcbEhKeyPress(Sender: TObject; var Key: Char);
begin
  TDBLookupComboboxEh(Sender).Tag := 1;
  //Чтобы  не было лишнего звука при нажатии на Enter
   if Key = #13 then
     Key := #0;
end;


Я думаю  ясно, что событию OnChange нужно назначить процедуру lcbEhChange, OnKeyDown lcbEhKeyDown и т.д.
Приведу небольшие комментарии.
Фильтрацию данных по мере ввода текста пользователем реализуем в событии OnChange (процедура lcbEhChange). Было замечено, что в некоторых случаях событие OnChange у компонента DBLookupComboboxEh срабатывает несколько раз подряд, поэтому в lcbEhKeyDown свойству Tag  компонента присваиваем 1, а в конце процедуры lcbEhChange это свойство делаем равным 0; 

Процедуры lcbEhKeyDown и lcbEhKeyPress необходимы для того, чтобы при выборе из выпадающего списка каких-либо значений с помощью клавиш стрелка вверх/вниз и нажатии на Enter осуществлялся переход к следующему компоненту. Пришлось использовать процедуру OnKeyDown, т.к. при выборе нажатием на Enter значений из списка, в событие OnKeyPress невозможно перехватить нажатие на Enter (компонент в этом случае при нажатии на Enter присваивает переменной Key код клавиши 0).

Ну и соответственно в OnExit проверяем, было ли введено значение, которого нет в справочнике.

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

Короче, EhLib супер!   smile 
PM MAIL WWW   Вверх
pseud
Дата 16.9.2008, 14:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Экспёрт Тыдыщ
***


Профиль
Группа: Завсегдатай
Сообщений: 1175
Регистрация: 18.5.2007
Где: Минск, Беларусь

Репутация: 16
Всего: 40



Цитата(beresa @  16.9.2008,  14:20 Найти цитируемый пост)
Короче, EhLib супер! 

честно говоря, не увидел почему...
в смысле, TDBLookupCombobox здесь сработал бы также.

Добавлено через 2 минуты и 18 секунд
хотел было поднять репу, но код спорный, когда будет время - опишу что не понравилось

Это сообщение отредактировал(а) pseud - 16.9.2008, 14:32


--------------------
Испытание чужого терпения можно считать успешным, если оно лопнуло...
PM MAIL   Вверх
Frees
Дата 16.9.2008, 14:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2233
Регистрация: 2.12.2005
Где: Екатеринбург

Репутация: 23
Всего: 54



обращение к Text лучше поменять на Trim(Text)



--------------------
Кольцов Виктор Владимирович
PM MAIL ICQ   Вверх
beresa
Дата 16.9.2008, 15:47 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 11
Регистрация: 2.7.2007
Где: Чита

Репутация: 1
Всего: 1



Цитата(pseud)

Цитата(beresa @  16.9.2008,  14:20 Найти цитируемый пост)
Короче, EhLib супер! 

честно говоря, не увидел почему...
в смысле, TDBLookupCombobox здесь сработал бы также.


А смысл в том, что в DBLookupCombobox нет свойства Style. Поэтому, если пользователь захочет ввести текст, которого нет в справочнике, у него это не получится.

А так, в DBLookupComboboxEh присваиваем Style значение DropDownEh и при выходе из компонента определяем, было ли введено такое значение, которого нет в справочнике. 
Это как раз таки то, что мне изначально и нужно было. 


Это сообщение отредактировал(а) beresa - 16.9.2008, 15:51
PM MAIL WWW   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Базы данных и репортинг"
Vit
Петрович

Запрещено:

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами


Обязательно указание:

1. Базы данных (Paradox, Oracle и т.п.)

2. Способа доступа (ADO, BDE и т.д.)


  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи
  • Вопросы по SQL и вопросы по базам данных не связанные с Дельфи задавать здесь

FAQ раздела лежит здесь!


Если Вам помогли и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, Vit, Петрович.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Базы данных и репортинг | Следующая тема »


 




[ Время генерации скрипта: 0.1283 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.