Excel vba ячейка с выпадающим списком

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

Элемент управления ComboBox на пользовательской форме

UserForm.ComboBox – это элемент управления пользовательской формы, предназначенный для передачи в код VBA информации, выбранной пользователем из раскрывающегося списка или введенной с клавиатуры.

ComboBox представляет из себя комбинацию двух элементов управления: текстового поля (TextBox) и списка (ListBox), поэтому его еще называют «комбинированным списком» или «полем со списком». Также ComboBox сочетает в себе свойства этих двух элементов управления.

Изначально комбинированный список прорисовывается на форме в виде текстового поля с кнопкой для отображения раскрывающегося списка. Далее по тексту будем использовать слово «поле» в значении текстового поля в составе элемента управления ComboBox, а словосочетание «раскрывающийся список» – в значении списка в составе элемента управления ComboBox.

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

Элемент управления ComboBox незаменим при больших списках. При списках из нескольких позиций его можно заменить на ListBox, который отображает позиции для выбора сразу после загрузки формы, не требуя дополнительных действий от пользователя.

Свойства поля со списком

Свойство Описание
AutoSize Автоподбор размера комбинированного поля. True – размер автоматически подстраивается под длину выбранной или введенной строки. False – размер элемента управления определяется свойствами Width и Height.
AutoTab Включение автоматической табуляции – передачи фокуса следующему элементу управления при достижении максимального числа символов при значениях свойства MaxLenght > 0. True – автоматическая табуляция включена, False – выключена.
ColumnCount Указывает количество столбцов в раскрывающемся списке. Значение по умолчанию = 1.
ColumnHeads Добавляет строку заголовков в раскрывающийся список. True – заголовки столбцов включены, False – заголовки столбцов выключены. Значение по умолчанию = False.
ColumnWidths Ширина столбцов в раскрывающемся списке. Значения для нескольких столбцов указываются в одну строку через точку с запятой (;).
ControlSource Ссылка на ячейку для ее привязки к элементу управления ComboBox.
ControlTipText Текст всплывающей подсказки при наведении курсора на элемент управления.
Enabled Доступ пользователя к полю и раскрывающемуся списку. True – доступ разрешен, False – доступ запрещен*. Значение по умолчанию = True.
Font Шрифт, начертание и размер текста в поле.
Height Высота элемента управления ComboBox.
Left Расстояние от левого края внутренней границы пользовательской формы до левого края комбинированного списка.
List Позволяет заполнить ComboBox данными из одномерного или двухмерного массива, а также обращаться к отдельным элементам раскрывающегося списка по индексам для записи и чтения.
ListIndex Номер выбранной пользователем строки в раскрывающемся списке. Нумерация начинается с нуля. Если ничего не выбрано, ListIndex = -1.
ListRows Количество видимых строк в раскрытом списке. Если общее количество строк больше ListRows, появляется полоса прокрутки. Значение по умолчанию = 8.
Locked Запрет на отображение раскрывающегося списка, ввод и редактирование данных в поле. True – ввод и редактирование запрещены**, False – ввод и редактирование разрешены. Значение по умолчанию = False.
MatchRequired Задает проверку вводимых в поле строк с элементами списка. True – проверка включена (допускается ввод только строк, совпадающих с элементами списка), False – проверка выключена (допускается ввод любых строк). Значение по умолчанию = False.
MaxLenght Максимальная длина строки в поле. Значение по умолчанию = 0, что означает – ограничений нет.
RowSource Источник строк для раскрывающегося списка (адрес диапазона на рабочем листе Excel).
TabIndex Целое число, определяющее позицию элемента управления в очереди на получение фокуса при табуляции. Отсчет начинается с 0.
Text Текстовое содержимое (значение) поля (=Value).
TextAlign Выравнивание текста в поле: 1 (fmTextAlignLeft) – по левому краю, 2 (fmTextAlignCenter) – по центру, 3 (fmTextAlignRight) – по правому краю.
Top Расстояние от верхнего края внутренней границы пользовательской формы до верхнего края комбинированного списка.
Value Текстовое содержимое (значение) поля (=Text).
Visible Видимость поля со списком. True – ComboBox отображается на пользовательской форме, False – ComboBox скрыт.
Width Ширина элемента управления.

* При Enabled в значении False пользователь не может раскрывать список, а также вводить или редактировать данные в поле.
** Для элемента управления ComboBox действие свойства Locked в значении True аналогично действию свойства Enabled в значении False.

В таблице перечислены только основные, часто используемые свойства поля со списком. Еще больше доступных свойств отображено в окне Properties элемента управления ComboBox, а все методы, события и свойства – в окне Object Browser.

Вызывается Object Browser нажатием клавиши «F2». Слева выберите объект ComboBox, а справа смотрите его методы, события и свойства.

Свойства BackColor, BackStyle, BorderColor, BorderStyle отвечают за внешнее оформление комбинированного списка и его границ. Попробуйте выбирать доступные значения этих свойств в окне Properties, наблюдая за изменениями внешнего вида элемента управления ComboBox на проекте пользовательской формы.

Способы заполнения ComboBox

Используйте метод AddItem для загрузки элементов в поле со списком по одному:

