Форум программистов, компьютерный форум, киберфорум
VBA
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.69/13: Рейтинг темы: голосов - 13, средняя оценка - 4.69
49 / 31 / 2
Регистрация: 14.02.2013
Сообщений: 677

Процедура "Умное выделение" для выделения столбцов в пределах диапазона с данными (Решено)

24.10.2017, 10:29. Показов 2792. Ответов 8

Студворк — интернет-сервис помощи студентам
Спасибо пользователю Burk за то, что терпеливо отвечал на мои надоедливые вопросы!

В Экселе есть штатная функция выделения. Если зажать Ctrl + Shift + стрелка вниз, то выделится диапазон данных до конца данных, или пустой столбец до начала данных. Но если требуется выделить пустой столбец рядом и в пределах столбца с данными, и не ограниченный снизу, то, к сожалению, ничего путного не выйдет.
Процедура SmartSelection позволяет решить эту проблему. Вешаем на кнопку или горячую клавишу, и пользуемся.

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
Sub SmartSelection()
Dim i As Long, RAC As Range, LHoriz As Boolean, y As Long, j As Long
Dim RCol As Long, LAC As Range, ineqCols As Boolean
Dim RHoriz As Boolean, rng As Range, AR As Range, cntCols As Long
    cntCols = Selection.Columns.Count
    Set LAC = Selection(1)
    Set RAC = LAC.Offset(0, cntCols - 1)
    RCol = RAC.Column
    ineqCols = cntCols > 1 ' неравенство столбиков. True, если первый
    ' и последний столбики диапазона - это разные столбики.
    
    ' На случай, если первая строка выделения расположена выше диапазона
    ' считаем строки j
    For j = 0 To Selection.Rows.Count - 1
        If ineqCols Then ' Для диапазонов из нескольких столбиков
            i = 0
            ' отдельно проверяем наличие данных влево от выделения,
            ' считаем только до первого столбика
            Do Until LHoriz Or RHoriz Or i = LAC.Column - 1
                i = i + 1
                If Len(LAC.Offset(j, -i).Value) Then
                    LHoriz = True
                    Set AR = LAC.Offset(j, -i)
                    Exit For
                End If
            Loop
            ' Если влево данных не нашли, смотрим вправо
            If Not LHoriz Then
                i = 0
                Do Until RHoriz Or i = 20
                    i = i + 1
                    If Len(RAC.Offset(j, i).Value) Then
                        RHoriz = True
                        Set AR = RAC.Offset(j, i)
                        Exit For
                    End If
                Loop
            End If
            ' Если данных не нашли ни влево, ни в право, и это последняя строка
            ' диапазона, то завершаем процедуру.
            If Not LHoriz And Not RHoriz And j = Selection.Rows.Count - 1 Then
                Exit Sub
            End If
        Else ' Для диапазонов из одного столбика
            i = 0
            ' отдельно проверяем наличие данных влево от выделения,
            ' считаем только до первого столбика
            Do Until LHoriz Or RHoriz Or i = LAC.Column - 1
                i = i + 1
                If Len(LAC.Offset(j, -i).Value) Then
                    LHoriz = True
                    Set AR = LAC.Offset(j, -i)
                    Exit For
                End If
            Loop
            ' Если влево данных не нашли, смотрим вправо
            If Not LHoriz Then
                i = 0
                Do Until RHoriz Or i = 20
                    i = i + 1
                    If Len(LAC.Offset(j, i).Value) Then
                        RHoriz = True
                        Set AR = LAC.Offset(j, i)
                        Exit For
                    End If
                Loop
            End If
            ' Если данных не нашли ни влево, ни в право, и это последняя строка
            ' диапазона, то завершаем процедуру.
            If Not LHoriz And Not RHoriz And j = Selection.Rows.Count - 1 Then
                Exit Sub
            End If
        End If
    Next j
    ' Теперь, когда нашли ячейку с данными, будем проверять весь её столбец
    Set AR = Range(Cells(AR.Row, AR.Column), Cells(Range("A:A").Rows.Count - AR.Row, AR.Column))
    For Each rng In AR
        With rng
            ' Если в текущей ячейке есть данные, а в двух ячейках под ней данных уже нет,
            ' то считаем эту ячейку последней ячейкой диапазона
            If Len(.Value) And (.Offset(1, 0).Value) = 0 And (.Offset(2, 0).Value) = 0 Then
                Range(Cells(LAC.Row, LAC.Column), Cells(.Row, RCol)).Select
                Exit Sub
            End If
        End With
    Next
End Sub
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
24.10.2017, 10:29
Ответы с готовыми решениями:

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

Функция для выделения диапазона разрядов
Всем добрых дней. Есть задумка написать функцию, которая будет выделять диапазон разрядов и будет их сдвигать вправо. То есть такого вид...

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

