Работа с Lookup-полями.
Работа с Lookup-полями.
Есть главная таблица, с которой связаны внешними ключами справочники. Для добавления данных в эту таблицу в наборе данных создал lookup-поля и связал из с TDBLoolupCombobox.
Всё бы ничего, но при добавлении в главную таблицу данных, которых нет в справочнике, приходится сначала открывать этот справочник, добавлять в него новые данные и только после этого появляется возможность занесения новых данных в главную таблицу – что очень не удобно.
Есть ли какие-нибудь компоненты для работы с lookup-полями, которые при внесении значения, которого ещё нет в справочнике, автоматически создают новую запись в справочнике и полю главной таблицы присваивают id созданной записи?
Всё бы ничего, но при добавлении в главную таблицу данных, которых нет в справочнике, приходится сначала открывать этот справочник, добавлять в него новые данные и только после этого появляется возможность занесения новых данных в главную таблицу – что очень не удобно.
Есть ли какие-нибудь компоненты для работы с lookup-полями, которые при внесении значения, которого ещё нет в справочнике, автоматически создают новую запись в справочнике и полю главной таблицы присваивают id созданной записи?
Re: Работа с Lookup-полями.
Таких компонент не видел.
И сдаётся мне, что не бывает. Слишком много телепатических действий он должен уметь делать.
Подумай сам, сколько всего нужно сделать для такой операции, даже зная структуру твоего справочника.
И сдаётся мне, что не бывает. Слишком много телепатических действий он должен уметь делать.
Подумай сам, сколько всего нужно сделать для такой операции, даже зная структуру твоего справочника.
Re: Работа с Lookup-полями.
Да, в принципе согласен с вами.WildSery писал(а):Таких компонент не видел.
И сдаётся мне, что не бывает. Слишком много телепатических действий он должен уметь делать.
Подумай сам, сколько всего нужно сделать для такой операции, даже зная структуру твоего справочника.
Мне бы хотелось узнать, как правильно и рационально сделать интерфейс для добавления данных в главную таблицу и как обычно это делают?
Пока я вижу два варианта:
1) поставить кнопку рядом с DBLoolupCombobox.
Но, когда на форме около 10 DBLoolupCombobox’ов и столько же кнопок, интерфейс формы кажется перегруженным.
2) Разместить тупо DBLoolupCombobox и пользователям объяснить, что, если в выпадающем списке нет нужных значений, необходимо сначала открыть справочник и добавить требуемое туда.
Но это тоже получается лишняя морока для пользователей.
А так-то у меня справочники все однотипные и состоят из 2-ух полей - id и значение (varchar). В принципе, можно отказаться от справочников и всё хранить в одной таблице; тогда то, что я задумал можно сделать с помощью DBCombobox. Но, это, наверное, не есть правильно.
Re: Работа с Lookup-полями.
в 1с 7.7 нет таких лукапов. там есть вызов форм справочников. где как раз можно добавить или отредактировать элемент, а затем кликнуть на нем, и он попадет как значение из справочника в нужную форму.
То есть, лукапы обычно предназначены когда надо выбрать, а не редактировать значения.
То есть, лукапы обычно предназначены когда надо выбрать, а не редактировать значения.
ага.1) поставить кнопку рядом с DBLoolupCombobox.
Re: Работа с Lookup-полями.
+1kdv писал(а):ага.1) поставить кнопку рядом с DBLoolupCombobox.
А вот лукап-боксы, в которые можно свои кнопки справа к стандартной стрелке добавлять (и/или заменять стрелку) - есть готовые.
Посмотри, например, набор компонент EhLib, тем более, что есть бесплатная версия, хоть и старая, но с отличным фунцкционалом.
Re: Работа с Lookup-полями.
Спасибо за ответы!
Использование кнопоки для добавления новых данных в справочнике самое лучшее решение и здесь, согласен с WildSery, DBLookupComboboxEh из набора Ehlib – будет самое то. Кнопочка есть в этом луккомбобоксе.
Использование кнопоки для добавления новых данных в справочнике самое лучшее решение и здесь, согласен с WildSery, DBLookupComboboxEh из набора Ehlib – будет самое то. Кнопочка есть в этом луккомбобоксе.
-
- Сообщения: 250
- Зарегистрирован: 25 июл 2007, 21:33
Re: Работа с Lookup-полями.
Смотря что надо. Приведу пример. Есть "простые" справочники - грузов, городов, улиц (они могут быть и не простыми, я привёл исключительно для примера, что в ряде приложений они МОГУТ быть простыми). Так вот, для таких справочников как-то нелогично вызывать окно справочника, в котором нужно добавить новое значение, а потом его и выбрать. Это логично для справочников, где нужно при добавлении записи заполнить несколько полей...
А для простого справочника у меня делается так: пользователь вводит текст в Edit, по мере ввода, под (над) Edit'ом появляется "выпадающее меню" с полями справочника, выбор из которого осуществляется нажатием Enter в Edit'е. А если нужно добавить в справочние, воодится новое значение, и нажимается Tab. Всё. Ну, запрос можно поставить, что значения "ххх" нет в справочнике, добавить? Да/Нет. И на уникальность проверить, потому что для "простых" справочников, обычно уникальность актуальна...
А уж как добавить - вопрос чисто технический, можно по-разному.
А для простого справочника у меня делается так: пользователь вводит текст в Edit, по мере ввода, под (над) Edit'ом появляется "выпадающее меню" с полями справочника, выбор из которого осуществляется нажатием Enter в Edit'е. А если нужно добавить в справочние, воодится новое значение, и нажимается Tab. Всё. Ну, запрос можно поставить, что значения "ххх" нет в справочнике, добавить? Да/Нет. И на уникальность проверить, потому что для "простых" справочников, обычно уникальность актуальна...
А уж как добавить - вопрос чисто технический, можно по-разному.
Re: Работа с Lookup-полями.
Интересная идея.Kotъ-Begemotъ писал(а): А для простого справочника у меня делается так: пользователь вводит текст в Edit, по мере ввода, под (над) Edit'ом появляется "выпадающее меню" с полями справочника, выбор из которого осуществляется нажатием Enter в Edit'е...
А что за компонент вы используете?
Я пытался что-то типо такого сделать, но, если в свойстве DataField какой-либо компонента (хоть DBLookupCombobox или же DBLookupComboboxEh) указать lookup-поле, то вводить такие значения, которых ещё нет в справочнике, просто не получается.
-
- Сообщения: 250
- Зарегистрирован: 25 июл 2007, 21:33
Re: Работа с Lookup-полями.
Обычный Edit для которого обрабатываются OnChange. По мере ввода текста, если еще не открыто показывается окно справочника без заголовка, с шириной, равной ширине Edit'а в котором DBGrid с Align = alClient, но фокус не передаётся в это окно, остаётся в Edit'е и по мере ввода текста в Edit происходит поиск наиоблее подходящего значения справочника. Обработаны так же нажатия клавиш на Edit - стрелка вверх/вниз (Next и Prior для датасета справочника) и Tab - как я уже говорил. При нажатии Enter в Edit подставляется текстовое значение из справочника, а в определённой переменной сохраняется ID записи справочника, после чего окно справочника закрывается, и фокус переходит к следующему компоненту формы.beresa писал(а): Интересная идея.
А что за компонент вы используете?
Я пытался что-то типо такого сделать, но, если в свойстве DataField какой-либо компонента (хоть DBLookupCombobox или же DBLookupComboboxEh) указать lookup-поле, то вводить такие значения, которых ещё нет в справочнике, просто не получается.
То есть здесь не используется Data-aware компонентов на форме ввода. Только в справочнике (Grid, DataSource, который ссылается на Dataset разположенный на DataModule)
Re: Работа с Lookup-полями.
Kotъ-Begemotъ, спасибо большое за подробное объяснение. С воодушевлением принялся за воплощение вашей идеи. И когда сделал так, как вы описали, появилась даже мысль разработать собственный компонент. Поэтому начал разбираться как делаются компоненты, просматривать исходники. В исходнах компонента DBLookupComboboxEh обратил внимание на свойство Style. И оказалось, что если выставить Style равным csDropDownEh (по умолчанию стоит csDropDownListEh), то в поле ввода можно вводить такие значение, которых ещё нет в справочнике. А это как раз мне было и нужно!
Итак, если вы хотите обеспечить максимум комфорта пользователям при добавлении данных в базу, рекомендую следующее.
Во-первых и самое главное – использоватать обязательно компонент DBLookupComboboxEh (данных компонент входит в библиотеку Еhlib, которая для «нашего брата» бесплатна). Далее в свойствах этого компонента установите следующее:
DataSource – источник данных главной таблицы
DataField– поле внешнего ключа, ссылающегося на справочник, в главной таблице
ListSource – источник данных справочника
KeyField – поле первичного ключа в справочнике
ListField – поле, значение которого будут показываться в выпадающем списке.
Style = csDropDownEh. (в этом случае появляется возможность вводить в поле ввода такие значения, которых нет в справочнике);
DropDownBox->AutoDrop = true. (по мере ввода данных автоматически будет появляться выпадающий список).
А теперь исходники:
Я думаю ясно, что событию 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 супер! =D>
Итак, если вы хотите обеспечить максимум комфорта пользователям при добавлении данных в базу, рекомендую следующее.
Во-первых и самое главное – использоватать обязательно компонент 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). Было замечено, что в некоторых случаях событие OnChange у компонента DBLookupComboboxEh срабатывает несколько раз подряд, поэтому в lcbEhKeyDown свойству Tag компонента присваиваем 1, а в конце процедуры lcbEhChange это свойство делаем равным 0;
Процедуры lcbEhKeyDown и lcbEhKeyPress необходимы для того, чтобы при выборе из выпадающего списка каких-либо значений с помощью клавиш стрелка вверх/вниз и нажатии на Enter осуществлялся переход к следующему компоненту. Пришлось использовать процедуру OnKeyDown, т.к. при выборе нажатием на Enter значений из списка, в событие OnKeyPress невозможно перехватить нажатие на Enter (компонент в этом случае при нажатии на Enter присваивает переменной Key код клавиши 0).
Ну и соответственно в OnExit проверяем, было ли введено значение, которого нет в справочнике.
В конце замечу, что описанное выше идеально подходит для простых справочников, т.е. в которых всего два поля - первичный ключ и какое-либо значение. Если имеем дела со справочниками, у которых несколько полей, то без кнопочки, вызывающей форму для редактирования, тут уж не обойтись.
EhLib супер! =D>