Форум программистов, компьютерный форум, киберфорум
C++ Builder
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.69/13: Рейтинг темы: голосов - 13, средняя оценка - 4.69
 Аватар для blackeangel
19 / 10 / 1
Регистрация: 22.07.2015
Сообщений: 908
Builder 6

Выпадающее меню в DBGrid

05.09.2019, 17:53. Показов 2616. Ответов 19
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Всем доброго времени суток.
Есть прлблема., которую не знаю как решить.
На форме есть таблица, данные которой берутся из mdb через ado. Нужно для определённого столбца сделать выпадайеу (типа combobox), в которой будут данные взятые из файла. Собственно это получилось сделать следующим кодом:
C++
1
MyDBGrid->Columns->Items[6]->PickList->LoadFromFile("Список моделей.txt");
Однако, вся печаль заключается в том, что данные в файле разделены ";". И в выпадайке должно отображаться то, что до ";", а в " ячейку" БД попадать то что после ";".
Пример файла с данными:
Code
1
2
3
Нас много;52-13А
Вас мало;467125
Много макарон; мало супа
При выборе " Нас много" в выпадайке в БД должно записаться "52-13А".
Как?
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
05.09.2019, 17:53
Ответы с готовыми решениями:

Выпадающее меню
Как реализовать вот такое меню?

TrayIcon - организовать выпадающее меню с разными функциями
Не могли бы помочь с данным элементом.Есть ли возможность сделать при нажатии на значок программы в трее выпадающее меню с разными...

ComboBox в StringGrid. Как сделать выпадающее меню недоступным для редактирования?
Добавил в ValueListEditor функцию выпадающего меню для второй колонки, делал по образу и подобию коду в данной теме: ...

19
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33414 / 21523 / 8237
Регистрация: 22.10.2011
Сообщений: 36,923
Записей в блоге: 12
05.09.2019, 20:22
Ну, смотри. Если бы мне понадобилось что-то подобное - я бы сделал вот так:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
// 1. Пишем дополнительный класс для хранения строки (строка должна стать потомком TObject
struct MyStr : public TObject
{
    String Fs;
    MyStr(String s) : TObject(), Fs(s)
    {
    }
};
 
// 2. Читаем файл в список строк, и каждую строку разбиваем на 2 части: до и после точки с запятой.
// Одну из них оставляем в Strings, а вторую заносим в Objects (вот поэтому понадобился класс MyStr, ведь
// Objects может хранить только потомков TObject)
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    TStringList *L = new TStringList;
    L->LoadFromFile("f.txt");
    for(int i = 0; i < L->Count; i++)
    {
        String s = L->Strings[i];
        int p = s.Pos(";");
        L->Objects[i] = new MyStr(Trim(s.SubString(p + 1, s.Length() - p)));
        L->Strings[i] = Trim(s.SubString(1, p - 1));
    }
    DBGrid1->Columns->Items[1]->PickList = L; // и только теперь назначаем в PickList наш список строк. Т.к. TStringList - потомок TStrings, то все нормально, у Билдера не должно быть вопросов
}
 
// 3. А вот теперь - самое интересное: в обработчике OnSetText для поля в НАБОРЕ ДАННЫХ делаем вот так:
void __fastcall TForm1::ADOTable1titleSetText(TField *Sender, const UnicodeString Text)
 
{
    // поскольку для этого поля назначен именно этот пиклист - то можно так и оставить
 
    // Итак: сначала проверяем, есть ли в пиклисте то значение, которое было выбрано.
    // Казалось бы - глупость, не может быть, чтобы его не было, но... Ведь после изменения опять отработает OnSetText, 
    // и вот тогда ничего уже менять не надо будет, потому что в пиклисте значения после точки с запятой нет.
    int ix = DBGrid1->Columns->Items[1]->PickList->IndexOf(Text); 
    if(ix >= 0)
    {
        // Если пришли сюда - то надо поменять выбранное значение на соответствующее ему значение из Objects.
        // Делаем это:
        Sender->AsString = static_cast<MyStr*>(static_cast<TStringList*>(DBGrid1->Columns->Items[1]->PickList)->Objects[ix])->Fs;
    }
}
Ну вот, как-то так. Проверять негде, 6-го Билдера не держу, но причин не работать - не вижу. Проверяй, будут вопросы - добро пожаловать
2
 Аватар для blackeangel
19 / 10 / 1
Регистрация: 22.07.2015
Сообщений: 908
05.09.2019, 21:48  [ТС]
volvo, у меня вопроса сразу 2:
1. Можно ли как то использовать у PickList функцию LoadFromStream для этих целей?
2. Как отловить переход на следующую строчку/столбец в базе(покидание ячейки)?

