Форум программистов, компьютерный форум, киберфорум
VBA
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.61/23: Рейтинг темы: голосов - 23, средняя оценка - 4.61
0 / 0 / 0
Регистрация: 09.07.2020
Сообщений: 24

Динамическое создание формы с CommandButton в несколько столбцов

15.07.2020, 13:49. Показов 6256. Ответов 71
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый день, уважаемые форумчане! Строго не судите, в VBA я полный "ноль", но пытаюсь сделать небольшую программку. Пытался слепить из разных вариантов на этом и других форумах, многое, что получилось, но застрял на одном вопросе. Суть вопроса: есть некие данные, которые подразделяются на группы. По выбору группы нужно создать динамически форму с кнопками, что бы они были не в один столбец, а в два или три, или более, то есть распределить по всей форме. Количество кнопок зависит от количества данных в группе, их может быть и три, и сто. Вроде понятно объяснил. Файл-пример в приложении. Если сможете помочь, буду очень благодарен.
Вложения
Тип файла: rar Пример (дин. создание формы).rar (28.9 Кб, 19 просмотров)
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
15.07.2020, 13:49
Ответы с готовыми решениями:

Динамическое создание столбцов
Здравствуйте, пишу программу наподобии таблицы. Т.е. сначала есть лишь столбец ФИО, будет подтягиваться список людей и заполнять строки...

