Looping with infinite data set

北城以北 提交于 2021-01-28 07:45:24

问题


I am trying to create a VBA but I keep getting stuck, if anyone can help that would be appreciated. So based on the picture I would like for each animal to be copied to each Set/# (and for the outcome to be on Sheet 2). The issue is that it won't always be a set of 14 it can vary based on the data but the Animals would stay the same (no more then 4). Below is what i currently have ganted it is not based on the picture. that's is just an example.

Example of Goal for VBA

updated VBA Example

Sub DowithIf()

rw = 5
cl = 2
rw = 1000

Do While rw < erw
If Cells(rw, cl) <> Cells(rw - 1, cl) Then
Cells(rw, cl + 1) = Cells(rw, cl)

Range("A5:B5").Select
Selection.Copy
Sheets("Sheet2").Select
Range("A2").Select
ActiveSheet.Paste
Range("A2:B4").Select
Application.CutCopyMode = False
Selection.FillDown
Sheets("Data").Select
Range("E3:J5").Select
Selection.Copy
Sheets("Sheet2").Select
Range("C2").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
    :=False, Transpose:=False
ElseIf Cells(rw, cl) = "" Then
    Exit Do
End If
   rw = rw + 1
Loop

End Sub

回答1:


I think you'd find this easier if you looked at VBA as more of a programming language than a macro recorder. In your example, the task is really just to create an array whose row count is:

number of set names * number of set items

All you'd need to do is populate that array following a certain pattern. In your example it would be:

set number n with all set items, set number n + 1 with all set items, etc.

Skeleton code would look something like this:

Const SET_NAMES_ROW_START As Long = 6
Const SET_ITEMS_ROW_START As Long = 6
Const SET_NAMES_COL As String = "A"
Const SET_ITEMS_COL As String = "E"
Const OUTPUT_ROW_START As Long = 6
Const OUTPUT_COL As String = "G"

Dim names() As Variant, items() As Variant, output() As Variant
Dim namesCount As Long, itemsCount As Long
Dim idx As Long, nameIdx As Long, itemIdx As Long

'Read the set values.
With Sheet1
    names = .Range( _
                .Cells(SET_NAMES_ROW_START, SET_NAMES_COL), _
                .Cells(.Rows.Count, SET_NAMES_COL).End(xlUp)) _
               .Resize(, 2).Value2
    items = .Range( _
                .Cells(SET_ITEMS_ROW_START, SET_ITEMS_COL), _
                .Cells(.Rows.Count, SET_ITEMS_COL).End(xlUp)) _
               .Value2
End With

'Dimension the output array.
namesCount = UBound(names, 1)
itemsCount = UBound(items, 1)

ReDim output(1 To namesCount * itemsCount, 1 To 3)

'Populate the output array.
nameIdx = 1
itemIdx = 1
For idx = 1 To namesCount * itemsCount
    output(idx, 1) = names(nameIdx, 1)
    output(idx, 2) = names(nameIdx, 2)
    output(idx, 3) = items(itemIdx, 1)
    itemIdx = itemIdx + 1
    If itemIdx > itemsCount Then
        'Increment the name index by 1.
        nameIdx = nameIdx + 1
        'Reset the item index to 1.
        itemIdx = 1
    End If
Next

'Write array to the output sheet.
Sheet1.Cells(OUTPUT_ROW_START, OUTPUT_COL).Resize(UBound(output, 1), UBound(output, 2)).Value = output



回答2:


So I think this will let you dynamically pick the size of your data set. I'm assuming that the column headers will always be at Row 5 as pictured. It loops through each input column and provides a unique output in H, I, and J. Disclaimer: I didn't get to test this as I'm not on my work PC.

Sub MixTheStuff()

'sets size of data in A (Set).  -5 for the header row as noted
x = ThisWorkbook.Sheets("Data").Cells(Rows.Count, 1).End(xlUp).Row - 5  
 
'sets size of data in B (#)
y = ThisWorkbook.Sheets("Data").Cells(Rows.Count, 2).End(xlUp).Row - 5

'sets size of data in E (Animal)
z = ThisWorkbook.Sheets("Data").Cells(Rows.Count, 5).End(xlUp).Row - 5   

i=6 'First row after the headers

For sThing = 1 to x    'set thing
For nThing = 1 to y    'number thing
For aThing = 1 to z    'animal thing

    'Pastes the value of the stuff (Set, #, and Animal respectively)
    ThisWorkbook.Sheets("Data").cell(i,10) = ThisWorkbook.Sheets("Data").cell(x,1).value
    ThisWorkbook.Sheets("Data").cell(i,11) = ThisWorkbook.Sheets("Data").cell(y,2).value
    ThisWorkbook.Sheets("Data").cell(i,12) = ThisWorkbook.Sheets("Data").cell(z,5).value

i = i + 1 'Go to the next output row

Next sThing
Next nThing
Next aThing

End Sub



回答3:


Sort of Unpivot

  • This will allow you to handle maximally 1023 animals.

The Code

Option Explicit

Sub SortOfUnpivot()
    
    Const FirstRow As Long = 6
    Const LastRowCol As String = "E"
    Const dstFirstCell As String = "H6"
    Dim srcCols As Variant
    srcCols = VBA.Array("A", "B", "E")
    
    Dim LB As Long
    LB = LBound(srcCols)
    Dim UB As Long
    UB = UBound(srcCols)
    Dim srcCount As Long
    srcCount = UB - LB + 1
    
    Dim LastRow As Long
    LastRow = Cells(Rows.Count, LastRowCol).End(xlUp).Row
    Dim rng As Range
    Set rng = Cells(FirstRow, LastRowCol).Resize(LastRow - FirstRow + 1)
    Dim Source As Variant
    ReDim Source(LB To UB)
    
    Dim j As Long
    For j = LB To UB
        Source(j) = rng.Offset(, Columns(srcCols(j)).Column - rng.Column).Value
    Next j
    
    Dim UBS As Long
    UBS = UBound(Source(UB))
    
    Dim Dest As Variant
    ReDim Dest(1 To UBS ^ 2, 1 To srcCount)
    Dim i As Long
    Dim k As Long
    
    For j = 1 To UBS
        k = k + 1
        For i = 1 + (j - 1) * UBS To UBS + (j - 1) * UBS
            Dest(i, 1) = Source(0)(k, 1)
            Dest(i, 2) = Source(1)(k, 1)
            Dest(i, 3) = Source(2)(i - (j - 1) * UBS, 1)
        Next i
    Next j
    
    Range(dstFirstCell).Resize(UBound(Dest), srcCount).Value = Dest
    
    
End Sub


来源:https://stackoverflow.com/questions/64760939/looping-with-infinite-data-set

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!