Тогда можно было б просто распарсить файл, PickList скормить из TStringList, как это было сделано у вас.
А дальше при переходе на новую строку менять перебором значение на значение.
Это у меня первая мысль такая была. Но как вижу, у вас должно "на лету" значение меняться.
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33414 / 21523 / 8237
Регистрация: 22.10.2011
Сообщений: 36,923
Записей в блоге: 12
05.09.2019, 21:53
Цитата Сообщение от blackeangel Посмотреть сообщение
Можно ли как то использовать у PickList функцию LoadFromStream для этих целей?
Нет. Но LoadFromFile - виртуальная функция, можно написать класс-перехватчик для TStringList, и в нем переопределить чтение из файла так, чтобы сразу же разбивать строку на видимую и невидимую части (как это сделано у меня), а потом в основной программе просто один раз вызвать LoadFromFile.

Цитата Сообщение от blackeangel Посмотреть сообщение
Как отловить переход на следующую строчку/столбец в базе(покидание ячейки)?
Я бы не советовал так делать. Лучше - сразу, при изменении, когда отрабатывает OnSetText, заменять одно на другое.
1
 Аватар для blackeangel
19 / 10 / 1
Регистрация: 22.07.2015
Сообщений: 908
05.09.2019, 21:53  [ТС]
Ещё была мысль делать combobox вместо PickList, привязывать его каким то чудом к нужному столбцу, что б он менял размеры так же, и вёл себя так же, и в нём делать подмену, когда он отправляет данные в бд
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33414 / 21523 / 8237
Регистрация: 22.10.2011
Сообщений: 36,923
Записей в блоге: 12
05.09.2019, 21:59
Эту мысль надо изгонять сразу же. Если есть возможность сделать что-то встроенными средствами компонента (а PickList - встроенное средство) - то это всегда предпочтительнее, чем "каким-то чудом" привязывать один компонент к определенной части другого. В общем, я написал, что сделал бы я. Решать - тебе. Хочешь - бери мою идею. Не хочешь - делай по своему.
0
 Аватар для blackeangel
19 / 10 / 1
Регистрация: 22.07.2015
Сообщений: 908
05.09.2019, 22:09  [ТС]
volvo, идея у вас суперская, да ещё без костылей почти, поэтому, с вашего разрешения, забираю ваш вариант.
Спасибо большое.


Не по теме:
где можно почитать всевозможные "действия" с таблицей типа ADOTable1titleSetText и т.п.?
0
 Аватар для blackeangel
19 / 10 / 1
Регистрация: 22.07.2015
Сообщений: 908
06.09.2019, 08:49  [ТС]
volvo, проверил - что то пошло не так...
Events такого нет, возможно от этого ошибка.
Из прикреплённых - какой должен быть вместо ADOTable1titleSetText?
Миниатюры
Выпадающее меню в DBGrid  
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33414 / 21523 / 8237
Регистрация: 22.10.2011
Сообщений: 36,923
Записей в блоге: 12
06.09.2019, 08:55
Не там ищешь. Надо сначала добавить в Fields все поля, которые у тебя есть в таблице (правый клик мышью, Add all fields), а потом уже искать OnSetText в нужном поле.
0
 Аватар для blackeangel
19 / 10 / 1
Регистрация: 22.07.2015
Сообщений: 908
06.09.2019, 08:57  [ТС]
volvo, Эмми..неее, у меня кол-во столбцов плаваяющее, так же как и столбец к которому текущую задачу применяю.
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33414 / 21523 / 8237
Регистрация: 22.10.2011
Сообщений: 36,923
Записей в блоге: 12
06.09.2019, 09:08
Что значит "плавающее"? Столбец обязан быть в списке Fields, чтобы ты вообще мог с ним работать. Не хочешь добавлять его так - значит придётся писать обработчик, совпадающий по сигнатуре с приведенным мной, и назначать его полю через AdoTable1->Fields->FieldByName("fieldname")->OnSetText перед использованием.

Сами себе усложнят задачу, а потом героически её решают...
0
 Аватар для blackeangel
19 / 10 / 1
Регистрация: 22.07.2015
Сообщений: 908
06.09.2019, 09:21  [ТС]
volvo, то и значит плавающее. Имя столбца может быть другим, данные в файле могут быть другими, расположение столбцов может быть любым. Есть файл настроек, из которого берётся какой столбец выпадающий, какой только для чтения, путь к БД и т.д. и т.п поэтому он чисто физически не может быть добавлен.
Миниатюры
Выпадающее меню в DBGrid  
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33414 / 21523 / 8237
Регистрация: 22.10.2011
Сообщений: 36,923
Записей в блоге: 12
06.09.2019, 09:28
Что, и найден быть не может? Тогда он на фиг не нужен, потому что Билдер работает с полем именно так, как я показал, через FieldByName. А поле, к которому нельзя обратиться - это из области извращений.

И не надо мне показывать код в виде картинки. Во-первых, это запрещено правилами, а во вторых - номера строк все равно не видны. Да и сам h-файл тоже. Я тоже могу показать картинку. На которой все будет компилироваться. И даже видео, где оно будет работать. Легче от этого кому-то будет?
0
 Аватар для blackeangel
19 / 10 / 1
Регистрация: 22.07.2015
Сообщений: 908
06.09.2019, 09:49  [ТС]
volvo, найден, он может быть лишь только тогда, когда подключиться к БД, ну это чисто логически. По номеру из файла настроек можно получить имя столбца.

Добавлено через 2 минуты
Код я не показывал, показывал что нет столбцов и что при попытки добавления - ошибка и её содержимое.

Добавлено через 12 минут
volvo, могу весь проект приложить для того чтоб было понятно о чём я?
0
 Аватар для blackeangel
19 / 10 / 1
Регистрация: 22.07.2015
Сообщений: 908
06.09.2019, 09:57  [ТС]
volvo, вот проект
Вложения
Тип файла: zip test.zip (140.3 Кб, 3 просмотров)
0
 Аватар для blackeangel
19 / 10 / 1
Регистрация: 22.07.2015
Сообщений: 908
06.09.2019, 12:28  [ТС]
volvo, мыслей нет?
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33414 / 21523 / 8237
Регистрация: 22.10.2011
Сообщений: 36,923
Записей в блоге: 12
06.09.2019, 13:31
Сделал свой проект в BCB6 на виртуалке. На форме - DBGrid, две кнопки и два Edit-а. Ну, по коду разберешься. По нажатию одной из кнопок выбирается файл, который будет назначаться как PickList, по нажатию второй - собственно то, что я предлагал. Я чуть-чуть изменил код, теперь он выглядит вот так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
//---------------------------------------------------------------------------
 
#include <vcl.h>
#pragma hdrstop
 
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
}
//---------------------------------------------------------------------------
 
struct MyStr : public TObject
{
    String Fs;
    MyStr(String s) : TObject(), Fs(s)
    {
    }
};
 
// это просто самописный метод, не надо его нигде искать, не забудь только в класс формы добавить прототип.
void __fastcall TForm1::MySetText(TField *Sender, const AnsiString Text)
 
{
    if(Sender->Tag)
    {
        TStringList *picklist = reinterpret_cast<TStringList*>(Sender->Tag);
        int ix = picklist->IndexOf(Text);
        if(ix >= 0)
        {
            Sender->AsString = static_cast<MyStr*>(picklist->Objects[ix])->Fs;
        }
    }
}
 
void __fastcall TForm1::btnGetFileClick(TObject *Sender)
{
    if(OpenDialog1->Execute())
    {
        ed_fileName->Text = OpenDialog1->FileName;
    }
}
//---------------------------------------------------------------------------
 
void __fastcall TForm1::btnAssignPickerClick(TObject *Sender)
{
    TStringList *L = new TStringList;
    L->LoadFromFile(ed_fileName->Text);
    for(int i = 0; i < L->Count; i++)
    {
        String s = L->Strings[i];
        int p = s.Pos(";");
        L->Objects[i] = new MyStr(Trim(s.SubString(p + 1, s.Length() - p)));
        L->Strings[i] = Trim(s.SubString(1, p - 1));
    }
    for(int i = 0; i < DBGrid1->Columns->Count; i++)
    {
        TField *fld = 0;
        if((fld = DBGrid1->Columns->Items[i]->Field) != 0 && fld->FieldName == ed_FieldName->Text)
        {
            DBGrid1->Columns->Items[i]->PickList = L;
            fld->Tag = reinterpret_cast<int>(L);
            fld->OnSetText = MySetText;
        }
    }
}
//---------------------------------------------------------------------------
Вносим имя поля, которое надо обработать, выбираем для него файл и жмем на капу "Assign". Все, в этом поле грида есть пиклист. Как и обещал - привожу скриншот. Все прекрасно работает:

Нужен сам проект - прикреплю проект...

