Excel миф несколько диапазонов

 

maximych

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

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

#1

08.04.2016 10:29:30

Всем привет!
Нужна помощь в написании кода.
Его задача — автоматизация выделения нескольких (допустим 60) несмежных диапазонов c одинаковым смещением вправо. Габариты диапазонов известны заранее и фиксированы. Для удобства «базовый» диапазон задан как именованный («test»).
Например выделяю 2 диапазона:

Код
Sub select()
Application.Union(Range("test"), Range("test").Offset(0, ).Select
End Sub

Собственно вопрос, как «зациклить» выделение, чтобы выделилось разом 60 таких кусков?
Заранее благодарен!

Изменено: maximych08.04.2016 12:47:08

 

Юрий М

Модератор

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

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

maximych, код следует оформлять соответствующим тегом: ищите такую кнопку и исправьте своё сообщение. Спасибо!
И, кстати, у Вас с таким названием макроса ничего не краснеет? ))

 

Апострофф

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

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

#3

08.04.2016 11:45:38

так?

Код
Sub Select_()
Set r = Range("test")
For n = 1 To 59
  Set r = Union(r, r.Offset(0, 8))
Next
r.Select
End Sub
 

LVL

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

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

Вопрос только в том для чего выделять 60 не смежных диапазонов  8-0

 

maximych

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

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

Апострофф, спасибо! Работает как надо.
А если несколько усложнить задачу.. Количество диапазонов остается фиксированным, количество столбцов в каждом диапазоне также фиксировано и равно 7, а вот количество строк задается пользователем, через MsgBox например. Реально ?

Изменено: maximych08.04.2016 13:00:03

 

Юрий М

Модератор

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

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

А такой диапазон у Вас имеется?

 

maximych

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

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

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

 

Юрий М

Модератор

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

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

:D

 

Юрий М

Модератор

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

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

#9

08.04.2016 13:08:09

Цитата
maximych написал:
а вот количество строк задается пользователем, через MsgBox например. Реально ?

Через MsgBox нереально — это только информационный инструмент. Смотрите в сторону InputBox.
Но непонятен один момент: если диапазон УЖЕ задан, в нём ведь и количество строк фиксированное.

 

maximych

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

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

#10

08.04.2016 13:15:26

Цитата
Юрий М написал:
Но непонятен один момент: если диапазон УЖЕ задан, в нём ведь и количество строк фиксированное.

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

Изменено: maximych08.04.2016 13:17:32

 

Юрий М

Модератор

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

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

#11

08.04.2016 13:20:55

Попробуйте вариант с произвольным диапазоном, который укажите сами:

Код
Sub Select_()
Dim r As Range
    Set r = Application.InputBox("Выберите мыхой стартовый диапазон.", "Выбираем диапазон.", Type:=8)
    For n = 1 To 59
      Set r = Union(r, r.Offset(0, 8))
    Next
    r.Select
End Sub
 

maximych

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

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

#12

08.04.2016 13:24:29

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