Динамическое создание таблицы из нескольких столбцов
Вот код: $(document).ready(function(){ var stolb = 0, product = $('#product'); if(stolb == 0) { ...

Динамическое создание столбцов таблицы или. _?
Доброго времени суток, уважаемые коллеги! Прошу вашей помощи (совета), ибо не имею достаточного опыта в данной теме. Итак, есть...

71
0 / 0 / 0
Регистрация: 09.07.2020
Сообщений: 24
15.07.2020, 18:52  [ТС]
Студворк — интернет-сервис помощи студентам
Спасибо, сейчас попробую.

Добавлено через 2 минуты
КостяФедореев, Спасибо, сейчас попробую.

Добавлено через 10 минут
Цитата Сообщение от КостяФедореев Посмотреть сообщение
Или вы за размеры формы переживаете?
Как уже ответил, переживаю за размер. Хотел сделать, сколько кнопок видно на форме, но не более какого-то кол-ва, такой размер формы. Что бы не было много пустого места или кнопки совсем мелкие, но все в одной форме (как в сказке про скорняка ).
0
Часто онлайн
 Аватар для КостяФедореев
987 / 637 / 280
Регистрация: 09.01.2017
Сообщений: 2,080
15.07.2020, 18:58
Alexey1974, что важней ширина или высота формы?
0
0 / 0 / 0
Регистрация: 09.07.2020
Сообщений: 24
15.07.2020, 19:01  [ТС]
КостяФедореев, Высота может быть стабильная, а ширина увеличиваться или уменьшаться.
0
Часто онлайн
 Аватар для КостяФедореев
987 / 637 / 280
Регистрация: 09.01.2017
Сообщений: 2,080
15.07.2020, 19:53
Alexey1974,
В модуль формы
Visual Basic
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
Private Sub UserForm_Initialize()
Dim n, m, h, aa, a As Long
Dim w
Dim cm As CommandButton, i As Long
h = 510 'Высота формы
a = InputBox("Укажите количество кнопок:", "Запрос данных", "")
n = (Int(Sqr(a))) * 2 'высота кнопок и кол-во
m = Round((a / n + 0.5), 0)
w = (80 + 2) * m
        UserForm1.Height = n * 20
        UserForm1.Width = w + 2
    For j = 0 To m - 1
        For i = 0 To n - 1
            aa = UserForm1.Controls.Count
            If a = aa Then Exit Sub
        Set cm = Me.Controls.Add("Forms.CommandButton.1", "Command" & aa + 1)
            With cm
                .Left = j * 80 + 4
                .Top = i * 18 + 2
                .Height = 18
                .Caption = "Кнопка " & aa + 1
            End With
        Next i
   Next j
End Sub
1
1847 / 1162 / 354
Регистрация: 11.07.2014
Сообщений: 4,107
15.07.2020, 19:54
Alexey1974, идея с созданием программно формы, как мне кажется (и не только мне) не очень удачная. Вам всё равно придется считать высоту и ширину формы по какому-то алгоритму. Если у вас будет уже созданная форма (вручную), то этот расчет можно поместить в файл инициализации этой, уже имеющейся, формы. И в неё можно заранее поместить "стационарные"кнопки. Размеры можно менять в любое время.
0
Часто онлайн
 Аватар для КостяФедореев
987 / 637 / 280
Регистрация: 09.01.2017
Сообщений: 2,080
15.07.2020, 19:54
Все меняется, примерно стремится к квадрату
0
0 / 0 / 0
Регистрация: 09.07.2020
Сообщений: 24
15.07.2020, 20:00  [ТС]
Спасибо всем. Не понимал как это можно сделать со стационарной формой. Конечно прислушаюсь к профессионалам. Завтра буду тестировать, сегодня уже мозг закипает от такого количества новой информации. Еще раз огромное спасибо, завтра отпишусь.
0
Часто онлайн
 Аватар для КостяФедореев
987 / 637 / 280
Регистрация: 09.01.2017
Сообщений: 2,080
15.07.2020, 20:02
Alexey1974, Вы поведайте, что изобретаете, так мы может и алгоритм подскажем правильный.
0
0 / 0 / 0
Регистрация: 09.07.2020
Сообщений: 24
15.07.2020, 20:21  [ТС]
КостяФедореев, Хорошо, спасибо, завтра постараюсь понятно сформулировать идею, а то сейчас пишу и сам не понимаю, что пишу .
0
 Аватар для anton-sf
128 / 64 / 14
Регистрация: 29.03.2015
Сообщений: 265
16.07.2020, 02:27
Alexey1974, сваял пример, на основе вашего файла, правда форма статичная, посмотрите
Вложения
Тип файла: rar Пример (дин. создание формы).rar (28.5 Кб, 6 просмотров)
0
 Аватар для anton-sf
128 / 64 / 14
Регистрация: 29.03.2015
Сообщений: 265
16.07.2020, 02:37
В файле есть:
1 лист с данными и рисованной кнопкой
1 модуль
Кликните здесь для просмотра всего текста
Visual Basic
1
2
3
4
5
6
'Module1
Sub StartExample()
    Dim Result As String
    Result = UserForm1.ShowExt
    MsgBox "Выбрано : " & """" & Result & """"
End Sub

2 класса
Кликните здесь для просмотра всего текста
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
'Class ResultReference
Private sValue As String
Public Event Change()
Public Property Get Value() As String
    Value = sValue
End Property
Public Property Let Value(ByVal Text As String)
    sValue = Text
    RaiseEvent Change
End Property
 
'Class EventOfControls
Public WithEvents ButtonEv As MSForms.CommandButton
Public ResultRef As ResultReference
Private Sub ButtonEv_Click()
    ResultRef.Value = ButtonEv.Caption
End Sub

1 форма
Кликните здесь для просмотра всего текста
Visual Basic
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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
Private Const SM_CXVSCROLL = 2
Private Declare Function GetSystemMetrics Lib "user32.dll" (ByVal nIndex As Long) As Long
Private DiffWidth As Single     'разница между шириной формы и шириной формы предназначенной для использования (минус, возможно, границы окна)
Private DiffHeight As Single    'разница между высотой формы и высотой формы предназначенной для использования (минус заголовок и, возможно, границы окна)
Private OffsetWidth As Single   'отступ от края формы по ширине
Private OffsetHeight As Single  'отступ от края формы по высоте
Private ButtonHeight As Single  'высота кнопки
Private MaxWidth As Single      'максимальная ширина формы
Private MaxHeight As Single     'максимальная высота формы
Private Buttons As Collection   'хранилище классов с кнопками и обработчиками событий
Private WithEvents Result As ResultReference 'сюда класс EventOfControls будет передавать имя нажатой кнопки
 
Public Function ShowExt() As String
    Me.Show
    ShowExt = Result.Value
    Unload Me
End Function
 
Private Sub Result_Change()
    Dim I As Integer
    For I = Buttons.Count To 1 Step -1
        Me.Controls.Remove Buttons(I).ButtonEv.Name
        Buttons.Remove I
    Next
    Me.Hide
End Sub
 
Private Sub UserForm_Initialize()
    Dim I As Integer
    Set Buttons = New Collection
    Set Result = New ResultReference
    'Set Buttons = New Collection
    Me.ScrollBars = fmScrollBarsNone
    DiffWidth = Me.Width - Me.InsideWidth
    DiffHeight = Me.Height - Me.InsideHeight
    OffsetHeight = 0.75 * 12
    OffsetWidth = 0.75 * 12
    MaxWidth = 0.75 * 640 - OffsetWidth * 2 - DiffWidth
    MaxHeight = 0.75 * 480 - OffsetHeight * 2 - DiffHeight
    ButtonHeight = 0.75 * 24
    ComboBox1.Style = fmStyleDropDownList
    'настройка размеров и положения combobox
    ComboBox1.Left = 0 + OffsetWidth
    ComboBox1.Top = 0 + OffsetHeight
    ComboBox1.Width = 0.75 * 160
    ComboBox1.Height = ButtonHeight
    'настройка начальных размеров формы
    Me.Width = OffsetWidth + ComboBox1.Width + OffsetWidth + DiffWidth
    Me.Height = OffsetHeight + ComboBox1.Height + OffsetHeight + DiffHeight
    'заполнение combobox названиями групп
    For I = 1 To List1.UsedRange.Columns.Count
        ComboBox1.AddItem List1.UsedRange(1, I).Value
    Next
End Sub
 
Private Sub ComboBox1_Change()
    Dim I As Integer
    Dim X As Single
    Dim LastX As Single
    Dim Y As Single
    Dim Column As Integer
    Dim DataRowsCount As Integer
    Dim EOC As EventsOfControls
    
    ComboBox1.Enabled = False
    ComboBox1.Visible = False
    
    Column = ComboBox1.ListIndex + 1
    DataRowsCount = WorksheetFunction.CountA(List1.Columns(Column))
    X = OffsetWidth
    Y = OffsetHeight
    LastX = X
    For I = 2 To DataRowsCount
        Set EOC = New EventsOfControls
        Set EOC.ButtonEv = Me.Controls.Add("Forms.CommandButton.1", "CommandButton" & I)
        Set EOC.ResultRef = Result
        EOC.ButtonEv.Caption = List1.Cells(I, Column).Value
        EOC.ButtonEv.AutoSize = True
        EOC.ButtonEv.AutoSize = False
        EOC.ButtonEv.Height = ButtonHeight
        EOC.ButtonEv.Left = X
        EOC.ButtonEv.Top = Y
        Buttons.Add EOC
        X = X + EOC.ButtonEv.Width
        If X > MaxWidth Then
            X = OffsetWidth
            Y = Y + ButtonHeight
            EOC.ButtonEv.Left = X
            EOC.ButtonEv.Top = Y
        Else
            If LastX < X Then LastX = X
        End If
    Next
    Me.Width = LastX + OffsetWidth + DiffWidth
    If Y > MaxHeight Then
        Me.ScrollHeight = Y + ButtonHeight + OffsetHeight
        Y = Int(MaxHeight / ButtonHeight)
        Y = Y * ButtonHeight
        Me.Height = Y + OffsetHeight * 2 + DiffHeight
        Me.Width = Me.Width + 0.75 * GetSystemMetrics(SM_CXVSCROLL)
        Me.ScrollBars = fmScrollBarsVertical
    Else
        Me.Height = Y + ButtonHeight + OffsetHeight + DiffHeight
    End If
End Sub
0
0 / 0 / 0
Регистрация: 09.07.2020
Сообщений: 24
16.07.2020, 09:32  [ТС]
Цитата Сообщение от КостяФедореев Посмотреть сообщение
Private Sub UserForm_Initialize()
Dim n, m, h, aa, a As Long
Dim w
Dim cm As CommandButton, i As Long
h = 510 'Высота формы
a = InputBox("Укажите количество кнопок:", "Запрос данных", "")
n = (Int(Sqr(a))) * 2 'высота кнопок и кол-во
m = Round((a / n + 0.5), 0)
w = (80 + 2) * m
        UserForm1.Height = n * 20
        UserForm1.Width = w + 2
    For j = 0 To m - 1
        For i = 0 To n - 1
            aa = UserForm1.Controls.Count
            If a = aa Then Exit Sub
        Set cm = Me.Controls.Add("Forms.CommandButton.1", "Command" & aa + 1)
            With cm
                .Left = j * 80 + 4
                .Top = i * 18 + 2
                .Height = 18
                .Caption = "Кнопка " & aa + 1
            End With
        Next i
   Next j
End Sub
Доброго дня. Попробовал Ваш вариант, создание формы то, что надо. Только видимо нужно что-то не много подкорректировать. При создании формы обрезается нижняя граница формы, скрывается нижний ряд кнопок. Скрин прикрепил.
Миниатюры
Динамическое создание формы с CommandButton в несколько столбцов  
0
0 / 0 / 0
Регистрация: 09.07.2020
Сообщений: 24
16.07.2020, 09:34  [ТС]
anton-sf, Спасибо, попробовал Ваш вариант, появляется ошибка. Скрин прикрепил.
Миниатюры
Динамическое создание формы с CommandButton в несколько столбцов  
0
Часто онлайн
 Аватар для КостяФедореев
987 / 637 / 280
Регистрация: 09.01.2017
Сообщений: 2,080
16.07.2020, 09:48
Alexey1974,
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Private Sub UserForm_Initialize()
Dim n, m, h, aa, a As Long
Dim w
Dim cm As CommandButton, i As Long
a = InputBox("Укажите количество кнопок:", "Запрос данных", "")
n = (Int(Sqr(a))) * 2 'высота кнопок и кол-во
m = Round((a / n), 0)
w = 80 * m
        UserForm1.Height = n * 18 + 32
        UserForm1.Width = w
    For j = 0 To m - 1
        For i = 0 To n - 1
            aa = UserForm1.Controls.Count
            If a = aa Then Exit Sub
        Set cm = Me.Controls.Add("Forms.CommandButton.1", "Command" & aa + 1)
            With cm
                .Left = j * 80
                .Top = i * 18
                .Height = 18
                .Caption = "Кнопка " & aa + 1
            End With
        Next i
   Next j
End Sub
Исправил
1
 Аватар для anton-sf
128 / 64 / 14
Регистрация: 29.03.2015
Сообщений: 265
16.07.2020, 09:58
Цитата Сообщение от Alexey1974 Посмотреть сообщение
Спасибо, попробовал Ваш вариант, появляется ошибка. Скрин прикрепил.
Попробуйте так:
Visual Basic
1
Private Declare PtrSafe Function GetSystemMetrics Lib "user32.dll" (ByVal nIndex As Long) As Long
Добавлено через 9 минут
Alexey1974, в модуле формы, в процедуре Private Sub ComboBox1_Change(), нужно заменить код в цикле
Кликните здесь для просмотра всего текста
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
    For I = 2 To DataRowsCount
        Set EOC = New EventsOfControls
        Set EOC.ButtonEv = Me.Controls.Add("Forms.CommandButton.1", "CommandButton" & I)
        Set EOC.ResultRef = Result
        EOC.ButtonEv.Caption = List1.Cells(I, Column).Value
        EOC.ButtonEv.AutoSize = True
        EOC.ButtonEv.AutoSize = False
        EOC.ButtonEv.Height = ButtonHeight
        Buttons.Add EOC
        If X + EOC.ButtonEv.Width > MaxWidth Then
            X = OffsetWidth
            Y = Y + ButtonHeight
        End If
        EOC.ButtonEv.Left = X
        EOC.ButtonEv.Top = Y
        X = X + EOC.ButtonEv.Width
        If LastX < X Then LastX = X
    Next

В целом всё неплохо выглядит пока данные одинаковой длинны, но не представляю как это будет выглядеть при данных очень разной длинны
1
0 / 0 / 0
Регистрация: 09.07.2020
Сообщений: 24
16.07.2020, 10:05  [ТС]
КостяФедореев, Отлично, спасибо. В моем случае это не принципиально, но может для кого-то важно будет, в этом варианте при создании одной кнопки на форме ее не видно. Еще раз большое спасибо за помощь.
0
0 / 0 / 0
Регистрация: 09.07.2020
Сообщений: 24
16.07.2020, 10:49  [ТС]
Цитата Сообщение от anton-sf Посмотреть сообщение
в модуле формы, в процедуре Private Sub ComboBox1_Change(), нужно заменить код в цикле
Отлично, спасибо огромное. Работает так как надо. Единственное при закрытии формы через "крестик" выдает ошибку (скрин прикрепил).
Миниатюры
Динамическое создание формы с CommandButton в несколько столбцов  
0
 Аватар для anton-sf
128 / 64 / 14
Регистрация: 29.03.2015
Сообщений: 265
16.07.2020, 11:02
Alexey1974, эта ошибка появилась потому что вы закрыли форму не выбрав значение
Замените
Visual Basic
1
Result = UserForm1.ShowExt
на
Visual Basic
1
If Not Result Is Nothing Then ShowExt = Result.Value
А в модуле, в процедуре StartExample, замените
Visual Basic
1
MsgBox "Выбрано : " & """" & Result & """"
на
Visual Basic
1
2
3
4
5
If Result <> "" Then
    MsgBox "Выбрано : " & """" & Result & """"
Else
    MsgBox "Ничего не выбрано!"
End if
Добавлено через 5 минут
В целом это пример, вам всё равно нужно дорабатывать его под свои нужды
0
Часто онлайн
 Аватар для КостяФедореев
987 / 637 / 280
Регистрация: 09.01.2017
Сообщений: 2,080
16.07.2020, 11:03
Alexey1974, и думаю надо поставить ограничение на количество кнопок, если их будет больше 1000, то форма не влезет на экран.
0
 Аватар для Narimanych
2753 / 1727 / 779
Регистрация: 23.03.2015
Сообщений: 5,452
16.07.2020, 11:05
Интуиция подсказывает, что проблему можно было бы решить совершенно по другому...
Но суть проблемы - под строжайшим секретом.
И надеюсь увидеть решение для 500 кнопок на форме для 15" экрана , исходя из вышеизложенных методов решения...

Интригует....
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
16.07.2020, 11:05

Динамическое создание столбцов таблицы или.?
Доброго времени суток, уважаемые коллеги! Прошу вашей помощи (совета), ибо не имею достаточного опыта в данной теме. Итак, есть...

Динамическое создание столбцов DataGrid-а журнального вида
Доброго времени суток! Допустим, у нас есть обычный DataGrid, который заполняеться из оперделенной коллекции (например, это группа...

Динамическое создание формы
Требуется через js отправить пользователя с пост запросом, адрес статичный но поля нет, (пользователь жмёт на кнопку, идёт запрос на...

Динамическое создание формы
Подскажите плиз, как динамически создавать форму. По задаче - у меня есть форма, на ней кнопки, меню... При нажатии на определённую...

Динамическое создание формы
Всем привет, есть малый вопрос насчет передачи параметров.Пишу уже свои функции. Сейчас пишу функции для работы с несколькими формами....


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

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
Про "Windows must die!"
kumehtar 04.11.2026
Знаете, чет накатило. . . . Когда-то это было почти боевым кличем: мол, нормальный человек сидит на DOS, OS/ 2 или Linux, а вот это вот - Must Die. А теперь человек произносит «мастдай» с усмешкой - и. . .
Красочные поля с номером страницы svg+background-image
russiannick 04.11.2026
Красочные поля с номером страницы не менее важны чем в эпоху бумажных книг. Посему спешу представить почтеннейшей публике этот важный инструмент который эти поля и формирует. В процессе разработки. . .
Вступаем в новую фазу генерации favicons, векторную.
russiannick 02.11.2026
Теперь нет нужды скрывать что используется простой svg. Исходный код изображения помещаем в поле и жмем кнопку. Исходник преобразуется в вид корректный для помещения в favicon или в url(). Нажатие. . .
Генератор паролей (вариант №4)
Maks 01.11.2026
После публикации 3-го варианта генератора паролей, разослал его своим коллегам (с целью оценки), в итоге были получены следующие рекомендации: 1. Вернуть возможность использования знаков | 1 l I;. . .
Генератор паролей (вариант №3)
Maks 30.10.2026
Финальная версия генератора паролей 1С. Доработка решения в этот раз коснулась только визуальной части, а именно, добавлен реквизит ДопПараметры (тип Булево), который скрывает/ отображает реквизиты:. . .
Магическое мышление и магия, современная наука не отличима от магии (говорит ИИ Джемени)
zorxor 30.10.2026
Джемени, расскажи, пожалуйста, что такое магическое мышление, что такое магия, почему современная наука чем-то напоминает магию? Фраза «Любая достаточно развитая технология неотличима от магии». . .
За какое время ИИ может подобрать пароль по хешу (рассказывает Джемени ИИ)
zorxor 30.10.2026
Расскажи, Джемени, если известен хэш МД5, например, за сколько ИИ сможет подобрать соответствующий пароль? Искусственный интеллект (ИИ) может подобрать простой или средний по сложности пароль по. . .
Кто убил Suno? Почему наше солнышко погасло? (диалог с ИИ Джемени)
zorxor 30.10.2026
Как убивали Suno. Хронология. «Убийство» музыкальной нейросети Suno — это затяжной процесс, в котором технологический хайп стартапа разбился о жесткую реальность судебных исков от гигантов. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru