Копирование массива в массив vba excel

Example

You can copy a VBA array into an array of the same type using the = operator. The arrays must be of the same type otherwise the code will throw a «Can’t assign to array» compilation error.

Dim source(0 to 2) As Long
Dim destinationLong() As Long
Dim destinationDouble() As Double

destinationLong = source     ' copies contents of source into destinationLong
destinationDouble = source   ' does not compile

The source array can be fixed or dynamic, but the destination array must be dynamic. Trying to copy to a fixed array will throw a «Can’t assign to array» compilation error. Any preexisting data in the receiving array is lost and its bounds and dimenions are changed to the same as the source array.

Dim source() As Long
ReDim source(0 To 2)

Dim fixed(0 To 2) As Long
Dim dynamic() As Long

fixed = source   ' does not compile
dynamic = source ' does compile

Dim dynamic2() As Long
ReDim dynamic2(0 to 6, 3 to 99) 

dynamic2 = source ' dynamic2 now has dimension (0 to 2)

Once the copy is made the two arrays are seperate in memory, i.e. the two variables are not references to same underlying data, so changes made to one array do not appear in the other.

Dim source(0 To 2) As Long
Dim destination() As Long

source(0) = 3
source(1) = 1
source(2) = 4

destination = source
destination(0) = 2

Debug.Print source(0); source(1); source(2)                ' outputs: 3 1 4
Debug.Print destination(0); destination(1); destination(2) ' outputs: 2 1 4

Copying Arrays of Objects

With arrays of objects the references to those objects are copied, not the objects themselves. If a change is made to an object in one array it will also appear to be changed in the other array — they are both referencing the same object. However, setting an element to a different object in one array won’t set it to that object the other array.

Dim source(0 To 2) As Range
Dim destination() As Range

Set source(0) = Range("A1"): source(0).Value = 3
Set source(1) = Range("A2"): source(1).Value = 1
Set source(2) = Range("A3"): source(2).Value = 4

destination = source

Set destination(0) = Range("A4")   'reference changed in destination but not source

destination(0).Value = 2           'affects an object only in destination
destination(1).Value = 5           'affects an object in both source and destination

Debug.Print source(0); source(1); source(2)                  ' outputs 3 5 4
Debug.Print destination(0); destination(1); destination(2)   ' outputs 2 5 4

Variants Containing an Array

You can also copy an array into and from a variant variable. When copying from a variant, it must contain an array of the same type as the receiving array otherwise it will throw a «Type mismatch» runtime error.

Dim var As Variant
Dim source(0 To 2) As Range
Dim destination() As Range

var = source
destination = var

var = 5
destination = var  ' throws runtime error

Копирование массивов

Вы можете скопировать массив VBA в массив того же типа, используя оператор = . Массивы должны быть одного типа, иначе код будет генерировать ошибку компиляции «Can not assign to array».

Dim source(0 to 2) As Long
Dim destinationLong() As Long
Dim destinationDouble() As Double

destinationLong = source     ' copies contents of source into destinationLong
destinationDouble = source   ' does not compile

Исходный массив может быть фиксированным или динамическим, но целевой массив должен быть динамическим. Попытка скопировать в фиксированный массив вызовет ошибку компиляции «Can not assign to array». Любые существующие данные в принимающем массиве теряются, а его границы и размеры изменяются так же, как исходный массив.

Dim source() As Long
ReDim source(0 To 2)

Dim fixed(0 To 2) As Long
Dim dynamic() As Long

fixed = source   ' does not compile
dynamic = source ' does compile

Dim dynamic2() As Long
ReDim dynamic2(0 to 6, 3 to 99) 

dynamic2 = source ' dynamic2 now has dimension (0 to 2)

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

Dim source(0 To 2) As Long
Dim destination() As Long

source(0) = 3
source(1) = 1
source(2) = 4

destination = source
destination(0) = 2

Debug.Print source(0); source(1); source(2)                ' outputs: 3 1 4
Debug.Print destination(0); destination(1); destination(2) ' outputs: 2 1 4

Копирование массивов объектов

С массивами объектов копируются ссылки на эти объекты, а не сами объекты. Если изменение в объекте в одном массиве будет также изменено в другом массиве — они оба ссылаются на один и тот же объект. Однако установка элемента в другой объект в одном массиве не приведет его к этому объекту в другом массиве.

Dim source(0 To 2) As Range
Dim destination() As Range

Set source(0) = Range("A1"): source(0).Value = 3
Set source(1) = Range("A2"): source(1).Value = 1
Set source(2) = Range("A3"): source(2).Value = 4

destination = source

Set destination(0) = Range("A4")   'reference changed in destination but not source

destination(0).Value = 2           'affects an object only in destination
destination(1).Value = 5           'affects an object in both source and destination

Debug.Print source(0); source(1); source(2)                  ' outputs 3 5 4
Debug.Print destination(0); destination(1); destination(2)   ' outputs 2 5 4

Варианты, содержащие массив

Вы также можете скопировать массив в переменную варианта и из нее. При копировании из варианта он должен содержать массив того же типа, что и принимающий массив, иначе он будет вызывать ошибку «Ошибка несоответствия типа».

Dim var As Variant
Dim source(0 To 2) As Range
Dim destination() As Range

var = source
destination = var

var = 5
destination = var  ' throws runtime error

Возвращаемые массивы из функций

Функция в нормальном модуле (но не модуле класса) может возвращать массив, помещая () после типа данных.

Function arrayOfPiDigits() As Long()
    Dim outputArray(0 To 2) As Long
    
    outputArray(0) = 3
    outputArray(1) = 1
    outputArray(2) = 4

    arrayOfPiDigits = outputArray
End Function

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

Sub arrayExample()

    Dim destination() As Long
    Dim var As Variant
    
    destination = arrayOfPiDigits()
    var = arrayOfPiDigits
    
    Debug.Print destination(0)          ' outputs 3
    Debug.Print var(1)                  ' outputs 1
    Debug.Print arrayOfPiDigits()(2)    ' outputs 4
    
End Sub

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

Вывод массива через выходной аргумент

Обычно это хорошая практика кодирования для аргументов процедуры как входных данных и для вывода через возвращаемое значение. Однако ограничения VBA иногда требуют, чтобы процедура выводила данные через аргумент ByRef .

Вывод в фиксированный массив

Sub threePiDigits(ByRef destination() As Long)
    destination(0) = 3
    destination(1) = 1
    destination(2) = 4
End Sub

Sub printPiDigits()
    Dim digits(0 To 2) As Long
    
    threePiDigits digits
    Debug.Print digits(0); digits(1); digits(2) ' outputs 3 1 4
End Sub

Вывод массива из метода класса

Выходной аргумент также может использоваться для вывода массива из метода / процедуры в модуле класса

' Class Module 'MathConstants'
Sub threePiDigits(ByRef destination() As Long)
    ReDim destination(0 To 2)
    
    destination(0) = 3
    destination(1) = 1
    destination(2) = 4
End Sub

' Standard Code Module
Sub printPiDigits()
    Dim digits() As Long
    Dim mathConsts As New MathConstants
    
    mathConsts.threePiDigits digits
    Debug.Print digits(0); digits(1); digits(2) ' outputs 3 1 4
End Sub

Передача массивов на прохождение

Массивы могут передаваться в процедуры, помещая () после имени переменной массива.

Function countElements(ByRef arr() As Double) As Long
    countElements = UBound(arr) - LBound(arr) + 1
End Function

Массивы должны передаваться по ссылке. Если не указан какой-либо передающий механизм, например myFunction(arr()) , то VBA будет считать ByRef по умолчанию, однако хорошая практика кодирования делает его явным. Попытка передать массив по значению, например myFunction(ByVal arr()) приведет к ошибке компиляции «Array argument должно быть ByRef» (или ошибке компиляции «Синтаксическая ошибка», если Auto Syntax Check не проверена в параметрах VBE) ,

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

Sub testArrayPassing()
    Dim source(0 To 1) As Long
    source(0) = 3
    source(1) = 1
    
    Debug.Print doubleAndSum(source)  ' outputs 8
    Debug.Print source(0); source(1)  ' outputs 6 2
End Sub

Function doubleAndSum(ByRef arr() As Long)
    arr(0) = arr(0) * 2
    arr(1) = arr(1) * 2
    doubleAndSum = arr(0) + arr(1)