With UserForm1.ComboBox1

  .AddItem «Элемент 1»

  .AddItem «Элемент 2»

  .AddItem «Элемент 3»

End With

Используйте свойство List, чтобы скопировать одномерный массив значений в элемент управления ComboBox:

UserForm1.ComboBox1.List = Array(«Строка 1», _

«Строка 2», «Строка 3», «Строка 4», «Строка 5»)

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

Используйте свойство RowSource, чтобы загрузить в ComboBox значения из диапазона ячеек рабочего листа:

UserForm1.ComboBox1.RowSource = «Лист5!B1:B15»

При загрузке данных из диапазона, содержащего более одного столбца, требуется предварительно указать количество столбцов в комбинированном списке:

With UserForm1.ComboBox1

  ‘Указываем количество столбцов

  .ColumnCount = 5

  .RowSource = «‘Таблица с данными’!A1:E20»

End With

В качестве имени листа используется имя ярлыка. Если имя листа содержит пробелы, оно заключается в одинарные кавычки.

Подробнее о заполнении элемента управления ComboBox вы можете ознакомиться в отдельной статье с наглядными примерами. И еще более подробно – в статье о заполнении ListBox, так как ListBox заполняется теми же способами, что и ComboBox.

Привязка поля со списком к ячейке

Чтобы привязать комбинированный список к ячейке на рабочем листе Excel, необходимо свойству ControlSource присвоить адрес ячейки. Это можно сделать непосредственно в окне Properties элемента управления ComboBox или в коде VBA:

UserForm1.ComboBox1.ControlSource = "Лист1!B2"

Имя листа для составного адреса ячейки берется из названия ярлыка. Если имя листа содержит пробелы, оно заключается в одинарные кавычки. При указании адреса без имени листа, ComboBox привязывается к ячейке на активном листе.

В результате привязки образуется взаимосвязь между свойством Value комбинированного списка и значением ячейки. Все изменения в поле ComboBox дублируются в привязанной ячейке и наоборот, изменения в ячейке приводят к изменению текста в поле.

Чтобы протестировать результаты привязки ячейки к полю со списком ComboBox1, разместите на пользовательской форме UserForm1 еще какой-нибудь элемент управления и запустите следующий код VBA Excel:

Sub Test()

With UserForm1.ComboBox1

  ‘Заполняем список ComboBox1 данными

  .List = Array(«Красный», «Оранжевый», «Желтый», _

  «Зеленый», «Голубой», «Синий», «Фиолетовый»)

  ‘Привязываем ComboBox1 к ячейке «A1»

  .ControlSource = «A1»

  ‘Открываем форму в немодальном окне

End With

  UserForm1.Show 0

End Sub

В результате работы кода пользовательская форма откроется в немодальном окне со значением в поле, скопированном из ячейки «A1» активного листа. Немодальное окно формы позволит редактировать ячейку «A1», не закрывая форму.

Меняйте значение ячейки «A1», нажимайте клавишу «Tab» или «Enter», поле комбинированного списка примет значение ячейки. Меняйте значение поля ComboBox1 с помощью клавиатуры или выбирайте из раскрывающегося списка, нажимайте клавишу «Tab» или «Enter», ячейка «A1» примет значение поля со списком.

Дополнительный элемент управления на форме нужен для передачи ему фокуса нажатием клавиши «Tab» или «Enter», чтобы завершить ввод значения в поле ComboBox1. Иначе новое значение поля будет передано в ячейку «A1» только при закрытии формы.

Значение ComboBox по умолчанию

В раскрывающийся список элемента управления ComboBox1 загружены названия семи основных цветов:

Private Sub UserForm_Initialize()

With Me.ComboBox1

  .List = Array(«Красный», «Оранжевый», «Желтый», _

  «Зеленый», «Голубой», «Синий», «Фиолетовый»)

  ‘Сюда добавляем код вставки значения по умолчанию

End With

End Sub

Есть несколько вариантов сделать так, чтобы при открытии пользовательской формы в поле ComboBox1 было отображено значение по умолчанию. Код следует вставлять перед строкой «End With».

‘Вариант 1 (произвольная строка)

.Value = «Моя строка по умолчанию»

‘или

.Value = «Синий»

‘Вариант 2 (произвольная строка)

.ControlSource = «A1»

Range(«A1») = «Моя строка по умолчанию»

‘или

.ControlSource = «A1»

Range(«A1») = «Желтый»

‘Вариант 3 (строка из списка)

.ListIndex = 0 ‘Красный

‘или

.ListIndex = 3 ‘Зеленый

Кроме значения по умолчанию, в свойства комбинированного списка можно добавить текст всплывающей подсказки, который будет отображаться при наведении на ComboBox курсора:

UserForm1.ComboBox1.ControlTipText = "Выберите значение из списка"

Извлечение информации из ComboBox

Первоначально элемент управления ComboBox открывается с пустым полем или значением по умолчанию. Свойства Value и Text в этом случае возвращают пустую строку или текст по умолчанию.

Если пользователь выбрал новое значение из раскрывающегося списка или ввел его с клавиатуры, оно перезапишет значения свойств Value и Text. Из этих свойств мы с помощью кода VBA Excel извлекаем информацию, выбранную или введенную пользователем:

