Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Не получили письмо с кодом активации?

Официальный форум Simple-Scada.

Автор Тема: Список он же ComboBox V2  (Прочитано 2239 раз)

Серега

  • Постоялец
  • ***
  • Сообщений: 209
    • Просмотр профиля
Список он же ComboBox V2
« : 02 Апреля 2020, 12:09:34 »
Добрый день!
Идея была следующая.
Берем ComboBox и прикручиваем к нему столбец из базы данных. Итак ...
1. В скрипте "Проект полностью запущен":
  - очищаем нужный список
  - запрашиваем из БД количество строк в нужном столбце конкретной таблицы указанной в настройках БД 
Код
RunSQL('SELECT count(*) FROM ways', nil, 150);
2. В скрипте "Выполнен SQL запрос" переменной  присваиваем значение количества строк через Case DataSet.Tag of
Код
150 : tblCountWays.Value := DataSet[0].AsInt;
3. В глобальном модуле объявляем процедуру вот такую:
Код
procedure ReadyComboBox (CountWaysInTbl:TM_Variable;
                         SelectedComboBox:TM_ComboBox;
                         DataSetX:TM_DataSet);
var
i:integer;
begin
SelectedComboBox.Clear;
for i := 0 to CountWaysInTbl.AsInt - 1 do
  SelectedComboBox.AddItem(DataSet[i].AsStr);
end;
4. Далее делаем универсальный скрипт:
Код
RunSQL('SELECT id_ways FROM etp_tc_insat.ways', nil, 151);
и вешаем его на OnClick нужного ComboBox
5. Далее в скрипте "Выполнен SQL запрос" вызываем через Case DataSet.Tag of глобальную функцию:
Код
151 : ReadyComboBox(tblCountWays, cbWayEnter, DataSet);
И вот тут выскакивает ошибка с указанием на строку в глобальном модуле SelectedComboBox.AddItem(DataSet [count].AsStr);
И задумка не работает. Можете помочь.
Жду вопросов и предложений

pan2000

  • Постоялец
  • ***
  • Сообщений: 170
    • Просмотр профиля
Re: Список он же ComboBox V2
« Ответ #1 : 03 Апреля 2020, 18:38:49 »
     Здравствуйте!
 
  Для заполнения списка из БД вполне можно обойтись обработкой запроса к БД, составленного таким образом, что данные для заполнения списка будут расположены в первом поле (с индексом 0) результата в DataSet, а ссылка на заполняемый список будет указана в параметрах вызова:
Код: (delphi)
- RunSQL('SHOW TABLES;', ComboBox1, 1);  // заполнить список ComboBox1 именами таблиц БД;

- RunSQL('DESC ' + UTF8ToString(ComboBox1.Text) + ';', ComboBox2, 1);    // список столбцов выбранной таблицы (для запроса DESC - первое поле записи);

- RunSQL('SELECT `' + UTF8ToString(ComboBox2.Text) + '` FROM `' + UTF8ToString(ComboBox1.Text) + '`;', ComboBox3, 1);   // выбранный столбец из выбранной таблицы. 

Фрагмент скрипта "Выполнен SQL-запрос":
Код: (delphi)
 . . .
  1: with DataSet.Sender as TM_ComboBox do begin
       Clear;                                     // очистить список
       while not DataSet.EOF do begin
         AddItem(DataSet.Fields[0].AsStr);        // заполнение списка
         DataSet.Next;                            // следующая запись
       end;
       Enabled := not DataSet.IsEmpty;            // список заполнен, разрешить доступ для непустого списка
     end;
 . . .

Похожий цикл и для заполнения списка из файла.

Пример получения списка значений выбранного столбца из выбранной таблицы текущей БД во вложении.

Серега

  • Постоялец
  • ***
  • Сообщений: 209
    • Просмотр профиля
Re: Список он же ComboBox V2
« Ответ #2 : 08 Апреля 2020, 08:34:36 »
Спасибо!
В указанном направлении пошли и все заработало как надо.

shaman

  • Новичок
  • *
  • Сообщений: 4
    • Просмотр профиля