End Function

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

Function doubleAndSum(ByRef arr() As Long)
    doubleAndSum = arr(0) * 2 + arr(1) * 2
End Function

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

Function doubleAndSum(ByRef arr() As Long)
    Dim copyOfArr() As Long
    copyOfArr = arr
    
    copyOfArr(0) = copyOfArr(0) * 2
    copyOfArr(1) = copyOfArr(1) * 2
    
    doubleAndSum = copyOfArr(0) + copyOfArr(1)
End Function

Копирование значений из диапазона ячеек в массив и обратно с помощью VBA Excel. Простейшие примеры обмена значениями между диапазоном и массивом.

Как известно, VBA обрабатывает информацию в массивах значительно быстрее, чем в ячейках рабочего листа Excel. Поэтому, при работе с большими объемами данных, удобнее использовать массивы, чем наблюдать во время выполнения кода за мерцанием изображения на экране или просто смотреть в неизменную картинку, если обновление экрана отключено (Application.ScreenUpdating = False). Здесь обмен значениями между массивом и диапазоном ячеек будет вполне уместен.

Копирование значений из диапазона ячеек в массив

Чтобы скопировать значения из диапазона ячеек в массив, необходимо объявить переменную универсального типа (As Variant) и присвоить ей значения диапазона ячеек с помощью оператора присваивания (=):

Dim a As Variant

a = Range(«A1:C3»)

VBA Excel автоматически преобразует объявленную переменную в двумерный массив, соответствующий размерности диапазона ячеек, в нашем случае в массив — a(1 To 3, 1 To 3), и заполняет его значениями. Нумерация измерений массивов, созданных таким образом, начинается с единицы (1).

Можно, в этом случае, объявить сразу динамический массив, чтобы изначально указать, что эта переменная будет массивом. Так как свойством диапазона ячеек по умолчанию в VBA Excel является значение (Value), его можно в коде явно не указывать, но, при желании, можно и указать. Получится такая конструкция, аналогичная первой:

Dim a() As Variant

a = Range(«A1:C3»).Value

Стоит отметить, что для копирования значений из диапазона ячеек в массив можно использовать только обычную переменную или динамический массив универсального типа (Variant). VBA Excel автоматически преобразовывает их в двумерный массив. Если объявить двумерный массив с указанной заранее размерностью, использовать его не получится, будет сгенерирована ошибка с сообщением: Can’t assign to array (Нельзя назначать массив).

Копирование значений из массива в диапазон ячеек

Значения в диапазон ячеек добавляются из массива с помощью оператора присваивания (=):

Range(«A6:F15») = a

‘или

Range(«A6:F15»).Value = a

‘где a — переменная двумерного массива

Обратите внимание, что вставить значения в диапазон ячеек можно только из двумерного массива. Размерность такого массива может начинаться с нуля (0). Количество элементов в измерениях массива должно совпадать с количеством строк и столбцов в диапазоне ячеек. Если вам нужно вставить значения в одну строку или в один столбец, укажите размерность единственной строки или единственного столбца как (0) или (1 To 1), если вы хотите использовать нумерацию измерений своего массива с единицы. Например, для записи десяти значений из массива в одну строку можно объявить такой массив — massiv(9, 0), или в один столбец — massiv(0, 9).

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

Обмен значениями между двумя диапазонами

Обмен значениями можно осуществить в VBA Excel не только между массивом и диапазоном, но и между двумя диапазонами одинаковой размерности:

Range(«B2:D6») = Range(«G7:I11»).Value

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

Если диапазон ячеек, принимающий значения, по размеру меньше диапазона-источника, то он будет заполнен полностью:

Range(«B2:D6») = Range(«G5:L13»).Value

Если принимающий диапазон ячеек по размеру больше передающего, то часть его будет заполнена значениями диапазона-источника, а остальные ячейки — значениями #Н/Д:

Range(«B2:D6») = Range(«G7:H9»).Value

Простейшие примеры обмена значениями

Эти примеры составлены так, чтобы вам не пришлось совершать лишних действий, просто скопируйте их в свой модуль любой книги Excel с поддержкой макросов и запустите по очереди на выполнение.

Пример 1

Заполнение двумерного массива значениями и и их присвоение диапазону ячеек на рабочем листе Excel:

Sub Test1()

Dim a(2, 2) As Variant

a(0, 0) = «телепузик»

a(0, 1) = «журналист»

a(0, 2) = «ящерица»

a(1, 0) = «короед»

a(1, 1) = «утенок»

a(1, 2) = «шмель»

a(2, 0) = 200

a(2, 1) = 300

a(2, 2) = 400

Range(«A1:C3»).Value = a

End Sub

В данном случае переменная массива не обязательно должна быть универсального типа (As Variant), например, если бы в нее записывались только текстовые данные, ее можно было бы объявить как строковую (As String), и все бы работало.

Пример 2

Объявление обычной переменной универсального типа, присвоение ей значений из диапазона ячеек «A1:C3», записанных кодом первого примера, и вставка этих значений из полученного двумерного массива в диапазон «D10:F12»:

Sub Test2()

Dim a As Variant

a = Range(«A1:C3»)

Range(«D10:F12») = a

End Sub

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

Пример 3

Допустим, на рабочем листе «Лист1» в ячейках «A1:A5» записано количество какого-то товара, а в ячейках «B1:B5» — его цена. Необходимо к этой информации добавить сумму каждого товара, умножив количество на цену, и перенести данные на «Лист2».

Sub Test3()

Dim a As Variant, i As Long

  a = Лист1.Range(«A1:C5»)

    For i = 1 To 5

      a(i, 3) = a(i, 1) _

      * a(i, 2)

    Next

  Лист2.Range(«A1:C5») = a

End Sub

Массив создан сразу с размерностью 5×3 с элементами под суммы. Даже если на первом листе в ячейках «C1:C5» есть какие-то значения, в массиве они будут перезаписаны результатами вычислений.

Копирование значений из массива в массив

Этот пример показывает, как в VBA Excel можно скопировать значения из одного массива в другой:

Sub Test4()

Dim arr1, arr2

    arr1 = Range(«G7:I11»)

    arr2 = arr1

    Range(«B2:D6») = arr2

End Sub


>
копирование массива в массив
, массив в екселе

  • Подписаться на тему
  • Сообщить другу
  • Скачать/распечатать тему



Сообщ.
#1

,
08.04.09, 21:05

    Здравствуйте. Помогите начинающему советом:)
    Неделю назад открыл для себя что такое макрос, применительно к Екселю. Сегодня книжку купил, но все равное не разберусь никак…
    Смысл в том чтоб выгрузить двумерный массив чисел-integer к примеру 1000 на 100, а далее по определенным условиям перегрузить, соответственно уже кусок этого массива в другой массив. Понял как массив создать, как его отфильтровать, а вот выгрузить полученные значения в новый массив не получается. Посоветуйте пожалуйста что-нибудь, желательно куском кода:) Спасибо заранее
    з.ы. два цикла j=1 to 100 внутри i=1 to 1000; отбор значений идет после цикла j и сравнивать хотел там же, по просто думал будет работать чтото типа old(i,j)=new(i,j) а почемуто нет:(

    Сообщение отредактировано: Kugeod — 08.04.09, 21:10

    Master

    MIF



    Сообщ.
    #2

    ,
    08.04.09, 22:42

      Moderator

      ******

      Рейтинг (т): 414

      Мож, стоит попробовать загрузить из старого массива в новый, а не наоборот: new(i,j)=old(i,j)


      Kugeod



      Сообщ.
      #3

      ,
      09.04.09, 06:46

        Я окончательно запутался :(

        Dim newM(1000,100) As Integer
        Dim oldM(1000, 100) As Integer
        Dim i As Integer: Dim j As Integer

        Sub Massiv()
        Randomize
        For i = 1 To 1000
        For j = 1 To 100
        oldM(i, j) = Fix(Rnd + 0.5)
        Next j
        If i > 500 Then newM(i, j) = oldM(i, j)
        Next i
        End Sub

        Выводит ошибку subscript out of range Почему не работает? :(

        Monster

        Akina



        Сообщ.
        #4

        ,
        09.04.09, 07:31

          Цитата Kugeod @ 09.04.09, 06:46

          Почему не работает?

          Потому что с логикой косяк.
          Выполняется цикл по j. От 1 до 100. Завершяется он, когда на очередном витке j становится больше 100, т.е. 101. Но следующей строкой ты делаешь newM(i, j) = oldM(i, j) — при j=101 иной реакции программы ожидать не следовало.

          Сообщение отредактировано: Akina — 09.04.09, 07:31


          GDK



          Сообщ.
          #5

          ,
          09.04.09, 08:42

            ExpandedWrap disabled

              Dim newM(1000, 100) As Integer

              Dim oldM(1000, 100) As Integer

              Dim i As Integer: Dim j As Integer

              Sub Massiv()

              Randomize

              For i = 1 To 1000

                  For j = 1 To 100

                      oldM(i, j) = Fix(Rnd + 0.5)

                      If i > 500 Then newM(i, j) = oldM(i, j)

                  Next j

                  ‘If i > 500 Then newM(i, j) = oldM(i, j)

              Next i

              End Sub

            Это надо было?

            И вот ещё, обрати внимание. Объявляешь массив 0-1000, 0-100. Т.е. такой массив будет содержать 1001 «строку» и 101 «колонку». А цикл начинаешь с номера 1. Т.е. не будет никаких действий с 0-й строкой и нулевой колонкой.

            Добавлено 09.04.09, 08:50
            И зря ты для экспериментов пользуешься такими большими массивами. Проще было бы (0-10, 0-4 ) например.

            Добавлено 09.04.09, 08:53
            И лучше используй Long вместо Integer. Хоть памяти занимает больше, зато гимора в виде сообщений с ошибками намного меньше будет.

            Monster

            Akina



            Сообщ.
            #6

            ,
            09.04.09, 09:24

              Цитата GDK @ 09.04.09, 08:42

              И вот ещё, обрати внимание. Объявляешь массив 0-1000, 0-100. Т.е. такой массив будет содержать 1001 «строку» и 101 «колонку». А цикл начинаешь с номера 1. Т.е. не будет никаких действий с 0-й строкой и нулевой колонкой.

              Это при условии что выше нет незахваченного при копировании Option Base 1. :D


              Kugeod



              Сообщ.
              #7

              ,
              09.04.09, 12:43

                Спасибо за ответы, почти разобрался с копированием. Вопрос возник.

                ExpandedWrap disabled

                  Sub Massiv()

                  Dim g As Integer

                  Randomize

                  For i = 1 To 100

                      For j = 1 To 10

                          oldM(i, j) = Fix((Rnd + 0.6) * 2)

                          If i > 50 Then newM(i, j) = oldM(i, j) ‘это выражение присваивает новому массиву значения только с (50,1) до (100,10)??

                      Next j

                  Next i

                  Worksheets(1).Range(Cells(1, 1), Cells(100, 10)).Value = newM ‘ это я гдето подсмотрел что так можно:)

                  End Sub

                Если первый комментарий в этом коде верный то почему итог выглядит как массив (1,1) (100,10) у которого значения до 50 заполнены нулями, а потом только выводится то что я хочу получить. Как сделать чтобы новый массив был только из 50 элементов по условию? и соответственно выводил 50 на 10.
                Заранее простите за тупость:(

                Monster

                Akina



                Сообщ.
                #8

                ,
                09.04.09, 13:18

                  Цитата Kugeod @ 09.04.09, 12:43

                  Если первый комментарий в этом коде верный то почему итог выглядит как массив (1,1) (100,10) у которого значения до 50 заполнены нулями, а потом только выводится то что я хочу получить.

                  При определении переменной типа Integer (неважно, одиночка или массив) ей присваивается значение «ноль». Потом ты часть массива перезаписываешь — меняешь нули на значение, — а начало так и остаётся всё в нулях.

                  Правильнее — так:

                  ExpandedWrap disabled

                    Dim oldM(1 to 100, 1 to 10) As Integer

                    Dim newM(1 to 50, 1 to 10) As Integer

                    Sub Massiv()

                    Dim i As Integer, j As Integer

                    Randomize Timer

                    For i = 1 To 100

                        For j = 1 To 10

                            oldM(i, j) = (Rnd + 0.6) * 2

                            If i > 50 Then newM(i-50, j) = oldM(i, j)

                        Next j

                    Next i

                    Worksheets(1).Range(Cells(1, 1), Cells(50, 10)).Value = newM

                    End Sub


                  Kugeod



                  Сообщ.
                  #9

                  ,
                  09.04.09, 21:05

                    В принципе я с вашей помощью почти разобрался. Akina вы предлагаете

                    ExpandedWrap disabled

                      if i>50 then newM(i-50,j)…

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

                    ExpandedWrap disabled

                      Sub Massiv()

                      Dim g As Integer

                      Randomize Timer

                      g = 1

                      For i = 1 To 100

                          For j = 1 To 10

                              oldM(i, j) = (Rnd + 0.6) * 2

                              If (i > 50 And i < 60) Or (i > 80 And i < 90) Then newM(g, j) = oldM(i, j)

                          Next j

                          If (i > 50 And i < 60) Or (i > 80 And i < 90) Then g = g + 1

                      Next i

                      Worksheets(1).Range(Cells(1, 1), Cells(g, 10)).Value = newM

                      End Sub

                    ввел переменную g чтобы вывести только те значения которые меня интересуют. Но все равно такое ощущение, что можно по другому, слишком нагромоздил.. Тем более что выходной массив при этом не уменьшается, а значит смысл теряется:(

                    Monster

                    Akina



                    Сообщ.
                    #10

                    ,
                    10.04.09, 04:35

                      ReDim Preserve

                      И вообще неплохо бы побольше читать.


                      GDK



                      Сообщ.
                      #11

                      ,
                      10.04.09, 13:12

                        Осторожнее с ReDim Preserve! Используйте только для одномерных массивов! Для многомерных массивов данные, хранящиеся в «2-м, 3-м, …» измерениях «обнуляются». Твоё безобразие — не безобразие.
                        Если не требуется высокое быстродействие могу посоветовать вместо массива использовать коллекции или ещё лучше объекты vbscript.Dictionary (вроде бы правильно написал). Но коллекциями можешь пользоваться сразу, а вот для чтобы был «доступ» к диктионари надо подключить библиотеку microsoft scripting runtime c помощью Tools-references…. Короче с ними работать намного удобнее. Особенно с dictionary. Но при его использовании по сравнению с коллекциями могут быть проблемы, т.к. на некоторых компах системные администраторы запрещают подключать некоторые библиотеки.

                        Сообщение отредактировано: GDK — 10.04.09, 13:13

                        Monster

                        Akina



                        Сообщ.
                        #12

                        ,
                        10.04.09, 14:00

                          Цитата GDK @ 10.04.09, 13:12

                          Для многомерных массивов данные, хранящиеся в «2-м, 3-м, …» измерениях «обнуляются».

                          Что??? никогда не было такого!


                          Kugeod



                          Сообщ.
                          #13

                          ,
                          10.04.09, 21:24

                            Да вот ReDim Preserve мне не помог никак:( Потому как Akina посоветовал мне почитать книгу и я прочел что можно изменять только последнее измерение многомерного массива. А меня то как раз интересует изменение первого измерения, так как мне оно не известно пока не закончится цикл, в этом же цикле вы предлагаете копировать массив в массив. За циклом его не скопировать а в цикле не переопределить первое измерение массива :(:(

                            Monster

                            Akina



                            Сообщ.
                            #14

                            ,
                            11.04.09, 05:20

                              Цитата Kugeod @ 10.04.09, 21:24

                              А меня то как раз интересует изменение первого измерения, так как мне оно не известно пока не закончится цикл

                              Поменяйте местами индексы :D


                              Kugeod



                              Сообщ.
                              #15

                              ,
                              13.04.09, 07:32

                                Поменяю индексы и что получится? Если имеете ввиду поменять местами циклы то это не возможно ввиду условий:( Написал бы ктонить что НИКАК я б и голову не ломал

                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)

                                0 пользователей:

                                • Предыдущая тема
                                • VB for Application
                                • Следующая тема

                                [ Script execution time: 0,0500 ]   [ 16 queries used ]   [ Generated: 16.04.23, 06:50 GMT ]  

                                How to overcome the restrictions of ReDim Preserve in multidimensional arrays

                                As mentioned by @ScottCraner, a ReDim Preserve can change only the last dimension of a given (datafield) array.
                                Therefore trying to resize a 2-dimensional array’s first dimension (=»rows») will fail.

                                However you can overcome this inconvenience applying the relatively unknown filtering capability of Application.Index() (c.f. section [2]) and profit from the additional bonus of less loops.

                                Further reading: see Some pecularities of the Application.Index() function

                                Sub GetRowsEqual10000()
                                    With Sheet1
                                        Dim lastRow As Long:  lastRow = .Range("A" & .Rows.Count).End(xlUp).Row
                                        Dim rng     As Range: Set rng = .Range("A2:F" & lastRow)
                                    End With
                                
                                    '[1] get data
                                    Dim data: data = rng
                                
                                    '[2] rearrange data via Application.Index() instead ReDim Preserve plus loops
                                    data = Application.Index(data, ValidRows(data, Condition:=10000), Array(1, 2, 3, 4, 5, 6))
                                End Sub
                                

                                Help function ValidRows()

                                Function ValidRows(arr, Condition) As Variant
                                'Purpose: a) check condition (e.g. values equalling 10000) and b) get valid row numbers c) in a 2-dim vertical array
                                ReDim tmp(1 To UBound(arr))     ' provide for 1-based 2-dim array
                                Dim i As Long, ii As Long
                                For i = 1 To UBound(arr)                ' loop through 1st "column"
                                    If arr(i, 1) = Condition Then       '   a) check condition 
                                        ii = ii + 1: tmp(ii) = i        '   b) collect valid row numbers
                                    End If
                                Next i
                                ReDim Preserve tmp(1 To ii)             '   resize tmp array (here the 1st dimension is also the last one:) 
                                ValidRows = Application.Transpose(tmp)  ' c) return transposed result as 2-dim array
                                End Function
                                

                                Edit due to comment (2020-04-22)

                                Short hints to the most frequent use of Application.Index():

                                Frequently the Application.Index() function is used to
                                get an entire row or column array out of a 2-dim array without need to loop.
                                Accessing your 1-based 2-dimensional datafield array like that requires to
                                indicate a single row or column number and
                                to set the neighbour argument column or row number to 0 (zero), respectively which might result in e.g.

                                        Dim horizontal, vertical, RowNumber As Long, ColumnNumber As Long
                                    RowNumber = 17: ColumnNumber = 4
                                    horizontal = Application.Index(data, RowNumber, 0)
                                    vertical   = Application.Index(data, 0, ColumnNumber)
                                

                                (Addressing a single array element will be done directly, however via data(i,j)
                                instead of a theoretical Application.Index(data, i, j))

                                How to use Application.Index() for restructuring/filtering purposes:

                                In order to profit from the advanced possibilities of Application.Index() you
                                need to pass not only the array name (e.g. data), but the row|column arguments as Arrays, e.g.

                                    data = Application.Index(data, Application.Transpose(Array(15,8,10)), Array(1, 2, 3, 4, 5, 6))
                                

                                Note that the rows parameter becomes a «vertical» 2-dim array by transposition, where Array(15,8,10)
                                would even change the existing row order
                                (in the example code above this is done in the last code line within the ValidRows() function).
                                The columns argument Array(1,2,3,4,5,6) on the other hand remains «flat» or «horizontal» and
                                allows to get all existing column values as they are.

                                So you eventually you are receiving any data elements within the given element indices
                                (think them as coordinates in a graphic).

                                Понравилась статья? Поделить с друзьями:

                                А вот еще интересные статьи:

                              • Копирование защищенных файлов excel
                              • Копирование листов с графиками в excel
                              • Копирование заполненных ячеек в excel
                              • Копирование листов в excel в одну книгу
                              • Копирование закрепленной ячейки в excel

                              • 0 0 голоса
                                Рейтинг статьи
                                Подписаться
                                Уведомить о
                                guest

                                0 комментариев
                                Старые
                                Новые Популярные
                                Межтекстовые Отзывы
                                Посмотреть все комментарии