Dim myTxt As String

myTxt = UserForm1.ComboBox1.Value

‘или

myTxt = UserForm1.ComboBox1.Text

Вторую строку кода можно записать myTxt = UserForm1.ComboBox1, так как Value является свойством поля со списком по умолчанию.

Если вас интересует, как извлечь значение из многостолбцового раскрывающегося списка, смотрите об этом в статье с описанием элемента управления ListBox. Извлечение данных из комбинированного поля аналогично извлечению данных из ListBox. Знакомясь со статьей, следует учесть, что у ComboBox отсутствует многострочный выбор.

Иногда перед загрузкой в ComboBox требуется отобрать уникальные элементы из имеющегося списка. Смотрите, как это сделать с помощью объектов Collection и Dictionary.

 

jurij271

Пользователь

Сообщений: 17
Регистрация: 26.07.2014

Здравствуйте. После долгих безуспешных попыток по поиску информации для решения имеющейся проблемы решил обратиться на форум.
Нужен макрос для получения выпадающего списка с данными, расположенными в несмежных ячейках   другого листа. В зависимости от выбранного значения формируется другой выпадающий список.
Суть проблемы:
1) Имеется Лист1, на котором в ячейках А2, А5, А8 … находятся данные для выпадющего списка №1. Выпадающий список №1 должен появляться при выделении ячейки В3, В4,.. В9 на Листе2. Причём, если данные в какой-либо из ячеек А2, А5, А8 … отсутствуют, то она присутствовать в выпадающем списке №1 не должна (т.е., чтобы в этом списке не было пустых строк)
2) На Листе1 имеются данные для выпадающего списка №2 в ячейках В2,С2,D2…;  В5,С5,D5…; В8,С8,D8 …. Выпадающий список №2 должен появляться при выделении ячейки С3, С4, С5 … на Листе2. Причём, данные для списка №2 должны браться из соответствующей строки в зависимости от значения выбранного в ячейке слева.
Конкретный пример находится в прилагаемом файле.
Версия  Excel — 2003!

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

Изменено: jurij27111.08.2014 00:27:06

 

ikki

Пользователь

Сообщений: 9709
Регистрация: 22.12.2012

#2

26.07.2014 11:49:06

Цитата
jurij271 пишет: помощь в написании данного макроса

и в чём именно Вам требуется «помощь»? я в Вашем файле даже заготовки макроса не нашёл.
или под этим словом Вы подразумеваете «напишите вместо меня»?

фрилансер Excel, VBA — контакты в профиле
«Совершенствоваться не обязательно. Выживание — дело добровольное.» Э.Деминг

 
 

jurij271

Пользователь

Сообщений: 17
Регистрация: 26.07.2014

#4

26.07.2014 23:07:53

Евгений, спасибо за информацию. Возможно это то, что мне нужно. Буду разбираться.

ikki, спасибо за внимание к поставленной мной задаче. Извиняюсь за отсутствие конкретных проблемных вопросов — попробую их конкретизировать. Решение первой части задачи сначала пытался делать стандартным способом (создавая именованный диапазон из несмежных ячеек). Но при попытке сделать выпадающий список через проверку данных выдаётся сообщение об ошибке. Эту проблему я частично решил через промежуточный лист, на котором формируется нужный список из данных с Листа1, располагаемых в соседних ячейках. Но в данном случае в выпадающем списке появляются пусты строки, если не все ячейки с исходными данными с Листа1 заполнены. (этот способ — в файле Пример1)
Потому пришёл к выводу, что без макроса в этой задаче не обойтись. Так как опыт написания программ на VBA у меня невелик (делаю свой первый проект) и в синтаксисе данного языка я не силён, то при необходимости написания программы запускаю макрорекордер и пытаюсь разобраться в полученном коде. Так вот в коде выпадающего списка нужно вместо непрерывного диапазона =$A$2:$A$23 указать несмежные ячейки с даными из Листа1.

Код
 Sub Макрос2()
    Range("B4".Select
    With Selection.Validation
        .Delete
        .Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Operator:= _
        xlBetween, Formula1:="=$A$2:$A$23"
        .IgnoreBlank = True
        .InCellDropdown = True
        .InputTitle = ""
        .ErrorTitle = ""
        .InputMessage = ""
        .ErrorMessage = ""
        .ShowInput = True
        .ShowError = True
    End With
End Sub

Прикрепленные файлы

  • Пример1.xls (24.5 КБ)

 

ikki

Пользователь

Сообщений: 9709
Регистрация: 22.12.2012

один доп.столбец, один доп.диапазон, два имени
без макросов

Прикрепленные файлы

  • списки.xls (22.5 КБ)

фрилансер Excel, VBA — контакты в профиле
«Совершенствоваться не обязательно. Выживание — дело добровольное.» Э.Деминг

 

jurij271

Пользователь

Сообщений: 17
Регистрация: 26.07.2014

ikki, большое Вам спасибо за помощь. Буду «пристраивать» Ваше решение к моему проекту. Можно ли ещё Вас побеспокоить своими вопросами, если возникнут некоторые «подводные камни» в процессе «пристройки»?
Ещё раз спасибо.

 

jurij271

Пользователь

Сообщений: 17
Регистрация: 26.07.2014

ikki, «пристроил» Ваше решение к своему проекту. Поскольку в качестве образца прикладывал примерный файл, то в процессе пристройки пришлось немного изменить условие (в зависимости от содержимого ячеек). Всё работает.
Осталось несколько «шероховатостей», которые хотелось бы устранить:
1) При выборе нового предмета в соседней ячейке справа остаётся прежний класс, даже если такого класса в данном предмете не существует. Логичным была бы очистка ячейки с классом при выборе нового предмета. Решение аналогичной проблемы рассматривалось на страничке с созданием связанных списков

http://www.planetaexcel.ru/techniques/1/38/

и Николай Павлов предложил для её решения следующий макрос:
Private Sub Worksheet_Change(ByVal Target As Excel.Range)
If Target.Address(False, False) = «C4» Then Range(«D4»).ClearContents
End Sub
Для одной пары ячеек макрос работает, если скопиравать его для другой пары ячеек (например, расположенных снизу, естественно, с указанием их имён), то класс при выборе нового предмета не удаляется. Даже если данный способ заработает, то решение этой задачи, конечно, будет некрасивое (48 однотипных макросов!). Полагаю, что логичным было бы решение через массив — при изменении элемента, соответствующего предмету, удалять содержимое ячейки справа. Хотя, может есть решение более простое?
2) Выпадающий список с классами содержал в том числе и пустые ячейки, в которых классов не было. Для списка, в котором для предметов отведено 5 ячеек этот недостаток несущественнен. В реализуемом же проекте на классы отводится 10 ячеек и выпадающий список уже некрасив (много пустых строк) и неудобен (появляется полоса прокрутки, случается что список пуст, так как предметы располагаются в его верхней (невидимой) части). Возможно ли модернизировать формулу для второго списка, с тем, чтобы пустые строки в нём отсутствовали?
3) И ещё один момент, который в общем-то несущественнен, но возможно упростит решение задачи: На листе «Предмет-Классы» у каждого класса уже предполагается номер. Для реализации этого столбец В с номерами для формирования списка скрывается. Может, ввиду имеющейся фиксированной нумерации предметов можно упростить создание первого выпадающего списка?
Спасибо.

Изменено: jurij27131.07.2014 10:34:28
(Опечатка)

 

ikki

Пользователь

Сообщений: 9709
Регистрация: 22.12.2012

посмотрите вариант.
изменения коснулись формулы для имени «Классы» и макроса
п.3 я, честно говоря, не понял.

фрилансер Excel, VBA — контакты в профиле
«Совершенствоваться не обязательно. Выживание — дело добровольное.» Э.Деминг

 

jurij271

Пользователь

Сообщений: 17
Регистрация: 26.07.2014

Уважаемый, ikki, большое Вам спасибо за решение имевшейся проблемы.
Имеется небольшой нюанс, который был замечен в ходе тестирования файла с решением:
При расположении классов не подряд, в выпадающем списке классов могут присутствовать пустые строки, либо отсутствовать классы (пример такой ситуации — в приложенном файле). Понимаю, что появляется эта проблема из-за принципа формирования списка классов (подсчитывается количество непустых ячеек и тем самым определяется количество строк, которые нужно выводить в списке) и решить её можно таком же способом, что и способ формирования списка с предметами (осуществлять нумерацию ячеек, содержащих классы и «вытаскивать» их в список по  наличию возле них номера). Но не лучше ли было бы решение через макрос? Ведь формирование обоих списков однотипное и, внеся список в массив, обращаться к его элементам и осуществлять выборку по определённым признакам было бы проще чем через встроенные функции? Кроме того, так, наверное, проще  будет  реализовать при необходимости и вложенные списки следующих уровней (т.е. решение будет универсальным, да и макрос уже задействован при очистке ячеек :).
Проблему с пустыми строками я решил принудительным переносом классов в начало списка. Хотя это, конечно, «половинчатое» решение, т.е. пользователю не будет предоставлено возможности произвольного размещения элементов списка в заданном диапазоне.
PS: 1) Массив взят из проекта, для данного примера можно использовать и меньше элементов.
2) Возможно перенос классов реализован не самым оптимальным способом :)

 

ikki

Пользователь

Сообщений: 9709
Регистрация: 22.12.2012

#10

07.08.2014 15:03:41

Цитата
jurij271 пишет: не лучше ли было бы решение через макрос?

Вы знаете, как это делать через макрос?
Вот и я не знаю  :)

Изменено: ikki11.08.2014 00:26:37

фрилансер Excel, VBA — контакты в профиле
«Совершенствоваться не обязательно. Выживание — дело добровольное.» Э.Деминг

 

jurij271

Пользователь

Сообщений: 17
Регистрация: 26.07.2014

Нет. В силу ничтожно малого опыта работы с VBA реализовать выпадающие списки через макрос я не могу. Предполагаю, что это возможно, хотя я (опять же, по причине малого опыта) могу ошибаться — ведь даже у Вас эта задача вызывает затруднение. Но в любом случае уже предложенное  Вами решение можно использовать в аналогичных задачах.
Честно говоря, когда начинал поиск решения проблемы со связанными выпадающими списками, то полагал, что эта задача уже решена (задача казалась мне достаточно распространённой). Оказалось, что нет. В любом случае, пусть найденное решение поможет тем, кто столкнётся с аналогичной проблемой.
Ещё раз выражаю Вам свою благодарность за помощь.

 

ikki

Пользователь

Сообщений: 9709
Регистрация: 22.12.2012

#12

07.08.2014 23:39:13

Цитата
jurij271 пишет: Предполагаю, что это возможно

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

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

фрилансер Excel, VBA — контакты в профиле
«Совершенствоваться не обязательно. Выживание — дело добровольное.» Э.Деминг

 

jurij271

Пользователь

Сообщений: 17
Регистрация: 26.07.2014

#13

08.08.2014 00:00:38

Цитата
ikki пишет: при активации ячейки проверять принадлежность нужному диапазону и создавать для текущей ячейки список в виде константы.

Что ж, будем надеяться, что у Вас появится желание реализовать имеющиеся идеи   :)

 

Юрий М

Модератор

Сообщений: 60570
Регистрация: 14.09.2012

Контакты см. в профиле

#14

08.08.2014 01:39:38

Цитата
ikki пишет: почему-то этот массив «не цепляется» у меня к проверке данных.

Может массив не тот? ))

 

Максим Зеленский

Пользователь

Сообщений: 4646
Регистрация: 11.06.2014

Microsoft MVP

#15

08.08.2014 08:01:18

недавно кто-то такое решение показывал
если уже есть массив, содержащий именно нужный перечень строк с названиями классов или предметов, то его (если правильно помню) можно присвоить проверке данных через макрос так:

Код
Range("A1").Validation.Add xlValidateList, xlValidAlertStop, xlBetween, Join(massiv,",") 

где massiv — это собственно одномерный массив нужных строк.
а уж по какому событию это делать, или по кнопке, или одноразово — смотрите сами

Изменено: Максим Зеленский08.08.2014 08:01:39

F1 творит чудеса

 

Юрий М

Модератор

Сообщений: 60570
Регистрация: 14.09.2012

Контакты см. в профиле

#16

08.08.2014 08:11:03

Я делаю так:

Код
[A1].Validation.Add Type:=xlValidateList, Formula1:=Join(arr, ",") 

Arr — одномерный массив

 

jurij271

Пользователь

Сообщений: 17
Регистрация: 26.07.2014

#17

10.08.2014 23:43:30

Уважаемые старожилы форума Максим Зеленский иЮрий М, спасибо за подсказку с выпадающим списком. Попробовал адаптировать к своему проекту — получилось. Выпадающий список предметов работает. В этой части есть следующая проблема — выпадающий список не обновляется. Первым запуском макрос нормально отрабатывается, а при следующем обращении к нему выдаётся ошибка. Причина — уже имеющийся выпадающий список в ячейке. (если его удалить, макрос опять срабатывает). Пробовал перед формирующимся выпадающим списком выполнять его удаление (макросом, записанным через макрорекордер). В этом случае выпадающий список даже не формируется. Восстанавливается работоспособность удалением списка «вручную».
Так что в этой части задачи стоит проблема с обновлением списка.

При формировании второго выпадающего списка (зависимого) решил реализовать идею предложенную ikki, (с функцией пользователя, поскольку количество массивов для зависимых списков будут расти в геометрической прогрессии по мере роста уровней вложенности списков). Конечно, «реализовать идею» это громко сказано, так как составлял эту функцию впервые. Понимаю, что в функции есть ошибка. Нужна корректировка профессионала …
Файл с макросом и функцией прилагаю.

Прикрепленные файлы

  • Подсчёт уроков(массив).xls (54.5 КБ)

VBA For Excel's Form Control Combo Boxes

You’re VBA Combo Box Cheat Sheet

In this post I am going to share everything I know about using VBA with an Excel Form Control Combo Box (aka drop down).  Most of the code is very self-explanatory so I will not write much of a description.  However, some of the syntax can be a little tricky so pay close attention to how the code is structured.  Please feel free to post comments if I missed an area or you have any questions!  Enjoy :)

Creating & Sizing/Positioning A Combo Box

Sub ComboBox_Create()
‘PURPOSE: Create a form control combo box and position/size it

Dim Cell As Range
Dim sht As Worksheet

Set sht = ThisWorkbook.Worksheets(«Sheet1»)

‘Create
  sht.DropDowns.Add(0, 0, 100, 15).Name = «Combo Box 1»

‘Create & Dimension to a Specific Cell
  Set Cell = Range(«B5»)

    With Cell
    sht.DropDowns.Add(.Left, .Top, .Width, .Height).Name = «Combo Box 2»
  End With

‘Create & Dimension to a Specific Cell Range
  Set Cell = Range(«B8:D8»)

    With Cell
    sht.DropDowns.Add(.Left, .Top, .Width, .Height).Name = «Combo Box 3»
  End With

End Sub

Deleting A Combo Box

Sub ComboBox_Delete()
‘PURPOSE: Delete a form control combo box

Dim sht As Worksheet

Set sht = ThisWorkbook.Worksheets(«Sheet1»)