Код
Sub diap()
col = 27
row = 10
rowqt = InputBox("Количество выделяемых строк?")
Set r = Range(Cells(row, col), Cells(row + rowqt - 1, col + 6))
For n = 1 To 60
  Set r = Union(r, r.Offset(0, )
Next
r.Select
End Sub

Изменено: maximych08.04.2016 13:26:05

 

Юрий М

Модератор

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

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

А вариант с Application.InputBox не смотрели?

 

maximych

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

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

#14

08.04.2016 13:48:58

Цитата
Юрий М написал: вариант с Application.InputBox не смотрели?

Все шикарно работает. Ваш вариант особенно удобен тем что можно произвольно выделить базовую область.
Благодарствуйте!

Изменено: maximych08.04.2016 14:19:25

Определение блока ячеек, состоящего из объединения двух и более диапазонов, с помощью метода Application.Union из кода VBA Excel. Примеры объединения.

Описание

Application.Union – это метод VBA Excel, который возвращает объект Range, являющийся объединением двух или более указанных диапазонов.

Синтаксис

Application.Union (Arg1, Arg2, Arg3, ..., Arg30)

  • Arg1, Arg2 – обязательные аргументы, представляющие из себя диапазоны ячеек (объекты Range).
  • Arg3, …, Arg30* – необязательные аргументы, представляющие из себя диапазоны ячеек (объекты Range).

* Допустимо использование до 30 аргументов включительно.

Примеры

Пример 1
Объединение диапазонов, занимающих прямоугольную область:

Sub Primer1()

Dim rngun As Range, arg1 As Range, arg2 As Range, arg3 As Range

    Set arg1 = Range(«B2:D6»)

    Set arg2 = Range(«D2:F6»)

    Set arg3 = Range(«B5:F9»)

    Set rngun = Application.Union(arg1, arg2, arg3)

MsgBox «Адрес объединенного диапазона: « & rngun.Address

End Sub

Объединение диапазонов, занимающих прямоугольную область

Объединение диапазонов, занимающих прямоугольную область

Пример 2
Объединение несмежных диапазонов:

Sub Primer2()

Dim rngun As Range, arg1 As Range, arg2 As Range, arg3 As Range

    Set arg1 = Range(«B2:C4»)

    Set arg2 = Range(«E2:F5»)

    Set arg3 = Range(«C7:E9»)

    Set rngun = Application.Union(arg1, arg2, arg3)

MsgBox «Адрес объединенного диапазона: « & rngun.Address

End Sub

Объединение несмежных диапазонов

Объединение несмежных диапазонов

Пример 3
Объединение пересекающихся диапазонов:

Sub Primer3()

Dim rngun As Range, arg1 As Range, arg2 As Range, arg3 As Range

    Set arg1 = Range(«B2:E5»)

    Set arg2 = Range(«C3:F9»)

    Set arg3 = Range(«D4:D10»)

    Set rngun = Application.Union(arg1, arg2, arg3)

MsgBox «Адрес объединенного диапазона: « & rngun.Address

End Sub

Объединение пересекающихся диапазонов

Объединение пересекающихся диапазонов

Самый наглядный вариант объединения ячеек рассмотрен в первом примере, когда объединяемые диапазоны образуют одну прямоугольную область. Во втором и третьем примерах результат объединения аналогичен использованию свойства Range объекта Worksheet:

Set rngun = Range(arg1.Address & «, « & arg2.Address & «, « & arg3.Address)

I was looking further to see if there is a better way of writing concatenate function and found this. It seems that we all have the same working principle for the function. So its ok.

But my function is different that it can take multiple parameters, in combination of ranges, texts and numbers.

I assume that a delimiter is mandatory, so if i don’t need it i just put «» as the last parameter).

I also assume that blank cells are not to be skipped. That’s the reason why i want the function to take multiple parameters, so i can easily omit those that that i don’t want in the concatenation.

Example of use:

=JoinText(A1:D2,F1:I2,K1:L1,";")

You can also use together text and number among the parameters:

=JoinText(A1:D2,123,F1:I2,K1:L1,"PQR",";")

I’d love to hear any comments or suggestions where it can be improved.

Here is the code.

Public Function JoinText(ParamArray Parameters() As Variant) As String
    Dim p As Integer, c As Integer, Delim As String

    Delim = Parameters(UBound(Parameters))

    For p = 0 To UBound(Parameters) - 1
        If TypeName(Parameters(p)) = "Range" Then
            For c = 1 To Parameters(p).Count
                JoinText = JoinText & Delim & Parameters(p)(c)
            Next c
        Else
            JoinText = JoinText & Delim & Parameters(p)
        End If
    Next p

    JoinText = Replace(JoinText, Delim, "", , 1, vbBinaryCompare)

End Function

Lnduk

1 / 1 / 0

Регистрация: 12.12.2019

Сообщений: 11

1

Excel

12.12.2019, 12:51. Показов 3802. Ответов 10

Метки нет (Все метки)


Студворк — интернет-сервис помощи студентам

Всем привет!
Коллеги, очень нужна помощь. Всю голову и гугл сломал.
Есть умная таблица в excel. В ней куча столбцов.
Нужно получить массив, для дальнейшей обработки, состоящий из значений столбцов таблицы:
employeeid(число типа long), FIO(string), department (string).
Кол-во строк достаточно большое для прямого перебора, не хотелось бы к нему прибегать.
В качестве более «элегантного» решения задумал такую конструкцию:

Visual Basic
1
2
3
4
5
6
7
8
Dim tbl As ListObject
Set tbl = Worksheets("data").ListObjects("employees")
    
Dim rID As Range: Set rID = tbl.ListColumns("employeeid").DataBodyRange
Dim rFIO As Range: Set rFIO = tbl.ListColumns("FIO").DataBodyRange
Dim rDep As Range: Set rDep = tbl.ListColumns("department").DataBodyRange
Dim rUsers As Range: Set rUsers = Union(rID, rFIO, rDep)
Dim arrUsersAll: arrUsersAll = rUsers

Не могу понять почему, но Union выдает странные результаты: только первые 2 диапазона.
Анализ помог определить, что затыка в 3-ем столбце. Если указать

Visual Basic
1
Union(rDep, rID, rFIO)

то выдаст только значения department.
Далее еще попробовал и обнаружил, что Union объединяет только рядом стоящие диапазоны. Т.е. rID это 1-ый столбец таблицы, rFIO 2-ой, а rDep — 5-ый.

Вопрос:
1. Почему так происходит? В описании метода не написано, что он объединяет только рядом стоящие диапазоны.
2. Как решить задачку?



0



208 / 183 / 43

Регистрация: 02.08.2019

Сообщений: 585

Записей в блоге: 23

12.12.2019, 13:47

2

Lnduk, привет! Union работает только со смежными или пересекающимися диапазонами, по этому она вам не подойдет

вот описание которое нашел:

Функция VBA Union возвращает объект Range, который представляет собой объединение двух объектов типа Range. Объединение содержит все ячейки, относящиеся к исходным диапазонам. Если адрес объединения двух диапазонов совпадает с адресом второго диапазона, первый диапазон входит в состав второго диапазона.

Добавлено через 23 секунды
или тут

https://qarchive.ru/2333452_me… ryvajutsja



0



1 / 1 / 0

Регистрация: 12.12.2019

Сообщений: 11

12.12.2019, 13:58

 [ТС]

3