8
1847 / 1162 / 354
Регистрация: 11.07.2014
Сообщений: 4,107
24.10.2017, 14:54
SrgKord, когда мне нужно выделить неограниченные снизу, столбцы, то я просто ухожу мышкой на имена (номера) столбцов и выделяю, без всяких процедур и кнопок, нужные мне. В пределах данных или пустых, или их комбинации - не волнует. Зачем доставать правое ухо левой рукой через голову.
0
49 / 31 / 2
Регистрация: 14.02.2013
Сообщений: 677
24.10.2017, 15:48  [ТС]
Burk, а если надо выделить пустой столбец, но не до конца листа, а строго по конец соседнего заполненного столбца?
0
1847 / 1162 / 354
Регистрация: 11.07.2014
Сообщений: 4,107
24.10.2017, 16:14
SrgKord, ну а если вам надо выделить лесенку до конца станицы, то выделяете при помощи Ctrl, нужные вам, верхние ячейки в столбцах в любом порядке и запускаете макрос. Вот только ума не приложу на зачем это надо. Видимо, интеллект у меня тает
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
Sub SrgSelectStairs()
'выделение лесенкой
Dim S As String, Arr() As String, I As Integer, J As Integer
S = Selection.Address
Arr = Split(S, ",")
S = ""
For J = 0 To UBound(Arr)
  I = InStrRev(Arr(J), "$")
  S = S & Arr(J) & ":" & Left(Arr(J), I) & Rows.Count & ","
Next
Range(Arr(0)).Select
Range(Left(S, Len(S) - 1)).Select
End Sub
0
Динохромный
1639 / 776 / 288
Регистрация: 22.12.2015
Сообщений: 2,422
24.10.2017, 16:24
SrgKord, код можно упростить (если я правильно разобрался в вашем алгоритме, то все различие будет в том, что ваш код допускает одну пустую ячейку в соседнем столбце, а код ниже будет выделять до нее. Если это принципиальный момент, можно допилить).
Кликните здесь для просмотра всего текста
Visual Basic
1
2
3
4
5
6
7
8
Public Sub select_left_right()
    Selection.Cells(1, 1).Select
    If Not (IsEmpty(Selection.End(xlToLeft)) Or IsEmpty(Selection.End(xlToLeft).End(xlDown))) Then
        Intersect(Range(Selection.End(xlToLeft).End(xlDown), Selection), Selection.EntireColumn).Select
    ElseIf Not (IsEmpty(Selection.End(xlToRight)) Or IsEmpty(Selection.End(xlToRight).End(xlDown))) Then
        Intersect(Range(Selection.End(xlToRight).End(xlDown), Selection), Selection.EntireColumn).Select
    End If
End Sub
1
1847 / 1162 / 354
Регистрация: 11.07.2014
Сообщений: 4,107
24.10.2017, 17:12
SrgKord, Sub Rovno для выделения по соседнему, SrgSelect, если просто выделить в строке, нужные вам ячейки, без использование Ctrl (строчное выделение подряд)

Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Sub Rovno()
Dim I As Integer, J As Integer, LastRow As Long
'для столбца справа, если нужен слева, то J-1
J = Selection.Column: I = Selection.Row
LastRow = Cells(Rows.Count, J + 1).End(xlUp).Row
Range(Cells(1, J), Cells(LastRow, J)).Select
End Sub
 
Sub SrgSelect()
Dim S As String
S = Selection.Address
I = InStrRev(S, "$")
Range(Left(S, I) & Rows.Count).Select
End Sub
1
49 / 31 / 2
Регистрация: 14.02.2013
Сообщений: 677
25.10.2017, 05:08  [ТС]
Burk, Мне, например, для комбинации с Ctrl+D не хватает именно такой функции. Вот чтобы не протягивать значение мышью по пицот позиций вниз, а просто, например, Alt+S и Ctrl+D, и готово. Если Ctrl+Shift+стрелка вниз, то выделит до последней строки на листе.

Dinoxromniy, да уж, проще значительно. Только надо чтобы вместо Selection.EntireColumn использовалось то количество столбцов, которое было в изначальном выделении. Разве что Offset сделать на количество столбцов - 1.
Примерно так, проверил, работает:
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
Public Sub select_left_right()
Dim cName As String, c2Name, rng As String
    cName = Mid(Selection.Address, 2, 1)
    c2Name = Mid(Selection.Offset(0, ((Selection.Columns.Count) - 1)).Address, 2, 1)
    rng = Range(cName & ":" & c2Name).Address
    If Not (IsEmpty(Selection.End(xlToLeft)) Or IsEmpty(Selection.End(xlToLeft).End(xlDown))) Then
        Intersect(Range(Selection.End(xlToLeft).End(xlDown), Selection), Range(rng)).Select
    ElseIf Not (IsEmpty(Selection.End(xlToRight)) Or IsEmpty(Selection.End(xlToRight).End(xlDown))) Then
        Intersect(Range(Selection.End(xlToRight).End(xlDown), Selection), Selection.EntireColumn).Select
    End If