sht.Shapes(«Combo Box 1»).Delete

End Sub

Adding Values To A Combo Box

Sub ComboBox_InputRange()
‘PURPOSE: Add values to your drop down list

Dim Cell As Range
Dim sht As Worksheet
Dim myArray As Variant
Dim myDropDown As Shape

Set sht = ThisWorkbook.Worksheets(«Sheet1»)
Set myDropDown = sht.Shapes(«Combo Box 1»)
myArray = Array(«Q1», «Q2», «Q3», «Q4»)

‘Based on data in a range (not linked)
  MyDropDown.ControlFormat.List = sht.Range(«A1:A4»).Value

  ‘Linked to data in a range (automatically changes based on current cell values)
  myDropDown.ControlFormat.ListFillRange = «A1:A4»

  ‘Based on Array values (written out)
  MyDropDown.ControlFormat.List = _
   Array(«Q1», «Q2», «Q3», «Q4»)

‘Based on Array values (variable)
  myDropDown.OLEFormat.Object.List = myArray

  ‘Add one by one
  With myDropDown.ControlFormat
    .AddItem «Q1»
    .AddItem «Q2»
    .AddItem «Q3»
    .AddItem «Q4»
  End With

End Sub

Overriding Values In The Drop Down List

Sub ComboBox_ReplaceValue()
‘PURPOSE: Replace value of the third item in the drop down list

Worksheets(«Sheet1»).Shapes(«Combo Box 1»).ControlFormat.List(3) = «FY»

End Sub

Removing Values From The Drop Down List

Sub ComboBox_RemoveValues()
‘PURPOSE: Remove a value(s) from the drop down list

Dim Cell As Range
Dim sht As Worksheet

Set sht = ThisWorkbook.Worksheets(«Sheet1»)

‘Remove A Single Item
  sht.Shapes(«Combo Box 1»).ControlFormat.RemoveItem 2

‘Remove All Items
  sht.Shapes(«Combo Box 1»).ControlFormat.RemoveAllItems

End Sub

Determine Current Selected Value From The Drop Down List

Sub ComboBox_GetSelection()
‘PURPOSE: Determine current selected value in ComboBox

Dim sht As Worksheet
Dim myDropDown As Shape

Set sht = ThisWorkbook.Worksheets(«Sheet1»)
Set myDropDown = sht.Shapes(«Combo Box 1»)

With myDropDown.ControlFormat
  MsgBox «Item Number: » & .Value & vbNewLine & «Item Name: » & .List(.Value)
End With

End Sub

Select A Value From The Drop Down List

Sub ComboBox_SelectValue()
‘PURPOSE: Automatically select a value from the drop down list

Dim Cell As Range
Dim sht As Worksheet
Dim Found As Boolean
Dim SetTo As String
Dim x As Long

Set sht = ThisWorkbook.Worksheets(«Sheet1»)

‘Select First List Item
  sht.Shapes(«Combo Box 1»).ControlFormat.ListIndex = 3

  ‘Select Item based on list Name/Value
  SetTo = «Q2»

    With sht.Shapes(«Combo Box 1»).ControlFormat
    For x = 1 To .ListCount
      If .List(x) = SetTo Then
        Found = True
        Exit For
    Next x

      If Found = True Then .ListIndex = x
  End With

End Sub

Link User’s Selection To A Cell (Outputs Numerical List Position)

Sub ComboBox_CellLink()
‘PURPOSE: Output the selection’s list position to a specific cell

Dim sht As Worksheet

Set sht = ThisWorkbook.Worksheets(«Sheet1»)

sht.Shapes(«Combo Box 1»).ControlFormat.LinkedCell = «$A$1»

End Sub

Adjust Drop Down Lines For A Combo Box

Sub ComboBox_DropDownLines()
‘PURPOSE: Set how many drop down lines are visible per scroll

Dim sht As Worksheet

Set sht = ThisWorkbook.Worksheets(«Sheet1»)

sht.Shapes(«Combo Box 1»).ControlFormat.DropDownLines = 12

End Sub

Toggle On/Off 3D Shading

Sub ComboBox_3DShading()
‘PURPOSE: Turn 3D shading on or off

Dim sht As Worksheet

Set sht = ThisWorkbook.Worksheets(«Sheet1»)

‘Turn 3D Shading On
  sht.Shapes(«Combo Box 1»).OLEFormat.Object.Display3DShading = True

‘Turn 3D Shading Off
  sht.Shapes(«Combo Box 1»).OLEFormat.Object.Display3DShading = False

End Sub

Assigning A Macro To A Combo Box

Sub ComboBox_AssignMacro()
‘PURPOSE: Assign a macro to be triggered when drop down is changed

Dim sht As Worksheet

Set sht = ThisWorkbook.Worksheets(«Sheet1»)

sht.Shapes(«Combo Box 1»).OnAction = «Macro1»

End Sub

Any Others?

If I’ve missed any VBA functionalities please leave a comment in the comments section below so I can continue to grow this list of combo box code!  I look forward to hearing your thoughts.

About The Author

Hey there! I’m Chris and I run TheSpreadsheetGuru website in my spare time. By day, I’m actually a finance professional who relies on Microsoft Excel quite heavily in the corporate world. I love taking the things I learn in the “real world” and sharing them with everyone here on this site so that you too can become a spreadsheet guru at your company.