Re: Список он же ComboBox V2
« Ответ #3 : 08 Июня 2020, 15:21:54 »
Добрый день. Дабы не плодить темы напишу здесь.
Идея абсолютно та же. Есть таблица, содержимым одного из столбцов необходимо заполнить ComboBox.
Основа алгоритма взята из поста №1, но доработано до такой логики: Мы не просто добавляем очередной пункт в ComboBox, а сравниваем содержимое очередной ячейки таблицы с уже существующими пунктами в ComboBox, т.к. содержимое ячеек в таблице может повторяться.
Сам запрос:
Код: (delphi)
RunSQL('SELECT `ProdName` FROM `archive` ', ComboBox3, 10);

Его обработка:
Код: (delphi)
if DataSet.Tag = 10 then
begin
  with DataSet.Sender as TM_ComboBox do
  begin
    Clear;                                     // очистить список
    AddItem(DataSet.Fields[0].AsStr);
    DataSet.Next;
    while not DataSet.EOF do
    begin
      flag := true;
      for i:= 0 to ItemsCount do
        if Items[i].Text = DataSet.Fields[0].AsUTF8String then
          flag := false;

      if flag then AddItem(DataSet.Fields[0].AsStr);        // заполнение списка
      DataSet.Next;                            // следующая запись
    end;
    Enabled := not DataSet.IsEmpty;            // список заполнен, разрешить доступ для непустого списка
  end;
end;
             
Все работает, за исключением одного момента, если ячейка таблицы содержит строку на русском языке, равенство Items.Text = DataSet.Fields[0].AsUTF8String не выполняется, хотя со строками с латинскими буквами все работает прекрасно. Подскажите, куда смотреть?
« Изменён: 08 Июня 2020, 16:33:57 от Simple-Scada »

Simple-Scada

  • Администратор
  • *****
  • Сообщений: 2998
    • Просмотр профиля
    • Simple-Scada
Re: Список он же ComboBox V2
« Ответ #4 : 08 Июня 2020, 16:47:48 »
Здравствуйте.

Цитировать
за исключением одного момента, если ячейка таблицы содержит строку на русском языке, равенство Items.Text = DataSet.Fields[0].AsUTF8String не выполняется
Видимо равенство не выполняется, т.к. Вы сравниваете разные типы строк UTF8String и string. Ведь Вы в коде заполняете список строками типа string (AddItem(DataSet.Fields[0].AsStr)), а затем сравниваете их c UTF8String (DataSet.Fields[0].AsUTF8String). Они, конечно, не будут совпадать. Нужно заполнять список и сравнивать значения в одном типе UTF8String. А также цикл по строкам списка должен быть таким: "for i:= 0 to ItemsCount - 1 do", т.к. отсчет идёт с нуля. Ещё можно прерывать цикл через Break, когда найдена первая совпадающая строка.  Пример готового кода:
Код: (delphi)
  if DataSet.Tag = 10 then
  begin
    with DataSet.Sender as TM_ComboBox do
    begin
      Clear;                                     // очистить список
      AddItem(DataSet.Fields[0].AsUTF8String);
      DataSet.Next;
      while not DataSet.EOF do
      begin
        flag := true;
        for i:= 0 to ItemsCount - 1 do
          if Items[i].Text = DataSet.Fields[0].AsUTF8String then
          begin
            flag := false;
            Break;
          end;

        if flag then AddItem(DataSet.Fields[0].AsUTF8String);        // заполнение списка
        DataSet.Next;                            // следующая запись
      end;
      Enabled := not DataSet.IsEmpty;            // список заполнен, разрешить доступ для непустого списка
    end;
  end;

pan2000

  • Постоялец
  • ***
  • Сообщений: 170
    • Просмотр профиля
Re: Список он же ComboBox V2
« Ответ #5 : 08 Июня 2020, 23:17:26 »
    Здравствуйте!

 Исключить дублирующие записи можно следующим SQL-запросом:
Код: (delphi)
RunSQL('SELECT `ProdName` FROM `archive` GROUP BY `ProdName`;', ComboBox3, 10);
Сравнение запросов с и без исключения дублирующих записей в проекте из вложении.

shaman

  • Новичок
  • *
  • Сообщений: 4
    • Просмотр профиля
Re: Список он же ComboBox V2
« Ответ #6 : 09 Июня 2020, 10:39:13 »
Здравствуйте.

Видимо равенство не выполняется, т.к. Вы сравниваете разные типы строк UTF8String и string.
Нет, это не сработало. Результат точно такой же, с латиницей все работает как надо, а русский текст не фильтруется.


Исключить дублирующие записи можно следующим SQL-запросом:
А вот это сработало! pan2000, спасибо! И код лаконичней и время выполнения скрипта меньше.