End Sub
0
Динохромный
1639 / 776 / 288
Регистрация: 22.12.2015
Сообщений: 2,422
25.10.2017, 09:20
Цитата Сообщение от SrgKord Посмотреть сообщение
Разве что Offset сделать на количество столбцов - 1.
Полагаю, тут удобнее воспользоваться свойством reszie объекта range. Код фактически должен растянуть полученное выделение до ширины, равной количеству столбцов в первоначальном выделении. Что-то вроде:
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
Public Sub select_left_right_sclmn()
    Dim i  As Integer
    i = Selection.Columns.Count
    Selection.Cells(1, 1).Select
    If Not (IsEmpty(Selection.End(xlToLeft)) Or IsEmpty(Selection.End(xlToLeft).End(xlDown))) Then
        Intersect(Range(Selection.End(xlToLeft).End(xlDown), Selection), Selection.EntireColumn).Select
    ElseIf Not (IsEmpty(Selection.End(xlToRight)) Or IsEmpty(Selection.End(xlToRight).End(xlDown))) Then
        Intersect(Range(Selection.End(xlToRight).End(xlDown), Selection), Selection.EntireColumn).Select
    End If
    Selection.Resize(Selection.Rows.Count, i).Select
End Sub
0
49 / 31 / 2
Регистрация: 14.02.2013
Сообщений: 677
25.10.2017, 10:03  [ТС]
Цитата Сообщение от Dinoxromniy Посмотреть сообщение
Полагаю, тут удобнее воспользоваться свойством reszie объекта range. Код фактически должен растянуть полученное выделение до ширины, равной количеству столбцов в первоначальном выделении. Что-то вроде:
Мои опыты с этим методом через раз приводят к ошибке. На msdn информация скудная, я не знаю, какие значения оно ждёт. Введу 1,1 - расширит. Введу 2,1 - ошибка. Ну это к примеру. Я не стал время терять, сделал свою функцию. Сперва именно ресайзом хотел.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
25.10.2017, 10:03
Помогаю со студенческими работами здесь

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

Выделение произвольного диапазона для копирования
Возник необычный вопрос. Выделяя произвольный диапазон,можно задать форматирование ячеек,а вот при попытке копирования выдаёт сообщение:...

Заполнение именованного диапазона данными из другого диапазона по условию: код не работает
Заполняю таблицу с данными о пищевой ценности продуктов. Простейший скрипт, ищущий совпадение в одной таблице (вроде БД), и, если...

Выделение диапазона для поиска информации поочерёдно
Приветствую! Прошу помочь с выбором верного решения для следующей задачи. Есть данные в виде множества столбцов одной строки, условно -...

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


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

Или воспользуйтесь поиском по форуму:
9
Ответ Создать тему
Новые блоги и статьи
Очистка реквизитов документа при копировании
Maks 09.04.2026
Алгоритм из решения ниже применим как для типовых, так и для нетиповых документов на самых различных конфигурациях. Задача: при копировании документа очищать определенные реквизиты и табличную. . .
модель ЗдравоСохранения 8. Подготовка к разному выполнению заданий
anaschu 08.04.2026
https:/ / github. com/ shumilovas/ med2. git main ветка * содержимое блока дэлэй из старой модели теперь внутри зайца новой модели 8ATzM_2aurI
Блокировка документа от изменений, если он открыт у другого пользователя
Maks 08.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа, разработанного в конфигурации КА2. Задача: запретить редактирование документа, если он открыт у другого пользователя. / / . . .
Система безопасности+живучести для сервера-слоя интернета (сети). Двойная привязка.
Hrethgir 08.04.2026
Далее были размышления о системе безопасности. Сообщения с наклонным текстом - мои. А как нам будет можно проверить, что ссылка наша, а не подделана хулиганами, которая выбросит на другую ветку и. . .
Модель ЗдрввоСохранения 7: больше работников, больше ресурсов.
anaschu 08.04.2026
работников и заданий может быть сколько угодно, но настроено всё так, что используется пока что только 20% kYBz3eJf3jQ
Дальние перспективы сервера - слоя сети с космологическим дизайном интефейса карты и логики.
Hrethgir 07.04.2026
Дальнейшее ближайшее планирование вывело к размышлениям над дальними перспективами. И вот тут может быть даже будут нужны оценки специалистов, так как в дальних перспективах всё может очень сильно. . .
Горе от ума
kumehtar 07.04.2026
Эта мне ментальная установка, что вот прямо сейчас, мол, мне для полного счастья не хватает (нужное вписать), и когда я этого достигну - тогда и полный кайф. Одна из самых сильных ловушек на пути. . . .
Использование значений реквизитов справочника в документе, с определенными условиями и правами
Maks 07.04.2026
1. Контроль срока действия договора Алгоритм из решения ниже реализован на примере нетипового документа "ЗаявкаНаРаботу", разработанного в конфигурации КА2. Задача: уведомлять пользователя, если. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru