Скопируйте значения из ячеек в диапазоне и вставьте их в случайную ячейку в диапазоне - PullRequest
0 голосов
/ 09 мая 2020

У меня есть два диапазона, как показано на этом рисунке.

Image 1

Я пытаюсь написать макрос VBA, который последовательно выбирает одну ячейку в первом диапазоне («B23 , F27 »), копирует значение выбранной ячейки, затем выбирает случайную ячейку во втором диапазоне (« G23, K27 ») и вставляет значение первой ячейки в случайно выбранную ячейку во втором диапазоне.

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

Результат должен быть похож на второе изображение.

Image 2

Я попытался присвоить массиву первый диапазон, а затем выбрать случайное значение из этого массива и вставить его во второй диапазон. Я также попытался извлечь уникальные значения из первого диапазона, построить с ним словарь, затем выбрать случайную ячейку из второго диапазона и случайное значение из словаря и вставить его. Позже я снова попытался использовать синтаксис VBA «с диапазоном» и «f» или «каждая ячейка в диапазоне», но я не могу просто придумать что-то, что действительно работает. Иногда второй диапазон заполняется различными значениями, но не так, как задумано.

Первый пример: этот просто не работает

Sub fillrange()
Dim empty As Boolean

'This part checks if every cell in the first range as a value in it
For Each Cell In Range("B23", "F27")
If Cell.Value = "" Then
empty = True
End If
Next


'If every cell is filled then
If empty Then
Exit Sub
Else:

 With ThisWorkbook.Worksheets("Sheet1)").Range("B23", "F27")
        .Cells(Application.WorksheetFunction.RandBetween(1, 25)).Select
      .Copy 'the cell select works, but it will copy all range

'This does not work
'For Each Cell In Range("G23", "K27")
'Cells(Application.WorksheetFunction.RandBetween(1, 25)).Select
'.PasteSpecial Paste:=xlPasteValues
'Next

    End With
    End If
End Sub

Второй пример: он заполняет диапазон, но с неправильными значениями

Sub fillrange2()
Dim empty As Boolean
For Each cell In Range("B23", "F27")
If cell.Value = "" Then
empty = True
    'This part checks if every cell in the first range as a value in it
Exit For
End If
Next cell

If empty Then
Exit Sub
Else:

    Dim ws As Worksheet
    Dim lRow As Long, i As Long
    Dim col As New Collection, itm As Variant

    Set ws = ThisWorkbook.Sheets("Sheet1")

    With ws
        lRow = .Range("A" & .Rows.Count).End(xlUp).Row

        For i = 1 To lRow
            On Error Resume Next
            col.Add .Range("B23", "F27").Value, CStr(.Range("A" & i).Value)
            On Error GoTo 0
        Next i
        End With
    Dim MyAr() As Variant

    ReDim MyAr(0 To (col.Count - 1))

    For i = 1 To col.Count
        MyAr(i - 1) = col.Item(i)
    Next
For Each cell In Range("G23", "K27")
cell.Value = Application.WorksheetFunction.RandBetween(LBound(MyAr), UBound(MyAr))
    Next
End If
End Sub

Третий пример: как второй пример, он заполняет диапазон, но с неправильными значениями

Sub fillrange3()
Dim MyAr() As Variant
MyAr = Range("B23", "F27")
 For Each cell In Range("G23", "K27")
cell.Value = Application.WorksheetFunction.RandBetween(LBound(MyAr), UBound(MyAr))
Next
End Sub

Ответы [ 2 ]

1 голос
/ 09 мая 2020

Вот еще один подход, только для небольшого разнообразия.

Sub x()

Dim r1 As Range, r2 As Range, i As Long
Dim r As Long, c As Long

Set r1 = Range("B23").Resize(5, 5) 'define our two ranges
Set r2 = Range("G23").Resize(5, 5)
r2.ClearContents 'clear output range

With WorksheetFunction
    Do Until .Count(r2) = r2.Count 'loop until output range filled
        r = .RandBetween(1, 25) 'random output cell number
        If .CountIf(r2, r1.Cells(i)) = 0 Then 'if not in output range already
            If r2.Cells(r) = vbNullString Then 'if random cell empty
                r2.Cells(r).Value = r1.Cells(i).Value 'transfer value
                i = i + 1
            End If
        End If
    Loop
End With

End Sub
1 голос
/ 09 мая 2020

Может что-то вроде этого?

Sub test()
Set Rng = Range("G23:K27")
n = 1
totCell = 25
Set oFill = Range("G23")
Set oSource = Range("B23")

For i = 1 To 5
oFill.Value = "X" & n
oFill.AutoFill Destination:=Range(oFill, oFill.Offset(4, 0)), Type:=xlFillSeries
Set oFill = oFill.Offset(0, 1)
n = n + 5
Next i

For i = 1 To 5
Do
RndVal = Int((totCell - 1 + 1) * Rnd + 1)
xVal = "X" & RndVal
Set C = Rng.Find(xVal, lookat:=xlWhole)
If Not C Is Nothing Then
C.Value = oSource.Value
Set oSource = oSource.Offset(1, 0)
check = check + 1
If check = 5 Then Exit Do
End If
Loop
Set oSource = oSource.Offset(-5, 1)
check = 0
Next i
End Sub

Я обманываю, делая подготовку для диапазона от G23 до K27, заполняя его значениями от X1 до X25 в первом for i = 1 to 5.

во втором for i = 1 to 5 - это смещение от столбца B к G.

Do - Loop - для генерации случайного числа от 1 до 25.
Если сгенерированное число найдено, то найденная ячейка имеет значение от " источник ",
если не найден, будет l oop, пока сгенерированное число не будет найдено 5 раз (следовательно, найденная ячейка также будет заполнена 5 разными источниками). Затем перед следующим i "исходная" ячейка смещается в следующий столбец.

Это, если я не ошибаюсь, чтобы понять, что вы имеете в виду.

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...