VBA copy set amount of rows into forms until end of data set

willow1985

Well-known Member
Joined
Jul 24, 2019
Messages
888
Office Version
  1. 365
Platform
  1. Windows
I need help with writing a macro that can copy a set amount of rows (say 15 rows) from a table of data and paste the data into another sheet (forms) at set locations one after another until there is no more data to copy in the table.

I do not know what the max amount of rows/data that will be in the table or how many forms will be required, but I do know the form will repeat every 17 rows. See below example.

I hope someone can help me with this. Loop codes are not my strong suit.
Thank you!

Book1
ABCDEFG
1OrderDateRegionRepItemUnitsUnit CostTotal
26-Jan-21EastJonesPencil951.99189.05
323-Jan-21CentralKivellBinder5019.99999.5
49-Feb-21CentralJardinePencil364.99179.64
526-Feb-21CentralGillPen2719.99539.73
615-Mar-21WestSorvinoPencil562.99167.44
71-Apr-21EastJonesBinder604.99299.4
818-Apr-21CentralAndrewsPencil751.99149.25
95-May-21CentralJardinePencil904.99449.1
1022-May-21WestThompsonPencil321.9963.68
118-Jun-21EastJonesBinder608.99539.4
1225-Jun-21CentralMorganPencil904.99449.1
1312-Jul-21EastHowardBinder291.9957.71
1429-Jul-21EastParentBinder8119.991619.19
1515-Aug-21EastJonesPencil354.99174.65
161-Sep-21CentralSmithDesk2125250
1718-Sep-21EastJonesPen Set1615.99255.84
185-Oct-21CentralMorganBinder288.99251.72
1922-Oct-21EastJonesPen648.99575.36
208-Nov-21EastParentPen1519.99299.85
2125-Nov-21CentralKivellPen Set964.99479.04
2212-Dec-21CentralSmithPencil671.2986.43
2329-Dec-21EastParentPen Set7415.991183.26
2415-Jan-22CentralGillBinder468.99413.54
251-Feb-22CentralSmithBinder87151305
2618-Feb-22EastJonesBinder44.9919.96
277-Mar-22WestSorvinoBinder719.99139.93
2824-Mar-22CentralJardinePen Set504.99249.5
2910-Apr-22CentralAndrewsPencil661.99131.34
3027-Apr-22EastHowardPen964.99479.04
3114-May-22CentralGillPencil531.2968.37
3231-May-22CentralGillBinder808.99719.2
3317-Jun-22CentralKivellDesk5125625
344-Jul-22EastJonesPen Set624.99309.38
3521-Jul-22CentralMorganPen Set5512.49686.95
367-Aug-22CentralKivellPen Set4223.951005.9
3724-Aug-22WestSorvinoDesk3275825
3810-Sep-22CentralGillPencil71.299.03
3927-Sep-22WestSorvinoPen761.99151.24
4014-Oct-22WestThompsonBinder5719.991139.43
4131-Oct-22CentralAndrewsPencil141.2918.06
4217-Nov-22CentralJardineBinder114.9954.89
434-Dec-22CentralJardineBinder9419.991879.06
4421-Dec-22CentralAndrewsBinder284.99139.72
Data


Book1
ABCDEFG
1CENTRAL FORM
2OrderDateRegionRepItemUnitsUnit CostTotal
323-Jan-21CentralKivellBinder5019.99999.5
49-Feb-21CentralJardinePencil364.99179.64
526-Feb-21CentralGillPen2719.99539.73
618-Apr-21CentralAndrewsPencil751.99149.25
75-May-21CentralJardinePencil904.99449.1
825-Jun-21CentralMorganPencil904.99449.1
91-Sep-21CentralSmithDesk2125250
105-Oct-21CentralMorganBinder288.99251.72
1125-Nov-21CentralKivellPen Set964.99479.04
1212-Dec-21CentralSmithPencil671.2986.43
1315-Jan-22CentralGillBinder468.99413.54
141-Feb-22CentralSmithBinder87151305
1524-Mar-22CentralJardinePen Set504.99249.5
1610-Apr-22CentralAndrewsPencil661.99131.34
1714-May-22CentralGillPencil531.2968.37
18Company Name
19CENTRAL FORM
20OrderDateRegionRepItemUnitsUnit CostTotal
2131-May-22CentralGillBinder808.99719.2
2217-Jun-22CentralKivellDesk5125625
2321-Jul-22CentralMorganPen Set5512.49686.95
247-Aug-22CentralKivellPen Set4223.951005.9
2510-Sep-22CentralGillPencil71.299.03
2631-Oct-22CentralAndrewsPencil141.2918.06
2717-Nov-22CentralJardineBinder114.9954.89
284-Dec-22CentralJardineBinder9419.991879.06
2921-Dec-22CentralAndrewsBinder284.99139.72
30
31
32
33
34
35
36Company Name
37CENTRAL FORM
38OrderDateRegionRepItemUnitsUnit CostTotal
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54Company Name
55CENTRAL FORM
56OrderDateRegionRepItemUnitsUnit CostTotal
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72Company Name
Central Form


VBA Code:
Sub Macro3()
'
' Macro3 Macro
'

'
    ActiveSheet.ListObjects("Order_Data").Range.AutoFilter Field:=2, Criteria1:= _
        "Central"
    Range("A3:G31").Select
    Selection.SpecialCells(xlCellTypeVisible).Select
    Selection.Copy
    Sheets("Central Form").Select
    Range("A3").Select
    Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
        :=False, Transpose:=False
    Sheets("Data").Select
    Range("A32:G44").Select
    Selection.SpecialCells(xlCellTypeVisible).Select
    Application.CutCopyMode = False
    Selection.Copy
    Sheets("Central Form").Select
    Range("A21").Select
    Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
        :=False, Transpose:=False
End Sub
 
Your filtering had to something to do with the 7 chunks only. The chunk is defined by the variable chunkSize in the code. Try this on a copy.
VBA Code:
Sub PasteToCentralForm3()
    Dim tableRange As Range, destSheet As Worksheet
    Dim tableArray() As Variant, Result() As Variant
    Dim numRows As Long, numCols As Long
    Dim i As Long, j As Long, loopCount As Long
    Dim chunkSize As Long
   
    Set tableRange = ThisWorkbook.Sheets("Data").ListObjects("Table1").DataBodyRange 'Change table name as needed
    Set destSheet = ThisWorkbook.Sheets("Central Form")
    chunkSize = 15 'adjust chunk size as needed.
   
    numRows = tableRange.Rows.Count
    numCols = tableRange.Columns.Count

    p = 1
    ' Read data into array
    tableArray = tableRange.Value
    ReDim Result(1 To numRows, 1 To numCols)
    For m = 1 To numRows
        If tableArray(m, 2) = "Central" Then
            For n = 1 To numCols
                Result(p, n) = tableArray(m, n)
            Next n
             p = p + 1
        End If
    Next m
   
    Application.ScreenUpdating = False
    loopCount = WorksheetFunction.RoundUp(UBound(Result, 1) / chunkSize, 0)
   
    ' Collect all data into one large array
    Dim outputData() As Variant
    ReDim outputData(1 To loopCount * (chunkSize + 2) - 2, 1 To numCols)
   
    Dim outputIndex As Long
    outputIndex = 1
   
    For i = 1 To loopCount
        Dim outputRowCount As Long
        outputRowCount = WorksheetFunction.Min(chunkSize, numRows - (i - 1) * chunkSize)
        For j = 1 To outputRowCount
            For k = 1 To numCols
                outputData(outputIndex, k) = Result((i - 1) * chunkSize + j, k)
            Next k
            outputIndex = outputIndex + 1
        Next j
        outputIndex = outputIndex + 2 ' Skip two rows for each chunk
    Next i
   
    ' Output all data to destination sheet at once
    destSheet.Cells(3, 1).Resize(UBound(outputData, 1), UBound(outputData, 2)).Value = outputData
   
    Application.ScreenUpdating = True
