#arrays #excel #vba
#массивы #excel #vba
Вопрос:
Я пытаюсь присвоить значения 1-мерного массива диапазону ячеек.
Например; мой массив содержит 23 элемента (каждый элемент рандомизирован от 1 до 5), а диапазон моих ячеек — от A1 до I7.
Я хочу случайным образом присвоить каждое значение моего массива этому диапазону ячеек.
Я рандомизирую значения ячеек в своем массиве, но значения моего массива не полностью присваиваются ячейкам.
Sub define_ore_body()
Dim lb_grade As Integer, ub_grade As Integer
Dim ore_body(1 To 23) As Variant
Dim i As Integer, j As Integer, k As Integer
Dim a As Object
Dim b As Range
Application.ScreenUpdating = False
'my selected range area A1toI7
Set b = Application.Range("A1:I7")
Set a = Application.Cells
'******* low and high ore bound ******
lb_grade = InputBox("Enter lowest ore grade:")
ub_grade = InputBox("Enter highest ore grade:")
'The reason why I do it as follows is that if the random lower bound does not start from 1,
'the largest random number it generates is 2 more than the value I have entered, so
If lb_grade > 1 Then
ub_grade = ub_grade - 2
End If
'******* Random Array ******
'array has 23 items
For i = 1 To 23
ore_body(i) = Int((ub_grade * Rnd) lb_grade)
Next i
'******* filling random cells with my array******
k = 1
For Each a In b
If a.Value = "" And k < 23 Then
b(Int(7 * Rnd 1), (8 * Rnd 1)) = ore_body(k)
ElseIf a.Count > 23 And k > 23 Then
Exit For
Else
k = k 1
End If
Next a
'******* after filling cell now fill empty cells with Zero******
For i = 1 To 7
For j = 1 To 9
If Cells(i, j) = "" Then
Cells(i, j) = 0
Else
End If
Next j
Next i
'******* Coloring only containing array values******
For i = 1 To 7
For j = 1 To 9
If Cells(i, j) > 0 Then
Application.Cells(i, j).Interior.ColorIndex = 38
Else
End If
Next j
Next i
End Sub
Комментарии:
1. Я не уверен, что понимаю. В A1: A17 есть 63 ячейки, поэтому, если у вас есть только 23 значения, то будут заполнены только 23 ячейки в этом диапазоне.
2. Привет @norie, да, я хочу случайным образом заполнить эти 23 значения в 63 ячейки, а остальные 40 ячеек будут заполнены нулем.
3. Тогда вам нужно еще 40 элементов в вашем массиве, содержащих нули; если вы объявите массив
(1 To 63) As Long
, то все его элементы будут инициализироваться0
. Будучи aVariant
, ваш текущий массив инициализируется сVariant/Empty
помощью , что эквивалентно0
в вычислениях и неявно преобразуется0
во многих ситуациях — ноVariant/Empty
это то, что вы получаете из полностью пустой ячейки, и это то, что будет помещено в ячейки, если вы просто измените размер массива.4. @MathieuGuindon да, и в коде я могу заполнить остальные ячейки нулем, но я не могу заполнить все элементы моего массива. Каждый раз он заполняет только от 18 до 21 (или аналогичных) элементов массива.
Ответ №1:
Массив содержит 23 элемента, которые инициализируются Variant/Empty
:
Dim ore_body(1 To 23) As Variant
Сделайте так, чтобы 63 элемента, которые инициализируются 0
:
Dim ore_body(1 To 63) As Long
Теперь остальная часть кода будет заполнять первые 23 элемента, потому что это то, что делает цикл:
For i = 1 To 23
Если вы хотите, чтобы цикл выполнялся по всем индексам, рассмотрите возможность использования LBound
UBound
операторов и для программного извлечения нижней и верхней границ массива соответственно:
For i = LBound(ore_body) To UBound(ore_body)
Обратите внимание, что вы 23
жестко запрограммировали в нескольких местах, что усложнит изменение, если / когда это 23 должно быть 25. Рассмотрите возможность замены каждого его вхождения на Const
:
Const ElementCount As Long = 23
Тогда каждый экземпляр 23
может стать ElementCount
, а затем, когда он должен стать 25, тогда есть только одно место, для изменения которого требуется какой-либо код.
Ответ №2:
- Цикл по массиву.
- Установите a в случайную ячейку в диапазоне A1: I7.
- Если ячейка пуста, поместите значение из массива в ячейку, если это не так, повторите шаг 2
Sub define_ore_body()
Dim lb_grade As Integer, ub_grade As Integer
Dim ore_body(1 To 23) As Variant
Dim i As Long, j As Long, k As Long
Dim a As Range
Dim b As Range
Application.ScreenUpdating = False
'my selected range area A1:I7
Set b = Application.Range("A1:I7")
' clear A1:A17
b.Clear
'******* low and high ore bound ******
lb_grade = InputBox("Enter lowest ore grade:")
ub_grade = InputBox("Enter highest ore grade:")
'The reason why I do it as follows is that if the random lower bound does not start from 1,
'the largest random number it generates is 2 more than the value I have entered, so
If lb_grade > 1 Then
ub_grade = ub_grade - 2
End If
'******* Random Array ******
'array has 23 items
For i = 1 To 23
ore_body(i) = Int((ub_grade * Rnd) lb_grade)
Next i
'******* filling random cells with my array******
For k = 1 To 23
Do
Set a = b.Cells(Int(7 * Rnd) 1, Int(9 * Rnd) 1)
Loop Until a.Value = ""
a.Value = ore_body(k)
Next k
'******* after filling cell now fill empty cells with Zero******
For i = 1 To 7
For j = 1 To 9
If Cells(i, j) = "" Then
Cells(i, j) = 0
Else
End If
Next j
Next i
'******* Coloring only containing array values******
For i = 1 To 7
For j = 1 To 9
If Cells(i, j) > 0 Then
Application.Cells(i, j).Interior.ColorIndex = 38
Else
End If
Next j
Next i
End Sub