Спасибо.
Но очень бы хотелось совета, как в этом случае поступить. Не хочу использовать перебор, манипуляции с исходными данными тоже не комильфо, использовать временный лист для объединения нужных диапазонов не самое красивое решение.
Другое пока в голову не приходит(



0



208 / 183 / 43

Регистрация: 02.08.2019

Сообщений: 585

Записей в блоге: 23

12.12.2019, 14:05

4

Lnduk, переместите столбики рядом друг с дргом

Добавлено через 1 минуту
это самое простое решение работает я проверил

Добавлено через 2 минуты
или закидывайте в массив всю таблицу



0



1 / 1 / 0

Регистрация: 12.12.2019

Сообщений: 11

12.12.2019, 14:12

 [ТС]

5

Цитата
Сообщение от art1289
Посмотреть сообщение

переместите столбики рядом друг с дргом

не вариант в моем случае: неприкосновенность исходных данных главное условие. Но работает — согласен.

Цитата
Сообщение от art1289
Посмотреть сообщение

или закидывайте в массив всю таблицу

пока так и сделал. Но в этом случае если поменяется порядок столбцов (кто знает что пользователю в голову придет) придется отдельный блок для поиска нужных данных в массиве делать.



0



Aleksan7

109 / 60 / 27

Регистрация: 22.02.2018

Сообщений: 189

12.12.2019, 14:12

6

Lnduk,
как вариант использовать 3 массива по 1 массиву на каждый рейнж,
если важно иметь один массив то эти три массива записать на лист «буфер» в соседние столбцы и считать как один массив,
можно через OLEDB не открывая книгу исходных данных:

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

Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Function SQL_excel(sSQL As String, sFilePath As String, rReportRange As Range, Optional HDR As String) As Object
If HDR = "" Then
    HDR = "No"
End If
Dim nCon As New ADODB.Connection
Dim nRs As New ADODB.Recordset
nCon.Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source='" & sFilePath & "'; Extended Properties='Excel 12.0;HDR=" & HDR & ";IMEX=1';"
nRs.Open sSQL, nCon
rReportRange.CopyFromRecordset nRs
nRs.Close
nCon.Close
End Function
 
Sub FromCloseBook()
    Dim sSQL As String
    Dim sFilePath As String
    sSHName = "ЛистДанных" 'имя листа
    sFilePath = "C:UsersAleksan7Desktopоктябрь.xlsx" 'путь к файлу
    sSQL = "SELECT F1, F2, F5 FROM [" & sSHName & "$]"
    Call SQL_excel(sSQL, sFilePath, ActiveSheet.Cells(1, 1))
End Sub



0



KoGG

5590 / 1580 / 406

Регистрация: 23.12.2010

Сообщений: 2,366

Записей в блоге: 1

12.12.2019, 14:13

7

Union может содержать и далеко стоящие диапазоны.
Только вот операцией

Visual Basic
1
arrUsersAll = rUsers

массив всего Union не получится.
Для получения массива все равно надо поэлементно загонять в массив каждую ячейку Union.



0



Lnduk

1 / 1 / 0

Регистрация: 12.12.2019

Сообщений: 11

12.12.2019, 14:44

 [ТС]

8

Aleksan7,

Цитата
Сообщение от Aleksan7
Посмотреть сообщение

как вариант использовать 3 массива по 1 массиву на каждый рейнж

их же потом все равно объединять. Вопрос как — еще не гуглил. Если подскажешь — буду очень признателен.

Цитата
Сообщение от Aleksan7
Посмотреть сообщение

записать на лист «буфер»

Не хочу использовать такой метод, но как вариант конечно рабочий.

Цитата
Сообщение от Aleksan7
Посмотреть сообщение

сегодня в соседней теме выкладывал код

Вот за это тоже спасибо. Интересное решение. Подумаю как применить…

Добавлено через 2 минуты
KoGG, не в этой строке дело: уже на этапе

Visual Basic
1
Set rUsers = Union(rID, rFIO, rDep)

в Union загоняются только первые смежные диапазоны.



0



109 / 60 / 27

Регистрация: 22.02.2018

Сообщений: 189

12.12.2019, 15:18

9

Lnduk, есть еще способ, изварщённо конечно, но…
Общиймассив = Array(Массив1, Массив2, Массив3)
обращаться к нему придётся так
элемент = Общиймассив(i)(k,1)
где i номер рейнжа с 0 до 2,
k номер строки начиная с 1 тк забирали с листа,
1 всегда 1 так как забирали столбец



0



1 / 1 / 0

Регистрация: 12.12.2019

Сообщений: 11

12.12.2019, 15:46

 [ТС]

10

Aleksan7, спасибо, попробую реализовать, но придется немного перепиливать обработчик — он заточен на обычный массив.
А через redim preserve добавить в один массив — возможно? Туплю немного…



0



109 / 60 / 27

Регистрация: 22.02.2018

Сообщений: 189

13.12.2019, 09:23

11

Lnduk, redim preserve меняет последнюю размерность массива, не вижу как он тут может помочь
На самом деле оптимальный вариант я вижу это манипуляции с листом буфер
1. создали новую невидимую книгу,
2. скомбинировали на листе нужный массив, забрали его
3. закрыли книгу не сохраняя

в итоге получим нормальный массив, с привычными адресами элементов, и не нужно обработчик править



0



IT_Exp

Эксперт

87844 / 49110 / 22898

Регистрация: 17.06.2006

Сообщений: 92,604

13.12.2019, 09:23

11

Понравилась статья? Поделить с друзьями:
  • Excel миф макрос при открытии
  • Excel метки на листе
  • Excel миф копирование файлов
  • Excel метки на графике
  • Excel миф количество значений