End Sub

This code is very close! The only problem is it clears out the rows in the forms it is supposed to skip! I will show you a before and after screenshot of the results.
Is there a way to prevent it from clearing it?

Before:
1712580982098.png


After:

1712581065022.png
 
Upvote 0

Excel Facts

Round to nearest half hour?
Use =MROUND(A2,"0:30") to round to nearest half hour. Use =CEILING(A2,"0:30") to round to next half hour.
Your filtering had to something to do with the 7 chunks only. The chunk is defined by the variable chunkSize in the code. Try this on a copy.
VBA Code:
Sub PasteToCentralForm3()
    Dim tableRange As Range, destSheet As Worksheet
    Dim tableArray() As Variant, Result() As Variant
    Dim numRows As Long, numCols As Long
    Dim i As Long, j As Long, loopCount As Long
    Dim chunkSize As Long
   
    Set tableRange = ThisWorkbook.Sheets("Data").ListObjects("Table1").DataBodyRange 'Change table name as needed
    Set destSheet = ThisWorkbook.Sheets("Central Form")
    chunkSize = 15 'adjust chunk size as needed.
   
    numRows = tableRange.Rows.Count
    numCols = tableRange.Columns.Count

    p = 1
    ' Read data into array
    tableArray = tableRange.Value
    ReDim Result(1 To numRows, 1 To numCols)
    For m = 1 To numRows
        If tableArray(m, 2) = "Central" Then
            For n = 1 To numCols
                Result(p, n) = tableArray(m, n)
            Next n
             p = p + 1
        End If
    Next m
   
    Application.ScreenUpdating = False
    loopCount = WorksheetFunction.RoundUp(UBound(Result, 1) / chunkSize, 0)
   
    ' Collect all data into one large array
    Dim outputData() As Variant
    ReDim outputData(1 To loopCount * (chunkSize + 2) - 2, 1 To numCols)
   
    Dim outputIndex As Long
    outputIndex = 1
   
    For i = 1 To loopCount
        Dim outputRowCount As Long
        outputRowCount = WorksheetFunction.Min(chunkSize, numRows - (i - 1) * chunkSize)
        For j = 1 To outputRowCount
            For k = 1 To numCols
                outputData(outputIndex, k) = Result((i - 1) * chunkSize + j, k)
            Next k
            outputIndex = outputIndex + 1
        Next j
        outputIndex = outputIndex + 2 ' Skip two rows for each chunk
    Next i
   
    ' Output all data to destination sheet at once
    destSheet.Cells(3, 1).Resize(UBound(outputData, 1), UBound(outputData, 2)).Value = outputData
   
    Application.ScreenUpdating = True
End Sub

This code worked however when it skipped 2 rows it also cleared them (see before and after screenshots below)
Is there a way to not have them cleared?
Also is it possible to specify specific columns to copy only (Like A:C for example on this line: numCols = tableRange.Columns.Count)

Thank you so much for all of the help!

Before code:
1712583068849.png


After code (red circle data was cleared):
1712583124622.png
 
Upvote 0
Your filtering had to something to do with the 7 chunks only. The chunk is defined by the variable chunkSize in the code. Try this on a copy.
VBA Code:
Sub PasteToCentralForm3()
    Dim tableRange As Range, destSheet As Worksheet
    Dim tableArray() As Variant, Result() As Variant
    Dim numRows As Long, numCols As Long
    Dim i As Long, j As Long, loopCount As Long
    Dim chunkSize As Long
   
    Set tableRange = ThisWorkbook.Sheets("Data").ListObjects("Table1").DataBodyRange 'Change table name as needed
    Set destSheet = ThisWorkbook.Sheets("Central Form")
    chunkSize = 15 'adjust chunk size as needed.
   
    numRows = tableRange.Rows.Count
    numCols = tableRange.Columns.Count

    p = 1
    ' Read data into array
    tableArray = tableRange.Value
    ReDim Result(1 To numRows, 1 To numCols)
    For m = 1 To numRows
        If tableArray(m, 2) = "Central" Then
            For n = 1 To numCols
                Result(p, n) = tableArray(m, n)
            Next n
             p = p + 1
        End If
    Next m
   
    Application.ScreenUpdating = False
    loopCount = WorksheetFunction.RoundUp(UBound(Result, 1) / chunkSize, 0)
   
    ' Collect all data into one large array
    Dim outputData() As Variant
    ReDim outputData(1 To loopCount * (chunkSize + 2) - 2, 1 To numCols)
   
    Dim outputIndex As Long
    outputIndex = 1
   
    For i = 1 To loopCount
        Dim outputRowCount As Long
        outputRowCount = WorksheetFunction.Min(chunkSize, numRows - (i - 1) * chunkSize)
        For j = 1 To outputRowCount
            For k = 1 To numCols
                outputData(outputIndex, k) = Result((i - 1) * chunkSize + j, k)
            Next k
            outputIndex = outputIndex + 1
        Next j
        outputIndex = outputIndex + 2 ' Skip two rows for each chunk
    Next i
   
    ' Output all data to destination sheet at once
    destSheet.Cells(3, 1).Resize(UBound(outputData, 1), UBound(outputData, 2)).Value = outputData
   
    Application.ScreenUpdating = True
End Sub

Please also explain the part of the code I listed below. When I apply this code to another data set I get a Runtime Error 9: Script out of Range on line:
outputData(outputIndex, k) = Result((i - 1) * chunkSize + j, k)

I am trying desperately to understand this part so I can make adjustments. I changed the skip 3 rows to 13 and Output cell to destSheet.Cells (13,1) 'First column, 13th row??
Thank you

VBA Code:
' Collect all data into one large array
    Dim outputData() As Variant
    ReDim outputData(1 To loopCount * (chunkSize + 2) - 2, 1 To numCols)
    
    Dim outputIndex As Long
    outputIndex = 1
    
    For i = 1 To loopCount
        Dim outputRowCount As Long
        outputRowCount = WorksheetFunction.Min(chunkSize, numRows - (i - 1) * chunkSize)
        For j = 1 To outputRowCount
            For k = 1 To numCols
                outputData(outputIndex, k) = Result((i - 1) * chunkSize + j, k)
            Next k
            outputIndex = outputIndex + 1
        Next j
        outputIndex = outputIndex + 2 ' Skip two rows for each chunk
    Next i
    
    ' Output all data to destination sheet at once
    destSheet.Cells(3, 1).Resize(UBound(outputData, 1), UBound(outputData, 2)).Value = outputData
    
    Application.ScreenUpdating = True
End Sub
 
Upvote 0
The 2's here are the number of rows to skip. maybe make a variable.
VBA Code:
ReDim outputData(1 To loopCount * (chunkSize + 2) - 2, 1 To numCols)
Here as well
VBA Code:
outputIndex = outputIndex + 2 ' Skip two rows for each chunk

Edit: I haven't had time to look at your previous questions about the Headers get overriden.
 
Upvote 0
This seems to be working on my end. Adjusted for chunkSize = 13, rowSkip = 3 Try this.
VBA Code:
Sub PasteToCentralForm4()
    Dim tableRange As Range, destSheet As Worksheet
    Dim tableArray() As Variant, Result() As Variant
    Dim numRows As Long, numCols As Long
    Dim i As Long, j As Long, loopCount As Long
    Dim chunkSize As Long
    Set tableRange = ThisWorkbook.Sheets("Data").ListObjects("Table1").DataBodyRange 'Change table name as needed
    Set destSheet = ThisWorkbook.Sheets("Central Form")
    chunkSize = 13 'adjust chunk size as needed.
    numRows = tableRange.Rows.Count
    numCols = tableRange.Columns.Count
    p = 1
   
    ' Read data into array
    tableArray = tableRange.Value
    ReDim Result(1 To numRows, 1 To numCols)
    For m = 1 To numRows
        If tableArray(m, 2) = "Central" Then
            For n = 1 To numCols
                Result(p, n) = tableArray(m, n)
            Next n
            p = p + 1
        End If
    Next m
   
    Application.ScreenUpdating = False
    loopCount = WorksheetFunction.RoundUp(UBound(Result, 1) / chunkSize, 0)
    Dim outputIndex As Long
    Dim rowSkip As Long
    rowSkip = 3 'change # of rows to skip
    outputIndex = 1
   
    ' Output each chunk of data
    For i = 1 To loopCount
        Dim outputRowCount As Long
        outputRowCount = WorksheetFunction.Min(chunkSize, numRows - (i - 1) * chunkSize)
        Dim outputData() As Variant
        ReDim outputData(1 To outputRowCount, 1 To numCols)
        For j = 1 To outputRowCount
            For k = 1 To numCols
                outputData(j, k) = Result((i - 1) * chunkSize + j, k)
            Next k
        Next j
        ' Output the chunk to destination sheet
        destSheet.Cells(outputIndex + 2, 1).Resize(outputRowCount, numCols).Value = outputData
        outputIndex = outputIndex + outputRowCount + rowSkip ' Move to next chunk
    Next i
    Application.ScreenUpdating = True
End Sub
 
Upvote 0
Solution
This seems to be working on my end. Adjusted for chunkSize = 13, rowSkip = 3 Try this.
VBA Code:
Sub PasteToCentralForm4()
    Dim tableRange As Range, destSheet As Worksheet
    Dim tableArray() As Variant, Result() As Variant
    Dim numRows As Long, numCols As Long
    Dim i As Long, j As Long, loopCount As Long
    Dim chunkSize As Long
    Set tableRange = ThisWorkbook.Sheets("Data").ListObjects("Table1").DataBodyRange 'Change table name as needed
    Set destSheet = ThisWorkbook.Sheets("Central Form")
    chunkSize = 13 'adjust chunk size as needed.
    numRows = tableRange.Rows.Count
    numCols = tableRange.Columns.Count
    p = 1
  
    ' Read data into array
    tableArray = tableRange.Value
    ReDim Result(1 To numRows, 1 To numCols)
    For m = 1 To numRows
        If tableArray(m, 2) = "Central" Then
            For n = 1 To numCols
                Result(p, n) = tableArray(m, n)
            Next n
            p = p + 1
        End If
    Next m
  
    Application.ScreenUpdating = False
    loopCount = WorksheetFunction.RoundUp(UBound(Result, 1) / chunkSize, 0)
    Dim outputIndex As Long
    Dim rowSkip As Long
    rowSkip = 3 'change # of rows to skip
    outputIndex = 1
  
    ' Output each chunk of data
    For i = 1 To loopCount
        Dim outputRowCount As Long
        outputRowCount = WorksheetFunction.Min(chunkSize, numRows - (i - 1) * chunkSize)
        Dim outputData() As Variant
        ReDim outputData(1 To outputRowCount, 1 To numCols)
        For j = 1 To outputRowCount
            For k = 1 To numCols
                outputData(j, k) = Result((i - 1) * chunkSize + j, k)
            Next k
        Next j
        ' Output the chunk to destination sheet
        destSheet.Cells(outputIndex + 2, 1).Resize(outputRowCount, numCols).Value = outputData
        outputIndex = outputIndex + outputRowCount + rowSkip ' Move to next chunk
    Next i
    Application.ScreenUpdating = True
End Sub

5 out of 6 spreadsheets work with this code without clearing rows, so no idea why one of them is doing it. But code seems to be working perfectly!

Thank you very much for all of your help and explaining everything so thoroughly! 😄
 
Upvote 0

Forum statistics

Threads
1,215,219
Messages
6,123,691
Members
449,117
Latest member
Aaagu

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top