Through my years in the corporate world, I’ve been able to pick up on opportunities to make working with Excel better and have built a variety of Excel add-ins, from inserting tickmark symbols to automating copy/pasting from Excel to PowerPoint. If you’d like to keep up to date with the latest Excel news and directly get emailed the most meaningful Excel tips I’ve learned over the years, you can sign up for my free newsletters. I hope I was able to provide you with some value today and I hope to see you back here soon!

— Chris
Founder, TheSpreadsheetGuru.com

Добрый день гуру excel!!!
Я не так часто пишу что-то в макросах, однако сейчас встала такая вот задача и я столкнулся с проблемой. Поиски решений в интернете не дали результата. Хотя несколько близких тем я нашел.

Здесь вот чувак бился над похожей задачей, но как он ее разрешил я все же разобрать не смог. https://stackoverflow.com/questio….-variab

Я опишу задачу в двух словах. У меня есть книга, в ней есть два листа. Лист — «Карточка Клиента» с программным именем Client_Card и Лист — «Данные» c программным именем staff_list.
На Листе1 есть табличка, в нескольких ее ячейках я хочу вывести выпадающие списки.
На листе2 храниться данные для выпадающего списка.

Я хочу использовать объект Range, который бы позволил мне меняться в случаи увеличения значений в списке
Я кстати пробовал вставить списки используя диапазон… но это тоже не сработало. Видимо нужно конкретно в ячейку вставлять.

[vba]

Код

With Client_Card.Range(Client_Card.Cells(14, 3), Client_Card.Cells(27, 3)).Validation

[/vba]

Я создал в книге с примером код. Как раз тот который работать не хочет.

Я пробовал просто вставлять в

[vba]

Код

…. Formula1:=staff_list.Range(staff_list.Cells(2, 1), staff_list.Cells(9, 1)).Value ‘но так оно не работает.

[/vba]

[vba]

Код

   With Client_Card.Cells(14, 3).Validation
        .Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Operator:= _
        xlBetween, Formula1:=staff_list.Range(staff_list.Cells(2, 1), staff_list.Cells(9, 1)).Value
    End With

[/vba]

Пробовал через переменную… но так тоже не работает

[vba]

Код

Private Sub CommandButton1_Click()
Dim bbbb As String

bbbb = staff_list.Range(staff_list.Cells(2, 1), staff_list.Cells(9, 1)).Value ‘

    With Cells(14, 3).Validation
        .Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Operator:= _
        xlBetween, Formula1:=»=bbbb»
    End With

     End Sub

[/vba]

Я подозреваю что список этот, в переменной необходимо подать через запятую… то есть видимо его надо прогнать через массив, где каждому значению подставить запятую и сформировать конечную переменную со всеми значениями через запятую.
Но я пока не стал так делать, в надежде что есть более простой способ, а я просто туплю…

В обще я хочу формировать данный выпадающие список на листе «Карточка клиента», при запуске книги. Но это потом, сейчас хотелось бы его заставить код работать

based on examples above and examples found on other sites, I created a generic procedure and some examples.

'Simple helper procedure to create a dropdown in a cell based on a list of values in a range
'ValueSheetName : the name of the sheet containing the value range
'ValueRangeString : the range on the sheet with name ValueSheetName containing the values for the dropdown
'CreateOnSheetName : the name of the sheet where the dropdown needs to be created
'CreateInRangeString : the range where the dropdown needs to be created
'FieldName As String : a name of the dropdown, will be used in the inputMessage and ErrorMessage
'See example below ExampleCreateDropDown
Public Sub CreateDropDown(ValueSheetName As String, ValueRangeString As String, CreateOnSheetName As String, CreateInRangeString As String, FieldName As String)
    Dim ValueSheet As Worksheet
    Set ValueSheet = Worksheets(ValueSheetName) 'The sheet containing the values
    Dim ValueRange As Range: Set ValueRange = ValueSheet.Range(ValueRangeString) 'The range containing the values
    Dim CreateOnSheet As Worksheet
    Set CreateOnSheet = Worksheets(CreateOnSheetName) 'The sheet containing the values
    Dim CreateInRange As Range: Set CreateInRange = CreateOnSheet.Range(CreateInRangeString)
    Dim InputTitle As String:  InputTitle = "Please Select a Value"
    Dim InputMessage As String:  InputMessage = "for " & FieldName
    Dim ErrorTitle As String:  ErrorTitle = "Please Select a Value"
    Dim ErrorMessage As String:  ErrorMessage = "for " & FieldName
    Dim ShowInput As Boolean:  ShowInput = True 'Show input message on hover
    Dim ShowError As Boolean:  ShowError = True 'Show error message on error
    Dim ValidationType As XlDVType:  ValidationType = xlValidateList
    Dim ValidationAlertStyle As XlDVAlertStyle:  ValidationAlertStyle = xlValidAlertStop 'Stop on invalid value
    Dim ValidationOperator As XlFormatConditionOperator:  ValidationOperator = xlEqual 'Value must be equal to one of the Values from the ValidationFormula1
    Dim ValidationFormula1 As Variant:  ValidationFormula1 = "=" & ValueSheetName & "!" & ValueRange.Address 'Formula referencing the values from the ValueRange
    Dim ValidationFormula2 As Variant:  ValidationFormula2 = ""

    Call CreateDropDownWithValidationInCell(CreateInRange, InputTitle, InputMessage, ErrorTitle, ErrorMessage, ShowInput, ShowError, ValidationType, ValidationAlertStyle, ValidationOperator, ValidationFormula1, ValidationFormula2)
