Topic: multiselect combobox save

Добрый день уважаемый DriveSoft.
В поисках решения проблемы с мултиселект  сохранением я в двух темах увидел ответ от вас

Мультиселект для ComboBox реализован только для поиска, но в принципе его можно приспособить и для связи многие ко многим используя скрипт.

не могли бы дать пример такого скрипта или же сказать где прочитать об этом

Re: multiselect combobox save

И еще не получается сделать связанные списки когда включен мултиселект у комбобокса

Re: multiselect combobox save

Сделал для вас пример, сохранение значений выбранных в ComboBox


Если подойдет, подумаем и над связанными списками )

Post's attachments

Attachment icon MultiSelect ComboBox many to many.zip 9.44 kb, 617 downloads since 2017-01-10 

Dmitry.

Re: multiselect combobox save

Спасибо вам DriveSoft.
Работает. Попытаюсь связать с моим проектом.
Не хватает только комментариев в коде для полного понимания и не понял почему в конце выскакивает информационное сообщение.
Уважаемый DriveSoft о вы посмотрели ошибку в SQL запросе в этой теме?

Re: multiselect combobox save

комментарии

var
    isChanged: boolean; // необходимо, чтобы знать если пользователь открывал ComboBox


procedure frmEmployee_cbFavoriteFood_OnCloseUp (Sender: string);
begin
    isChanged := True; // запоминаем, если пользователь открывал ComboBox
end;

procedure frmEmployee_OnShow (Sender: string; Action: string);
var
    idEmp: string;
    idFood: integer;
    Results: TDataSet;
    i,c: integer;
begin
    isChanged := False;
    frmEmployee.cbFavoriteFood.SetAllCheckBoxes(false);

    if Action='ShowRecord' then // если окно появилось для показа существующей записи
    begin
        idEmp := IntToStr(frmEmployee.bSave.dbGeneralTableID); // запоминаем id редактируемой записи
        SQLQuery('SELECT id_food FROM FavoriteFood WHERE id_employees='+idEmp, Results); // sql запрос для получения значений поля id_food для редактируемой записи, в этих значениях сохранены выбранные пункты в ComboBox

        while not Results.Eof do // читаем результат sql запрос
        begin
            idFood := Results.FieldByName('id_food').asInteger; // id еды, которую необходимо отметить в ComboBox

            c := frmEmployee.cbFavoriteFood.Items.Count-1;
            for i := 1 to c do // цикл перебора значений в ComboBox для нахождения и отметки необходимого пункта
            begin
                if frmEmployee.cbFavoriteFood.dbIndexToID(i) = idFood then
                    frmEmployee.cbFavoriteFood.ItemsChecked[i] := True;
            end;
                       
            Results.Next; // переход к следующей записи результата sql запроса
        end;

    end;
end;

procedure frmEmployee_bSave_OnAfterClick (Sender: string);
var
    i,c: integer;
    idFood: string;
    idEmp: string;
begin
    if isChanged then // если пользователь открывал ComboBox, значит он там возможно что то изменил
    begin
            idEmp := IntToStr(frmEmployee.bSave.dbGeneralTableID); // запоминаем id редактируемой записи
            SQLExecute('DELETE FROM FavoriteFood WHERE id_employees='+idEmp); // удаляем записи о выбранных значениях в ComboBox
        
            c := frmEmployee.cbFavoriteFood.Items.Count-1;
            for i := 1 to c do // цикл перебора пунктов в ComboBox
            begin
                if frmEmployee.cbFavoriteFood.ItemsChecked[i] then // если пункт в ComboBox выбран, то создаем об этом запись в БД
                begin
                    idFood := IntToStr(frmEmployee.cbFavoriteFood.dbIndexToID(i));
                    SQLExecute('INSERT INTO FavoriteFood (id_employees, id_food) VALUES('+idEmp+','+idFood+')');
                end;
            end;
    end;
end;


чтобы сообщение не выскакивало, найдите в коде и удалите строку ShowMessage
просто забыл сам удалить

Dmitry.

Re: multiselect combobox save

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

Re: multiselect combobox save

Может час поздний о может я не вникаю но опять возникли проблемы.
Сейчас проблема с поиском.
Как сделать чтобы в поиске участвовал комбобокс?

Я чуть-чуть изменил ваш пример.

Post's attachments

Attachment icon MultiCombo.zip 326.2 kb, 460 downloads since 2017-01-12 

Re: multiselect combobox save

Я посмотрел ваш проект, но у вас там все перепутано,
вместо события

procedure frmEmployee_OnShow (Sender: string; Action: string)

;
вы используете

procedure Form1_TableGrid1_OnCellDoubleClick (Sender: string; ACol, ARow: Integer); 

этого также не было в моем примере

idEmp := IntToStr(Form1.TableGrid1.dbItemID);
Dmitry.

9 (edited by beniamin91 2017-01-12 13:23:41)

