Генератор комбинаций Excel

у меня есть код, который генерирует перестановку на основе входных данных 8 столбцов и объединяет столбцы вместе. пока работает отлично, но я столкнулся с проблемой. он работает, когда заполнено более 2 строк. поэтому, если в строке 10 есть только одна запись для любого из столбцов от A-H, происходит сбой. строки заполнены A, B, C во всех 8 столбцах, если в столбце 8 есть только A, тогда происходит сбой

я тоже пробовал

Set col1 = Range(Range("A10"), Range("A" & Rows.Count).End(xlUp))

вместо

Set col1 = Range("A10", Range("A10").End(xlDown)) 

но затем возникает ошибка несоответствия типов.

Любая помощь будет здорово. Это весь код:

Sub combinations()

Dim out() As Variant
Dim f, g, h, i, j, k, l, m As Long

Dim col1 As Range
Dim col2 As Range
Dim col3 As Range
Dim col4 As Range
Dim col5 As Range
Dim col6 As Range
Dim col7 As Range
Dim col8 As Range
Dim out1 As Range

'Set col1 = Range("A10", Range("A10").End(xlDown))
Set col1 = Range(Range("A10"), Range("A" & Rows.Count).End(xlUp))
Set col2 = Range("B10", Range("B10").End(xlDown))
Set col3 = Range("C10", Range("C10").End(xlDown))
Set col4 = Range("D10", Range("D10").End(xlDown))
Set col5 = Range("E10", Range("E10").End(xlDown))
Set col6 = Range("F10", Range("F10").End(xlDown))
Set col7 = Range("G10", Range("G10").End(xlDown))
Set col8 = Range("H10", Range("H10").End(xlDown))

c1 = col1
c2 = col2
c3 = col3
c4 = col4
c5 = col5
c6 = col6
c7 = col7
c8 = col8

'initializes each column from column1-column8 as Range, sets the size of the range from row10 to last row

Set out1 = Range("M1", Range("T1").Offset(UBound(c1) * UBound(c2) * UBound(c3) * UBound(c4) * UBound(c5) * UBound(c6) * UBound(c7) * UBound(c8)))
out = out1

'creates a range for the output

f = 1
g = 1
h = 1
i = 1
j = 1
k = 1
l = 1
m = 1
n = 1

Do While f <= UBound(c1)

    Do While g <= UBound(c2)
        Do While h <= UBound(c3)
            Do While i <= UBound(c4)

    Do While j <= UBound(c5)
        Do While k <= UBound(c6)
            Do While l <= UBound(c7)
             Do While m <= UBound(c8)
            out(n, 1) = c1(f, 1)
            out(n, 2) = c2(g, 1)
            out(n, 3) = c3(h, 1)
            out(n, 4) = c4(i, 1)
            out(n, 5) = c1(j, 1)
            out(n, 6) = c2(k, 1)
            out(n, 7) = c3(l, 1)
            out(n, 8) = c4(m, 1)
            'goes down one column and grabs each cells value

            n = n + 1
            m = m + 1
        Loop
        m = 1
        l = l + 1
    Loop
    l = 1
    k = k + 1
Loop
k = 1
j = j + 1
 Loop
        j = 1
        i = i + 1
    Loop
    i = 1
    h = h + 1
Loop
h = 1
g = g + 1
Loop
g = 1
f = f + 1
Loop

'repeats process for all 8 columns

out1.Value = out

'places values in the output range "out1"


Dim LastRow As Long
  LastRow = Cells(Rows.Count, "M").End(xlUp).Row

  'Range("Z1:Z" & LastRow).Formula = "=M1 & "" | "" & N1 & "" | "" & O1 & "" | "" & P1 & "" | "" & Q1 & "" | "" & R1 & "" | "" & S1 & "" | "" & T1 "


  Range("Z1:Z" & LastRow).Formula = "=M1 & $F$3 & N1 & $F$3 & O1 & $F$3 & P1 & $F$3 & Q1 & $F$3 & R1 & $F$3 & S1 & $F$3 & T1 "


     'concatentates the cells from column M-T, seperated by the delimiter in cell F3


    Range("Z1").Select
    Range(Selection, Selection.End(xlDown)).Select
    Selection.Copy
    Range("A1").Select
    Sheets("Sheet2").Select
    Columns("F").ColumnWidth = 120
    Range("F2").Select
    Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
        :=False, Transpose:=False
    Range("A1").Select

    'Copies the concatenated output, pastes in sheet2 as values

End Sub

person nkodb37    schedule 23.02.2015    source источник
comment
Что вы имеете в виду под крахом? Если выдает ошибку, что это за сообщение об ошибке и в какой строке оно возникает. Одна проблема, которую я вижу в вашем сценарии, заключается в том, что если вы приравниваете вариантную переменную к диапазону из одной ячейки, результирующая переменная НЕ будет массивом. Поэтому, когда вы рассматриваете его как массив, вы получите ошибку. Вы должны проверить это в своем коде.   -  person Ron Rosenfeld    schedule 23.02.2015
comment
Set out1 = Range(M1, Range(T1).Offset(UBound(c1) * UBound(c2) * UBound(c3) * UBound(c4) * UBound(c5) * UBound(c6) * UBound(c7) * UBound (c8))) Эта строка приводит к ошибке переполнения, когда в любом из 8 столбцов заполнена только одна строка.   -  person nkodb37    schedule 23.02.2015
comment
Тогда у вас есть несколько проблем. Если вы посмотрите на размер переменных вариантов, где у вас есть только одна запись, и вы выбираете диапазон с помощью xldown, вы получите огромный массив. Проверьте окно местных жителей, и вы поймете, что я имею в виду   -  person Ron Rosenfeld    schedule 23.02.2015


Ответы (1)


У вас несколько проблем:

Set col1 = Range("A10", Range("A10").End(xlDown))
c1 = col1

Если в col1 заполнена только строка 10, эта последовательность приводит к тому, что c1 представляет собой вариантный массив с размерами (от 1 до 1048567, от 1 до 1).

Лучше бы:

Set col1 = Range("A10", Cells(Rows.Count, "A").End(xlUp))

но с этим и только с одной ячейкой, заполненной в столбце, c1 больше не будет массивом.

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

    Dim c1, c2, c3, c4, c5, c6, c7, c8

Dim col1 As Range
Dim col2 As Range
Dim col3 As Range
Dim col4 As Range
Dim col5 As Range
Dim col6 As Range
Dim col7 As Range
Dim col8 As Range
Dim out1 As Range

'Set col1 = Range("A10", Range("A10").End(xlDown))
Set col1 = Range("A10", Cells(Rows.Count, "A").End(xlUp))
Set col2 = Range("B10", Cells(Rows.Count, "b").End(xlUp))
Set col3 = Range("C10", Cells(Rows.Count, "c").End(xlUp))
Set col4 = Range("D10", Cells(Rows.Count, "d").End(xlUp))
Set col5 = Range("E10", Cells(Rows.Count, "e").End(xlUp))
Set col6 = Range("F10", Cells(Rows.Count, "f").End(xlUp))
Set col7 = Range("G10", Cells(Rows.Count, "g").End(xlUp))
Set col8 = Range("H10", Cells(Rows.Count, "h").End(xlUp))



c1 = col1
    If Not IsArray(c1) Then
        ReDim c1(1, 1)
        c1(1, 1) = col1.Value
    End If
c2 = col2
    If Not IsArray(c2) Then
        ReDim c2(1, 1)
        c2(1, 1) = col1.Value
    End If
c3 = col3
    If Not IsArray(c3) Then
        ReDim c3(1, 1)
        c3(1, 1) = col1.Value
    End If
c4 = col4
    If Not IsArray(c4) Then
        ReDim c4(1, 1)
        c4(1, 1) = col1.Value
    End If
c5 = col5
    If Not IsArray(c5) Then
        ReDim c5(1, 1)
        c5(1, 1) = col1.Value
    End If
c6 = col6
    If Not IsArray(c6) Then
        ReDim c6(1, 1)
        c6(1, 1) = col1.Value
    End If
c7 = col7
    If Not IsArray(c7) Then
        ReDim c7(1, 1)
        c7(1, 1) = col1.Value
    End If
c8 = col8
    If Not IsArray(c8) Then
        ReDim c8(1, 1)
        c8(1, 1) = col1.Value
    End If    

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

person Ron Rosenfeld    schedule 23.02.2015
comment
Большое спасибо за разъяснение проблем, я применил решение ко всем столбцам, а также объявил c1 - c8 (вы правы, это уже нужно было сделать). однако он по-прежнему показывает ошибку переполнения, когда заполнена только одна строка - person nkodb37; 23.02.2015
comment
@ nkodb37 Проверьте размеры всех ваших переменных c1 ... c8, когда вы получите эту ошибку. - person Ron Rosenfeld; 23.02.2015
comment
@ nkodb37 Когда я применяю решение ко всем столбцам, я не получаю ошибку переполнения, если заполнена только одна строка, только в одном или нескольких столбцах. - person Ron Rosenfeld; 23.02.2015
comment
я объявил c1 - c8 как варианты и скопировал/вставил If Not IsArray(c1) Then vTemp = c1 ReDim c1(1 To 1, 1 To 1) c1(1, 1) = vTemp End If для всех столбцов. - person nkodb37; 23.02.2015
comment
Проверьте размеры всех ваших переменных c1...c8, когда вы получите эту ошибку Посмотрите в окно Locals. Как я уже сказал, я не могу воспроизвести эту проблему. - person Ron Rosenfeld; 23.02.2015
comment
Должно быть что-то еще в строках, которые имеют только одну запись. В противном случае вы должны увидеть c1 (от 1 до 1, от 1 до 1). Может, космос? - person Ron Rosenfeld; 23.02.2015
comment
Вы можете опубликовать свой ответ и скопировать / вставить его в новый документ Excel? - person nkodb37; 23.02.2015
comment
Я могу опубликовать соответствующий код, но поскольку ни один из ваших c1...c8 не отображается как (1 к 1, 1 к 1), я подозреваю, что в ваших данных есть что-то неожиданное. - person Ron Rosenfeld; 23.02.2015
comment
@ nkodb37 Я отредактировал свой ответ, чтобы отразить соответствующие изменения, которые я предлагаю. - person Ron Rosenfeld; 23.02.2015
comment
Спасибо, это отлично работает, только проблема теперь в том, что если столбец 1 заполнен более чем одной строкой, а остальные 7 столбцов заполнены только 1 строкой, он будет генерировать значения только для столбца 1. вы получаете те же результаты? - person nkodb37; 23.02.2015
comment
Да, я вижу ту же проблему. И, наоборот, я увижу subscript out of range в этой строке: out(n, 5) = c1(j, 1) Изучив этот раздел кода, он, похоже, создает проблемы в различных обстоятельствах, когда столбцы не имеют одинакового заполнения. Это логическая проблема, которую я оставлю вам для решения. - person Ron Rosenfeld; 23.02.2015