End Sub


'An example using the ExampleCreateDropDown
Private Sub ExampleCreateDropDown()
    Call CreateDropDown(ValueSheetName:="Test", ValueRangeString:="C1:C5", CreateOnSheetName:="Test", CreateInRangeString:="B1", FieldName:="test2")
End Sub


'The full option function if you need more configurable options
'To create a dropdown in a cell based on a list of values in a range
'Validation: https://msdn.microsoft.com/en-us/library/office/ff840078.aspx
'ValidationTypes: XlDVType  https://msdn.microsoft.com/en-us/library/office/ff840715.aspx
'ValidationAlertStyle:  XlDVAlertStyle  https://msdn.microsoft.com/en-us/library/office/ff841223.aspx
'XlFormatConditionOperator  https://msdn.microsoft.com/en-us/library/office/ff840923.aspx
'See example below ExampleCreateDropDownWithValidationInCell
Public Sub CreateDropDownWithValidationInCell(CreateInRange As Range, _
                                        Optional InputTitle As String = "", _
                                        Optional InputMessage As String = "", _
                                        Optional ErrorTitle As String = "", _
                                        Optional ErrorMessage As String = "", _
                                        Optional ShowInput As Boolean = True, _
                                        Optional ShowError As Boolean = True, _
                                        Optional ValidationType As XlDVType = xlValidateList, _
                                        Optional ValidationAlertStyle As XlDVAlertStyle = xlValidAlertStop, _
                                        Optional ValidationOperator As XlFormatConditionOperator = xlEqual, _
                                        Optional ValidationFormula1 As Variant = "", _
                                        Optional ValidationFormula2 As Variant = "")

    With CreateInRange.Validation
        .Delete
        .Add Type:=ValidationType, AlertStyle:=ValidationAlertStyle, Operator:=ValidationOperator, Formula1:=ValidationFormula1, Formula2:=ValidationFormula2
        .IgnoreBlank = True
        .InCellDropdown = True
        .InputTitle = InputTitle
        .ErrorTitle = ErrorTitle
        .InputMessage = InputMessage
        .ErrorMessage = ErrorMessage
        .ShowInput = ShowInput
        .ShowError = ShowError
    End With
End Sub


'An example using the CreateDropDownWithValidationInCell
Private Sub ExampleCreateDropDownWithValidationInCell()
    Dim ValueSheetName As String: ValueSheetName = "Hidden" 'The sheet containing the values
    Dim ValueRangeString As String: ValueRangeString = "C7:C9" 'The range containing the values
    Dim CreateOnSheetName As String: CreateOnSheetName = "Test"  'The sheet containing the dropdown
    Dim CreateInRangeString As String: CreateInRangeString = "A1" 'The range containing the dropdown

    Dim ValueSheet As Worksheet
    Set ValueSheet = Worksheets(ValueSheetName)
    Dim ValueRange As Range: Set ValueRange = ValueSheet.Range(ValueRangeString)
    Dim CreateOnSheet As Worksheet
    Set CreateOnSheet = Worksheets(CreateOnSheetName)
    Dim CreateInRange As Range: Set CreateInRange = CreateOnSheet.Range(CreateInRangeString)
    Dim FieldName As String: FieldName = "Testing Dropdown"
    Dim InputTitle As String:  InputTitle = "Please Select a value"
    Dim InputMessage As String:  InputMessage = "for " & FieldName
    Dim ErrorTitle As String:  ErrorTitle = "Please Select a value"
    Dim ErrorMessage As String:  ErrorMessage = "for " & FieldName
    Dim ShowInput As Boolean:  ShowInput = True
    Dim ShowError As Boolean:  ShowError = True
    Dim ValidationType As XlDVType:  ValidationType = xlValidateList
    Dim ValidationAlertStyle As XlDVAlertStyle:  ValidationAlertStyle = xlValidAlertStop
    Dim ValidationOperator As XlFormatConditionOperator:  ValidationOperator = xlEqual
    Dim ValidationFormula1 As Variant:  ValidationFormula1 = "=" & ValueSheetName & "!" & ValueRange.Address
    Dim ValidationFormula2 As Variant:  ValidationFormula2 = ""

    Call CreateDropDownWithValidationInCell(CreateInRange, InputTitle, InputMessage, ErrorTitle, ErrorMessage, ShowInput, ShowError, ValidationType, ValidationAlertStyle, ValidationOperator, ValidationFormula1, ValidationFormula2)

End Sub

Понравилась статья? Поделить с друзьями:
  • Excel vba ячейка cell
  • Excel vba это просто
  • Excel vba экспорт в pdf
  • Excel vba экранирование кавычек
  • Excel vba ширина ячеек