Я обещал скрин, на котором все работает.
Миниатюры
Выпадающее меню в DBGrid  
1
 Аватар для blackeangel
19 / 10 / 1
Регистрация: 22.07.2015
Сообщений: 908
06.09.2019, 13:41  [ТС]
volvo, я не сомневался, что у вас на статически подключеной БД всё заработает) Попробуйте на моём проекте такое же провернуть - не получится ;-)

Это не спор и не вызов)
Но, если вам реально интересен этот момент - вы попробуете.
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33414 / 21523 / 8237
Регистрация: 22.10.2011
Сообщений: 36,923
Записей в блоге: 12
06.09.2019, 14:56
Лучший ответ Сообщение было отмечено blackeangel как решение

Решение

Цитата Сообщение от blackeangel Посмотреть сообщение
Попробуйте на моём проекте такое же провернуть - не получится ;-)
Такой наивный Если бы я был не уверен - я бы не давал этот метод. Смотри:



Все, что изменил - это путь в конфиг файле к БД, и имя пользователя задал вручную. Так что метод-то рабочий, хоть при статическом подключении, хоть при динамическом.
Вложения
Тип файла: zip test.zip (1.55 Мб, 10 просмотров)
1
 Аватар для blackeangel
19 / 10 / 1
Регистрация: 22.07.2015
Сообщений: 908
06.09.2019, 15:27  [ТС]
volvo, да ладно?! Лопни мои глаза, мама родная!
Похоже на то, что с меня пиво
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
06.09.2019, 15:27
Помогаю со студенческими работами здесь

Выпадающее меню. Не фиксируется бордер раздела меню, при использовании подменю
Делаю выпадающее меню, почти все сделал, осталось по сути немного, и не могу закончить. Вот код: ...

Выпадающее меню - разный размер шрифта для разных уровней меню
Есть у меня данный список, но возник вопрос: &quot;как сделать чтобы в надписи буквы1 был шрифт 19px, а в выпадающем меню был шрифт 16px&quot; ...

Как прикрепить выпадающее меню к названию в основном меню
Здравствуйте. Сейчас на сайте есть вертикальное меню, и при наведении на какой-либо его пункт, выпадающее меню появляется в самом верху...

Выпадающее меню
Доброго времени суток. Коллеги, подскажите как осуществить: Есть ImageView, хочется чтобы при нажатии на него разворачивалась...

Выпадающее меню
Я вставила код в виджет &quot;Текст&quot; &lt;div class=&quot;dropdown pull-left&quot;&gt; &lt;button class=&quot;btn btn-warning&quot; type=&quot;button&quot;&gt; ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Знаешь почему 90% людей редко бывают счастливыми?
kumehtar 14.04.2026
Потому что они ждут. Ждут выходных, ждут отпуска, ждут удачного момента. . . а удачный момент так и не приходит.
Фиксация колонок в отчете СКД
Maks 14.04.2026
Фиксация колонок в СКД отчета типа Таблица. Задача: зафиксировать три левых колонки в отчете. Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка) / / . . .
Настройки VS Code
Loafer 13.04.2026
{ "cmake. configureOnOpen": false, "diffEditor. ignoreTrimWhitespace": true, "editor. guides. bracketPairs": "active", "extensions. ignoreRecommendations": true, . . .
Оптимизация кода на разграничение прав доступа к элементам формы
Maks 13.04.2026
Алгоритм из решения ниже реализован на нетиповом документе, разработанного в конфигурации КА2. Задачи, как таковой, поставлено не было, проделанное ниже исключительно моя инициатива. Было так:. . .
Контроль заполнения и очистка дат в зависимости от значения перечислений
Maks 12.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "ПланированиеПерсонала", разработанного в конфигурации КА2. Задача: реализовать контроль корректности заполнения дат назначения. . .
Архитектура слоя интернета для сервера-слоя.
Hrethgir 11.04.2026
В продолжение https:/ / www. cyberforum. ru/ blogs/ 223907/ 10860. html Знаешь что я подумал? Раз мы все источники пишем в голове ветки, то ничего не мешает добавить в голову такой источник, который сам. . .
Подстановка значения реквизита справочника в табличную часть документа
Maks 10.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "ПланированиеПерсонала", разработанного в конфигурации КА2. Задача: при выборе сотрудника (справочник Сотрудники) в ТЧ документа. . .
Очистка реквизитов документа при копировании
Maks 09.04.2026
Алгоритм из решения ниже применим как для типовых, так и для нетиповых документов на самых различных конфигурациях. Задача: при копировании документа очищать определенные реквизиты и табличную. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru