Подскажите пожалуйста , есть ли способ сделать так, чтобы в выпадающем списке в ячейке можно было бы выбирать несколько значений сразу с помощью галочек (как например в фильтрах в сводных таблицах) и потом эти выбранные значения отображать в соседней ячейке справа через запятую ,ну или записывать эти выбранные значения в "массив" или в "список" в VBA, для дальнейшей обработки ?
Как сделать так, чтобы можно было выбирать в выпадающем списке значения по-очереди и отображать их в соседних ячейках - знаю. Код снизу делает это, но нужно, чтобы выбирать можно было галочками и не по-очереди , а одновременно, как на картинке
...
[vba]
Код
Private Sub Worksheet_Change(ByVal Target As Range) 'справа от выпадающего списка будут добавляться выбранные значения. On Error Resume Next If Not Intersect(Target, Range("b12:b18")) Is Nothing And Target.Cells.Count = 1 Then Application.EnableEvents = False If Len(Target.Offset(0, 1)) = 0 Then Target.Offset(0, 1) = Target Else Target.End(xlToRight).Offset(0, 1) = Target End If Target.ClearContents Application.EnableEvents = True End If
End Sub
[/vba]
Добрый день всем!
Подскажите пожалуйста , есть ли способ сделать так, чтобы в выпадающем списке в ячейке можно было бы выбирать несколько значений сразу с помощью галочек (как например в фильтрах в сводных таблицах) и потом эти выбранные значения отображать в соседней ячейке справа через запятую ,ну или записывать эти выбранные значения в "массив" или в "список" в VBA, для дальнейшей обработки ?
Как сделать так, чтобы можно было выбирать в выпадающем списке значения по-очереди и отображать их в соседних ячейках - знаю. Код снизу делает это, но нужно, чтобы выбирать можно было галочками и не по-очереди , а одновременно, как на картинке
...
[vba]
Код
Private Sub Worksheet_Change(ByVal Target As Range) 'справа от выпадающего списка будут добавляться выбранные значения. On Error Resume Next If Not Intersect(Target, Range("b12:b18")) Is Nothing And Target.Cells.Count = 1 Then Application.EnableEvents = False If Len(Target.Offset(0, 1)) = 0 Then Target.Offset(0, 1) = Target Else Target.End(xlToRight).Offset(0, 1) = Target End If Target.ClearContents Application.EnableEvents = True End If
Такая игрушка для обычного выпадающего списка. Галочки лень искать было, сделал + и - Делал на скорую руку, вполне возможно, что какие-то моменты не учел. Но это не так важно, главное принцип
Такая игрушка для обычного выпадающего списка. Галочки лень искать было, сделал + и - Делал на скорую руку, вполне возможно, что какие-то моменты не учел. Но это не так важно, главное принцип_Boroda_
Круто! Спасибо! Не могли вы ответить на несколько вопросов:
1.Нигде не увидел инструкции объявления переменных DIm a_ , x_ , z_ хотя у меня стоит Option Explicit , но VBA не ругается при запуске этого кода... Почему так происходит?
2.Попытался понять как работает код ,но пока не смог вникнуть. Не могли бы Вы в комментах пояснить, что к чему , если не трудно.
3. Если нажимать F8 , то пошаговая отладка не работает и не понятно как в процессе выполнения кода меняются переменные a_ , x_, z_ , поэтому сложно понять как код работает. Чем вы пользуетесь для отладки таких кодов?
Заранее спасибо, за ответы!
[vba]
Код
Private Sub Worksheet_Change(ByVal Target As Range) ' процедура запускаемая при изменении в диапазоне Target If Target.Address(0, 0) = "D1" Then ' если смещение на 0 строк и 0 столбцов от выбранной пользователем ячейки равно D1 a_ = Replace(Replace(Target, "+ ", ""), "- ", "") ' то в переменную a_ записываем строку, содержащуюся в ячейке D1 без знаков "+ " и "- " If InStr(x_, a_) Then ' если в переменной x_ (для чего эта переменная?) содержится строка a_ , то z_ = Replace(Replace(x_, a_ & ",", ""), a_, "") ' очищаем переменную x_ от переменной a_ с запятой и без запятой и записываем это все в переменную z_ ... Зачем? If Right(z_, 1) = "," Then ' если справа в переменной z_ осталась запятая z_ = Left(z_, Len(z_) - 1) ' , то удаляем ее , с помощью этого выражения End If Else ' если в переменной x_ НЕ содержится строка a_ , то z_ = x_ & a_ ' к x_ добавляется a_ и записывается все это в переменную z_ If Left(z_, 1) = "," Then ' если в конце z_ есть запятая , то z_ = Mid(z_, 2) ' в переменную z_ записываем первые 2 символа слева (Зачем?) End If End If Application.EnableEvents = 0 ' запрещаем события Target = z_ ' пишем в ячейку d1 значение переменной z_ Application.EnableEvents = 1 ' разрешаем события SendKeys "%{down}" ' передаем в процедуру нажатие клавиш ALT +стрелка вниз, чтобы перейти к следующему значению в списке x_ = Target & "," ' пишем в переменную x_ значение из ячейки d1 плюс запятая End If End Sub
Private Sub Worksheet_SelectionChange(ByVal Target As Range) ' процедура запускающаяся при выделении ячейки D1 If Target.Address(0, 0) = "D1" Then Application.EnableEvents = 0 ' запрещаем изменение событий. Зачем? Target = "" ' обнуляем значение в ячейке D1 Application.EnableEvents = 1 ' разрешаем изменение событий ...? SendKeys "%{down}" ' передаем в процедуру нажатие клавиш ALT плюс стрелка вниз,чтобы можно было выбрать другие значения из списка Зачем? x_ = "" ' обнуляем переменную x_ End If End Sub
Круто! Спасибо! Не могли вы ответить на несколько вопросов:
1.Нигде не увидел инструкции объявления переменных DIm a_ , x_ , z_ хотя у меня стоит Option Explicit , но VBA не ругается при запуске этого кода... Почему так происходит?
2.Попытался понять как работает код ,но пока не смог вникнуть. Не могли бы Вы в комментах пояснить, что к чему , если не трудно.
3. Если нажимать F8 , то пошаговая отладка не работает и не понятно как в процессе выполнения кода меняются переменные a_ , x_, z_ , поэтому сложно понять как код работает. Чем вы пользуетесь для отладки таких кодов?
Заранее спасибо, за ответы!
[vba]
Код
Private Sub Worksheet_Change(ByVal Target As Range) ' процедура запускаемая при изменении в диапазоне Target If Target.Address(0, 0) = "D1" Then ' если смещение на 0 строк и 0 столбцов от выбранной пользователем ячейки равно D1 a_ = Replace(Replace(Target, "+ ", ""), "- ", "") ' то в переменную a_ записываем строку, содержащуюся в ячейке D1 без знаков "+ " и "- " If InStr(x_, a_) Then ' если в переменной x_ (для чего эта переменная?) содержится строка a_ , то z_ = Replace(Replace(x_, a_ & ",", ""), a_, "") ' очищаем переменную x_ от переменной a_ с запятой и без запятой и записываем это все в переменную z_ ... Зачем? If Right(z_, 1) = "," Then ' если справа в переменной z_ осталась запятая z_ = Left(z_, Len(z_) - 1) ' , то удаляем ее , с помощью этого выражения End If Else ' если в переменной x_ НЕ содержится строка a_ , то z_ = x_ & a_ ' к x_ добавляется a_ и записывается все это в переменную z_ If Left(z_, 1) = "," Then ' если в конце z_ есть запятая , то z_ = Mid(z_, 2) ' в переменную z_ записываем первые 2 символа слева (Зачем?) End If End If Application.EnableEvents = 0 ' запрещаем события Target = z_ ' пишем в ячейку d1 значение переменной z_ Application.EnableEvents = 1 ' разрешаем события SendKeys "%{down}" ' передаем в процедуру нажатие клавиш ALT +стрелка вниз, чтобы перейти к следующему значению в списке x_ = Target & "," ' пишем в переменную x_ значение из ячейки d1 плюс запятая End If End Sub
Private Sub Worksheet_SelectionChange(ByVal Target As Range) ' процедура запускающаяся при выделении ячейки D1 If Target.Address(0, 0) = "D1" Then Application.EnableEvents = 0 ' запрещаем изменение событий. Зачем? Target = "" ' обнуляем значение в ячейке D1 Application.EnableEvents = 1 ' разрешаем изменение событий ...? SendKeys "%{down}" ' передаем в процедуру нажатие клавиш ALT плюс стрелка вниз,чтобы можно было выбрать другие значения из списка Зачем? x_ = "" ' обнуляем переменную x_ End If End Sub
1. Если Option Explicit явно не прописан в модуле с кодом, то его как бы и нет. Если Вы его вручную добавите, тогда да, нужно объявлять 2. [vba]
Код
Private Sub Worksheet_Change(ByVal Target As Range) 'при изменении ячейки If Target.Address(0, 0) = "D1" Then 'если это Д1 'Target - это ОДИН только что выбранный элемент списка a_ = Replace(Replace(Target, "+ ", ""), "- ", "") 'меняем в Д1 "+ " и "- " на пусто, полученное будет а_ If InStr(x_, a_) Then 'Если в х_ присутствует значение а_ z_ = Replace(Replace(x_, a_ & ",", ""), a_, "") 'убираем из х_ или а_ с запятой, или, если так не нашли, то просто а_ If Right(z_, 1) = "," Then 'если справа оказыывается лишняя запятая z_ = Left(z_, Len(z_) - 1) 'убираем ее End If ' Else 'Если в х_ отсутствует значение а_ z_ = x_ & a_ 'прилепляем а_ справа к х_, обзываем все это z_ If Left(z_, 1) = "," Then 'если слева лишняя запятая z_ = Mid(z_, 2) 'убираем ее End If ' End If ' Application.EnableEvents = 0 'откл реакцию на события Target = z_ 'суем полученное в Д1 Application.EnableEvents = 1 'вкл реакцию на события SendKeys "%{down}" 'жмем Альт СтрелкаВниз x_ = Target & "," 'переменная (см. модуль 1) равна ячейке Д1 и запятая справа End If End Sub
Private Sub Worksheet_SelectionChange(ByVal Target As Range) 'при выделении ячейки If Target.Address(0, 0) = "D1" Then 'если это Д1 Application.EnableEvents = 0 'откл реакцию на события Target = "" 'очищаем Д1 Application.EnableEvents = 1 'вкл реакцию на события SendKeys "%{down}" 'жмем Альт СтрелкаВниз x_ = "" 'переменная (см. модуль 1) равна пусто End If End Sub
[/vba] 3. Дело в том, что SendKeys работает в активном приложении. Если Вы работаете с листа, то активен лист, а если Вы пробегаете макрос через VBA (F5 или F8), то активен VBA и SendKeys отрабатывает уже в нем Я ничем не пользуюсь, пишу, запускаю, проверяю результат 4.
Для того, чтобы то, что в ячейке Д1, можно было считать при SelectionChange, а работать со считанным в Change 5. Без z_ конечно можно, но код получится длиннее и медленнее. Да и у меня привычка, если что-то в коде вычисляется более одного раза - сделать это вычисление раньше и засунуть в переменную
1. Если Option Explicit явно не прописан в модуле с кодом, то его как бы и нет. Если Вы его вручную добавите, тогда да, нужно объявлять 2. [vba]
Код
Private Sub Worksheet_Change(ByVal Target As Range) 'при изменении ячейки If Target.Address(0, 0) = "D1" Then 'если это Д1 'Target - это ОДИН только что выбранный элемент списка a_ = Replace(Replace(Target, "+ ", ""), "- ", "") 'меняем в Д1 "+ " и "- " на пусто, полученное будет а_ If InStr(x_, a_) Then 'Если в х_ присутствует значение а_ z_ = Replace(Replace(x_, a_ & ",", ""), a_, "") 'убираем из х_ или а_ с запятой, или, если так не нашли, то просто а_ If Right(z_, 1) = "," Then 'если справа оказыывается лишняя запятая z_ = Left(z_, Len(z_) - 1) 'убираем ее End If ' Else 'Если в х_ отсутствует значение а_ z_ = x_ & a_ 'прилепляем а_ справа к х_, обзываем все это z_ If Left(z_, 1) = "," Then 'если слева лишняя запятая z_ = Mid(z_, 2) 'убираем ее End If ' End If ' Application.EnableEvents = 0 'откл реакцию на события Target = z_ 'суем полученное в Д1 Application.EnableEvents = 1 'вкл реакцию на события SendKeys "%{down}" 'жмем Альт СтрелкаВниз x_ = Target & "," 'переменная (см. модуль 1) равна ячейке Д1 и запятая справа End If End Sub
Private Sub Worksheet_SelectionChange(ByVal Target As Range) 'при выделении ячейки If Target.Address(0, 0) = "D1" Then 'если это Д1 Application.EnableEvents = 0 'откл реакцию на события Target = "" 'очищаем Д1 Application.EnableEvents = 1 'вкл реакцию на события SendKeys "%{down}" 'жмем Альт СтрелкаВниз x_ = "" 'переменная (см. модуль 1) равна пусто End If End Sub
[/vba] 3. Дело в том, что SendKeys работает в активном приложении. Если Вы работаете с листа, то активен лист, а если Вы пробегаете макрос через VBA (F5 или F8), то активен VBA и SendKeys отрабатывает уже в нем Я ничем не пользуюсь, пишу, запускаю, проверяю результат 4.
Для того, чтобы то, что в ячейке Д1, можно было считать при SelectionChange, а работать со считанным в Change 5. Без z_ конечно можно, но код получится длиннее и медленнее. Да и у меня привычка, если что-то в коде вычисляется более одного раза - сделать это вычисление раньше и засунуть в переменную_Boroda_
Огромное спасибо за ответы! А как Вы сделали список в ячейке D1 , чтобы там были значения с плюсами и минусами, которые при выборе меняются друг на друга?
Огромное спасибо за ответы! А как Вы сделали список в ячейке D1 , чтобы там были значения с плюсами и минусами, которые при выборе меняются друг на друга?t330
_Boroda_, Здравствуйте. Очень классный список получился... А возможно на одном листе сделать таких списков несколько? Простыми методами у меня не получилось реализовать.
_Boroda_, Здравствуйте. Очень классный список получился... А возможно на одном листе сделать таких списков несколько? Простыми методами у меня не получилось реализовать.AnK1LL