Re: multiselect combobox save

Я использую

Form1_TableGrid1_OnCellDoubleClick 

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

idEmp := IntToStr(Form1.TableGrid1.dbItemID);

так я получаю id записи с которым надо работать.
Я таким способом хотел приспособить ваш пример к моему проекту.
Сейчас у меня проблема с поиском.
Не знаю как сделать чтобы при выборе food-ов из комбобокса в таблице показывались employees у которых выбраны такие  food.
Проблема в том что кроме комбобокса food в поиске будут участвовать текстбоксы lastname и firstname.

Re: multiselect combobox save

beniamin91
Скачайте последнюю версию программы
https://www.dropbox.com/s/1y0jek64gzfdy … a.zip?dl=0


Доработал, чтобы ComboBox с опцией MultiSelect заработал при поиске. Правда записи в результате поиска могут задваиваться в гриде, пока не могу это поправить

Dmitry.

Re: multiselect combobox save

Дмитрий, подскажите а как будет выглядеть скрипт если на форме 2,3 и т.д комбобокса с multiselect, которые необходимо сохранить. Нужно использовать вложеный цикл? набросал скрипт, но что то он не правильно отрабатывает

procedure frmEmployee_OnShow (Sender: string; Action: string);
var
    idEmp: string;
    idUsers, idFiles: integer;
    Results: TDataSet;
    i,c,d: integer;
begin
    isChanged := False;
    frmEmployee.ComboBox2.SetAllCheckBoxes(false);
    frmEmployee.ComboBox4.SetAllCheckBoxes(false);

    if Action='ShowRecord' then
    begin

        idEmp := IntToStr(frmEmployee.Button10.dbGeneralTableID);
        SQLQuery('SELECT id_Users FROM db_items WHERE id_db_main='+idEmp, Results);
        SQLQuery('SELECT id_db_files FROM db_items WHERE id_db_main='+idEmp, Results);
        while not Results.Eof do
          begin
            idFiles := Results.FieldByName('id_db_files').asInteger;
            d := frmEmployee.ComboBox4.Items.Count-1;
            for i := 1 to d do
            begin
                if frmEmployee.ComboBox4.dbIndexToID(i) = idUsers then
                  frmEmployee.ComboBox4.ItemsChecked[i] := True;
            end;
            Results.Next;
          end;


        while not Results.Eof do
          begin
            idUsers := Results.FieldByName('id_Users').asInteger;
            c := frmEmployee.ComboBox2.Items.Count-1;
            for i := 1 to c do
            begin
                if frmEmployee.ComboBox2.dbIndexToID(i) = idUsers then
                    frmEmployee.ComboBox2.ItemsChecked[i] := True;
            end;

            Results.Next;
          end;


          end;
        end;



procedure frmEmployee_Button10_OnAfterClick (Sender: string);
var
    i,c,d: integer;
    idEmp: string;
    idUsers: string;
    idFiles: string;

begin
    if isChanged then
            idEmp := IntToStr(frmEmployee.Button10.dbGeneralTableID);
            SQLExecute('DELETE FROM db_items WHERE id_db_main='+idEmp);


            c := frmEmployee.ComboBox2.Items.Count-1;
            d := frmEmployee.ComboBox4.Items.Count-1;
            for i := 1 to c do
          begin
            if frmEmployee.ComboBox2.ItemsChecked[i] then
            begin
             idUsers := IntToStr(frmEmployee.ComboBox2.dbIndexToID(i));
             for i := 1 to d do
              begin
              if frmEmployee.ComboBox4.ItemsChecked[i] then
              idFiles := IntToStr(frmEmployee.ComboBox4.dbIndexToID(i));
              SQLExecute('INSERT INTO db_items (id_db_main, id_db_files, id_Users) VALUES('+idEmp+','+idFiles+', '+idUsers+')');
              end ;

             end;

         end;

 end;

Re: multiselect combobox save

pt.82
Для каждого ComboBox-а должна быть отдельная таблица БД, в вашем случае вы сохраняете все в таблице db_items ?
Либо я не понял задумку.

Dmitry.

Re: multiselect combobox save

DriveSoft wrote:

pt.82
Для каждого ComboBox-а должна быть отдельная таблица БД, в вашем случае вы сохраняете все в таблице db_items ?
Либо я не понял задумку.

да хотел сохранять все в таблицу db_items, т.е. если выбрано в первом комбобоксе 2 записи а во втором 3, то в в db_items должно записаться 6 записей. как по аналогии если на форме 2 комбобокса (без mutiselect) то в таблицу запишится одна запись  в поля id_combobox1, id_combobox2 ну т.е id записей таблиц на которые настроены comboboxы и есть связ с записываемой базой.
или я не так понимаю данный скрипт?

Re: multiselect combobox save

pt.82
Не так, просто используйте отдельные таблицы для каждого ComboBox-а

Dmitry.