3

I want to duplicate each row in a worksheet 57 times per row, across 39 columns (after the result, meaning there would be 58 duplicates of each record).

So for example, I have included a snippet below of what some of my records look like now (take in mind, there are 39 columns, snippet cant snip the complete view):

Original Data

And here is the result I am looking foR (Note: this example is with 10 duplicates for each row rather than 58, as the screenshot would be too large). The original file has over 5000 records, so I know whatever code I use will take a while to load, this is fine by me, I just want the result)

Desired Result

Here is the code I have used below, this does not duplicate the rows as such but ensures that each row has a gap of 57 blank rows between each row across the 39 columns (A to AM). This would be a longer and more complicated way of completing the task, as I would then have to find a way to fill in the blanks. Hence why I'm posting the question as there must be a more efficient way.

Sub Duplication()

Dim lastRow As Long
lastRow = Sheets("MasterSheet").Range("A" & Rows.Count).End(xlUp).Row

For i = lastRow To 3 Step -1
    Cells(i, 1).Resize(57).Insert Shift:=xlDown
Next
For i = lastRow To 3 Step -1
    Cells(i, 2).Resize(57).Insert Shift:=xlDown
Next
For i = lastRow To 3 Step -1
    Cells(i, 3).Resize(57).Insert Shift:=xlDown
Next
For i = lastRow To 3 Step -1
    Cells(i, 4).Resize(57).Insert Shift:=xlDown
Next
For i = lastRow To 3 Step -1
    Cells(i, 5).Resize(57).Insert Shift:=xlDown
Next
For i = lastRow To 3 Step -1
    Cells(i, 6).Resize(57).Insert Shift:=xlDown
Next
For i = lastRow To 3 Step -1
    Cells(i, 7).Resize(57).Insert Shift:=xlDown
Next
For i = lastRow To 3 Step -1
    Cells(i, 8).Resize(57).Insert Shift:=xlDown
Next
For i = lastRow To 3 Step -1
    Cells(i, 9).Resize(57).Insert Shift:=xlDown
Next
For i = lastRow To 3 Step -1
    Cells(i, 10).Resize(57).Insert Shift:=xlDown
Next
For i = lastRow To 3 Step -1
    Cells(i, 11).Resize(57).Insert Shift:=xlDown
Next
For i = lastRow To 3 Step -1
    Cells(i, 12).Resize(57).Insert Shift:=xlDown
Next
For i = lastRow To 3 Step -1
    Cells(i, 13).Resize(57).Insert Shift:=xlDown
Next
For i = lastRow To 3 Step -1
    Cells(i, 14).Resize(57).Insert Shift:=xlDown
Next
For i = lastRow To 3 Step -1
    Cells(i, 15).Resize(57).Insert Shift:=xlDown
Next
For i = lastRow To 3 Step -1
    Cells(i, 16).Resize(57).Insert Shift:=xlDown
Next
For i = lastRow To 3 Step -1
    Cells(i, 17).Resize(57).Insert Shift:=xlDown
Next
For i = lastRow To 3 Step -1
    Cells(i, 18).Resize(57).Insert Shift:=xlDown
Next
For i = lastRow To 3 Step -1
    Cells(i, 19).Resize(57).Insert Shift:=xlDown
Next
For i = lastRow To 3 Step -1
    Cells(i, 20).Resize(57).Insert Shift:=xlDown
Next
For i = lastRow To 3 Step -1
    Cells(i, 21).Resize(57).Insert Shift:=xlDown
Next
For i = lastRow To 3 Step -1
    Cells(i, 22).Resize(57).Insert Shift:=xlDown
Next
For i = lastRow To 3 Step -1
    Cells(i, 23).Resize(57).Insert Shift:=xlDown
Next
For i = lastRow To 3 Step -1
    Cells(i, 24).Resize(57).Insert Shift:=xlDown
Next
For i = lastRow To 3 Step -1
    Cells(i, 25).Resize(57).Insert Shift:=xlDown
Next
For i = lastRow To 3 Step -1
    Cells(i, 26).Resize(57).Insert Shift:=xlDown
Next
For i = lastRow To 3 Step -1
    Cells(i, 27).Resize(57).Insert Shift:=xlDown
Next
For i = lastRow To 3 Step -1
    Cells(i, 28).Resize(57).Insert Shift:=xlDown
Next
For i = lastRow To 3 Step -1
    Cells(i, 29).Resize(57).Insert Shift:=xlDown
Next
For i = lastRow To 3 Step -1
    Cells(i, 30).Resize(57).Insert Shift:=xlDown
Next
For i = lastRow To 3 Step -1
    Cells(i, 31).Resize(57).Insert Shift:=xlDown
Next
For i = lastRow To 3 Step -1
    Cells(i, 32).Resize(57).Insert Shift:=xlDown
Next
For i = lastRow To 3 Step -1
    Cells(i, 33).Resize(57).Insert Shift:=xlDown
Next
For i = lastRow To 3 Step -1
    Cells(i, 34).Resize(57).Insert Shift:=xlDown
Next
For i = lastRow To 3 Step -1
    Cells(i, 35).Resize(57).Insert Shift:=xlDown
Next
For i = lastRow To 3 Step -1
    Cells(i, 36).Resize(57).Insert Shift:=xlDown
Next
For i = lastRow To 3 Step -1
    Cells(i, 37).Resize(57).Insert Shift:=xlDown
Next
For i = lastRow To 3 Step -1
    Cells(i, 38).Resize(57).Insert Shift:=xlDown
Next
For i = lastRow To 3 Step -1
    Cells(i, 39).Resize(57).Insert Shift:=xlDown
Next    

End Sub

Please let me know what you think, apologies if there is a much easier solution I am currently unaware of. I tried looking on forums and other questions, but none par the code I have displayed gave me a result in the desired direction.

Thank you

EuanM28
  • 258
  • 3
  • 14
  • You may wish to read up on the Excel Range.insert method – freeflow Feb 20 '23 at 11:23
  • @freeflow using the code `Range("3:3").Insert CopyOrigin:=xlFormatFromLeftOrAbove` and duplicating that 57 does create 57 blank rows, but it does not apply to all of the records, and it doesn't duplicate so this doesn't seem the correct method. – EuanM28 Feb 20 '23 at 11:49

4 Answers4

6

You could take all data into array and the paste values from there looping:

enter image description here

Sub test()
Dim i As Long, j As Long
Dim LastColumn As Long, LastRow As Long
Dim MyData As Variant
Dim HowManyCopies As Long, MyCounter As Long, CurrentRow As Long

Application.ScreenUpdating = False

'get last column, in your case 39, here is just 4
LastColumn = 4

'get last non blank row
LastRow = Range("A" & Rows.Count).End(xlUp).Row

'all data into array, headers included
MyData = Range("A1").CurrentRegion.Value

'clear range except headers
Range(Cells(2, 1), Cells(LastRow, LastColumn)).Clear

'Duplicate rows. Loop trough each row of array
'we start at row 2 because 1 is headers

HowManyCopies = 4 'as example, just 4 duplicates of each row
CurrentRow = 2 'where to start duplicating

For i = 2 To UBound(MyData) Step 1
    'loop trough counter until HowManyCopies is reached
    For MyCounter = 1 To HowManyCopies Step 1
        'loop trough each column and paste value
        For j = 1 To LastColumn Step 1
            Cells(CurrentRow, j).Value = MyData(i, j)
        Next j
        CurrentRow = CurrentRow + 1
    Next MyCounter
Next i

Erase MyData 'clean variable

Application.ScreenUpdating = True
End Sub

enter image description here

The example above just duplicate a dataset of 5 rows and 4 columns each row 4 times but it's easy to adapt to 5000 rows and 39 columns (it will take longer, tough).

UPDATE: After doing some research, I've been able to design a more efficient code and tested with with a dataset of 5000 rows and 39 columns it took just 55 seconds to complete. The code is longer but it is worthless.

All credits goes to these resources:

How do I slice an array in Excel VBA?

CPearson Functions For VBA Arrays

The main sub is almost the same but the code is longer because it needs some auxiliary functions to work properly (check CPearson link to understand properly what the code does):

Option Explicit

'Source: http://www.cpearson.com/excel/vbaarrays.htm

' Error Number Constants
'''''''''''''''''''''''''''
Public Const C_ERR_NO_ERROR = 0&
Public Const C_ERR_SUBSCRIPT_OUT_OF_RANGE = 9&
Public Const C_ERR_ARRAY_IS_FIXED_OR_LOCKED = 10&

Sub test()
Dim Inicio As Date 'just to check how long, not needed
Inicio = Now 'just to check how long, not needed`

Dim i As Long, j As Long
Dim LastColumn As Long, LastRow As Long
Dim MyData As Variant, ThisDataRow() As Variant
Dim HowManyCopies As Long, MyCounter As Long, CurrentRow As Long

Application.ScreenUpdating = False

'get last column, in your case 39
LastColumn = 39

'get last non blank row, tested with 5000 rows of data
LastRow = Range("A" & Rows.Count).End(xlUp).Row

'all data into array, headers included
MyData = Range("A1").CurrentRegion.Value

'clear range except headers
Range(Cells(2, 1), Cells(LastRow, LastColumn)).Clear

'Duplicate rows. Loop trough each row of array
'we start at row 2 because 1 is headers

HowManyCopies = 58 '58 copies of each row, 57+1 because we delete original one
CurrentRow = 2 'where to start duplicating

For i = 2 To UBound(MyData) Step 1
    'loop trough counter until HowManyCopies is reached
    For MyCounter = 1 To HowManyCopies Step 1
        'paste values into row using CPearson codes
        GetRow MyData, ThisDataRow, i
        Range(Cells(CurrentRow, 1), Cells(CurrentRow, LastColumn)).Value = ThisDataRow
        CurrentRow = CurrentRow + 1
    Next MyCounter
Next i

Erase MyData 'clean variable
Erase ThisDataRow

Application.ScreenUpdating = True

Debug.Print Format(Now - Inicio, "hh:nn:ss") 'just to check how long, not needed

End Sub

Function GetRow(Arr As Variant, ResultArr As Variant, RowNumber As Long) As Boolean
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' GetRow
' This populates ResultArr with a one-dimensional array that is the
' specified row of Arr. The existing contents of ResultArr are
' destroyed. ResultArr must be a dynamic array.
' Returns True or False indicating success.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Dim ColNdx As Long
''''''''''''''''''''''''''''''
' Ensure Arr is an array.
''''''''''''''''''''''''''''''
If IsArray(Arr) = False Then
    GetRow = False
    Exit Function
End If

''''''''''''''''''''''''''''''''''
' Ensure Arr is a two-dimensional
' array.
''''''''''''''''''''''''''''''''''
If NumberOfArrayDimensions(Arr) <> 2 Then
    GetRow = False
    Exit Function
End If

''''''''''''''''''''''''''''''''''
' Ensure ResultArr is a dynamic
' array.
''''''''''''''''''''''''''''''''''
If IsArrayDynamic(ResultArr) = False Then
    GetRow = False
    Exit Function
End If

''''''''''''''''''''''''''''''''''''
' Ensure ColumnNumber is less than
' or equal to the number of columns.
''''''''''''''''''''''''''''''''''''
If UBound(Arr, 1) < RowNumber Then
    GetRow = False
    Exit Function
End If
If LBound(Arr, 1) > RowNumber Then
    GetRow = False
    Exit Function
End If

Erase ResultArr
ReDim ResultArr(LBound(Arr, 2) To UBound(Arr, 2))
For ColNdx = LBound(ResultArr) To UBound(ResultArr)
    ResultArr(ColNdx) = Arr(RowNumber, ColNdx)
Next ColNdx

GetRow = True


End Function

Public Function NumberOfArrayDimensions(Arr As Variant) As Integer
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' NumberOfArrayDimensions
' This function returns the number of dimensions of an array. An unallocated dynamic array
' has 0 dimensions. This condition can also be tested with IsArrayEmpty.
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Dim Ndx As Integer
Dim Res As Integer
On Error Resume Next
' Loop, increasing the dimension index Ndx, until an error occurs.
' An error will occur when Ndx exceeds the number of dimension
' in the array. Return Ndx - 1.
Do
    Ndx = Ndx + 1
    Res = UBound(Arr, Ndx)
Loop Until Err.Number <> 0

NumberOfArrayDimensions = Ndx - 1

End Function

Public Function IsArrayDynamic(ByRef Arr As Variant) As Boolean
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' IsArrayDynamic
' This function returns TRUE or FALSE indicating whether Arr is a dynamic array.
' Note that if you attempt to ReDim a static array in the same procedure in which it is
' declared, you'll get a compiler error and your code won't run at all.
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

Dim LUBound As Long

' If we weren't passed an array, get out now with a FALSE result
If IsArray(Arr) = False Then
    IsArrayDynamic = False
    Exit Function
End If

' If the array is empty, it hasn't been allocated yet, so we know
' it must be a dynamic array.
If IsArrayEmpty(Arr:=Arr) = True Then
    IsArrayDynamic = True
    Exit Function
End If

' Save the UBound of Arr.
' This value will be used to restore the original UBound if Arr
' is a single-dimensional dynamic array. Unused if Arr is multi-dimensional,
' or if Arr is a static array.
LUBound = UBound(Arr)

On Error Resume Next
Err.Clear

' Attempt to increase the UBound of Arr and test the value of Err.Number.
' If Arr is a static array, either single- or multi-dimensional, we'll get a
' C_ERR_ARRAY_IS_FIXED_OR_LOCKED error. In this case, return FALSE.
'
' If Arr is a single-dimensional dynamic array, we'll get C_ERR_NO_ERROR error.
'
' If Arr is a multi-dimensional dynamic array, we'll get a
' C_ERR_SUBSCRIPT_OUT_OF_RANGE error.
'
' For either C_NO_ERROR or C_ERR_SUBSCRIPT_OUT_OF_RANGE, return TRUE.
' For C_ERR_ARRAY_IS_FIXED_OR_LOCKED, return FALSE.

ReDim Preserve Arr(LBound(Arr) To LUBound + 1)

Select Case Err.Number
    Case C_ERR_NO_ERROR
        ' We successfully increased the UBound of Arr.
        ' Do a ReDim Preserve to restore the original UBound.
        ReDim Preserve Arr(LBound(Arr) To LUBound)
        IsArrayDynamic = True
    Case C_ERR_SUBSCRIPT_OUT_OF_RANGE
        ' Arr is a multi-dimensional dynamic array.
        ' Return True.
        IsArrayDynamic = True
    Case C_ERR_ARRAY_IS_FIXED_OR_LOCKED
        ' Arr is a static single- or multi-dimensional array.
        ' Return False
        IsArrayDynamic = False
    Case Else
        ' We should never get here.
        ' Some unexpected error occurred. Be safe and return False.
        IsArrayDynamic = False
End Select

End Function

Public Function IsArrayEmpty(Arr As Variant) As Boolean
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' IsArrayEmpty
' This function tests whether the array is empty (unallocated). Returns TRUE or FALSE.
'
' The VBA IsArray function indicates whether a variable is an array, but it does not
' distinguish between allocated and unallocated arrays. It will return TRUE for both
' allocated and unallocated arrays. This function tests whether the array has actually
' been allocated.
'
' This function is really the reverse of IsArrayAllocated.
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

Dim LB As Long
Dim UB As Long

Err.Clear
On Error Resume Next
If IsArray(Arr) = False Then
    ' we weren't passed an array, return True
    IsArrayEmpty = True
End If

' Attempt to get the UBound of the array. If the array is
' unallocated, an error will occur.
UB = UBound(Arr, 1)
If (Err.Number <> 0) Then
    IsArrayEmpty = True
Else
    ''''''''''''''''''''''''''''''''''''''''''
    ' On rare occassion, under circumstances I
    ' cannot reliably replictate, Err.Number
    ' will be 0 for an unallocated, empty array.
    ' On these occassions, LBound is 0 and
    ' UBoung is -1.
    ' To accomodate the weird behavior, test to
    ' see if LB > UB. If so, the array is not
    ' allocated.
    ''''''''''''''''''''''''''''''''''''''''''
    Err.Clear
    LB = LBound(Arr)
    If LB > UB Then
        IsArrayEmpty = True
    Else
        IsArrayEmpty = False
    End If
End If

End Function

Here's the test:

enter image description here

Took just 55 seconds.

  • This is quality, exactly what I needed, you are a champion – EuanM28 Feb 20 '23 at 11:54
  • Only takes 6 minutes to run, that leads to 301,659 rows, class – EuanM28 Feb 20 '23 at 12:05
  • @EuanM28 Please, check updated answer and see if it takes less time. Thanks!!! – Foxfire And Burns And Burns Feb 21 '23 at 10:05
  • 1
    It took 4 min 35 seconds for me, but I have been experiencing a lot of weird runtimes with VBA (sometimes something that takes 1 minute takes 5 on off days, with the same amount of data). Regardless, this is faster so thank you! I'm sure it will run quicker in the future. Thank you again this helped massively. – EuanM28 Feb 21 '23 at 10:39
5

Try this more compact way, please:

Sub duplicateRows()
  Dim sh As Worksheet, i As Long
  Const duplRows As Long = 57 'number of rows to be inserted
  
  Set sh = ActiveSheet: i = 2 '1 is for the header
  Application.ScreenUpdating = False: Application.Calculation = xlCalculationManual
  Do While sh.Range("A" & i) <> ""
       sh.rows(i + 1 & ":" & i + duplRows).insert xlDown
       sh.rows(i + 1 & ":" & i + duplRows).Value2 = sh.rows(i).Value2
      
      i = i + duplRows + 1
  Loop
  Application.ScreenUpdating = True: Application.Calculation = xlCalculationAutomatic
End Sub

And a little faster version (copying only used range data) will be:

Sub duplicateRows_()
  Dim sh As Worksheet, lastr As Long, rngUR As Range, i As Long
  Const duplRows As Long = 3
  
  Set sh = ActiveSheet: i = 2 '1 is for the header
  Set rngUR = sh.UsedRange
  Application.ScreenUpdating = False: Application.Calculation = xlCalculationManual
  Do While sh.Range("A" & i) <> ""
       sh.rows(i + 1 & ":" & i + duplRows).insert xlDown
       Intersect(sh.rows(i + 1 & ":" & i + duplRows), rngUR.EntireColumn).Value2 = Intersect(sh.rows(i), rngUR).Value2
      
      i = i + duplRows + 1
  Loop
  Application.ScreenUpdating = True: Application.Calculation = xlCalculationAutomatic
End Sub

A fastest version would be the next. It (temporarily) returns in the next sheet, so take care to be empty. If you like the return, you can delete the exiting content of active sheet and paste there. It uses a second array and place the necessary data in it, dropping the processed result at once, at the end of the code. As I suggested in one of my below comments...:

Sub duplicateRowsArrays()
  Dim sh As Worksheet, sh1 As Worksheet, arrUR, arrFin, i As Long, j As Long, k As Long, c As Long
  Const duplRows As Long = 3
  
  Set sh = ActiveSheet: Set sh1 = sh.Next 'the sheet where to (temporarily) return the processed array result
  arrUR = sh.UsedRange.Value
  ReDim arrFin(1 To UBound(arrUR) * (duplRows + 1) + 1, 1 To UBound(arrUR, 2))
  
  For i = 1 To UBound(arrUR, 2): arrFin(1, i) = arrUR(1, i): Next i 'place the header in final array
  k = 2
  For i = 2 To UBound(arrUR)                  'starting iteration from the second row
        For j = 1 To duplRows + 1             'place the necessary data in the virtually inserted rows
            For c = 1 To UBound(arrUR, 2)
              arrFin(k, c) = arrUR(i, c)
            Next c
            k = k + 1
        Next j
  Next i
  
  'drop the final array content at once:
   sh1.Range("A1").Resize(UBound(arrFin), UBound(arrFin, 2)).Value = arrFin
End Sub

If you like the result, you should clear sh.cells and drop the result on sh.Range("A1")...

FaneDuru
  • 38,298
  • 4
  • 19
  • 27
  • Upvoted because this code is really really short and **it keeps original format if needed**, but it takes way longer than working with arrays – Foxfire And Burns And Burns Feb 20 '23 at 12:23
  • @Foxfire And Burns And Burns Thanks! I would say, it depends on the size of the range being processed, and it is not so slow. It does not use clipboard, keeping the format from insertion. Copying **in cell** from an array takes longer than array to array (a mean `.value` to `.value`). The code can be easily adapted to use intersection between used range and rows being copied/pasted. A really fast solution would be to drop the values in an array, too. It is easy to `ReDim` such an array from the beginning and load it in a simple iteration. – FaneDuru Feb 20 '23 at 12:36
  • @Foxfire And Burns And Burns The most saved time will come from **writing in cells only once, at the end of the code**. I placed a faster way using the above mentioned intersection. – FaneDuru Feb 20 '23 at 12:37
  • 1
    Tested with 20x39 dataset, 100 duplicates each row. Working with arrays takes `2,31E-05` and working with Insert takes `6,02E-04` Almost 26 times slower. I'm using Excel 2007. – Foxfire And Burns And Burns Feb 20 '23 at 13:10
  • @Foxfire And Burns And Burns It is obvious that inserting rows takes a lot of time... I am not near my computer now. When I will be near it I will try a piece of code writing in another array and drop the processed result at once. It must be the faster way, I think... – FaneDuru Feb 20 '23 at 13:17
3

Just out of curiosity, can you try this and let me know how long it takes? I think it might be faster than Foxfire's solution as it doesn't write to individual cells but rather into an array and then just assigns that array to a range.

Also please have the sheet you want to work with selected because I had some very weird errors when specifying the worksheet on some of the lines so I just got rid of it.

Sub dupeRows()
    Dim arr() As Variant, resultArr() As Variant, rng As Range, dupeCount As Long, lastRow As Long, lastColumn As Long
    
    dupeCount = 58 'specify number of duplicates here
    
    With ActiveSheet
        lastColumn = .Cells(1, .Columns.Count).End(xlToLeft).Column
        lastRow = .Cells(.Rows.Count, 1).End(xlUp).Row
    End With
    
    Set rng = Range(Cells(2, 1), Cells(lastRow, lastColumn))
    
    arr = rng
    ReDim resultArr(1 To (UBound(arr) * dupeCount), 1 To UBound(arr, 2))
    
    For i = 1 To UBound(arr)
        For k = 1 To dupeCount
            For j = 1 To UBound(arr, 2)
                resultArr((i - 1) * dupeCount + k, j) = arr(i, j)
            Next j
        Next k
    Next i
    Application.ScreenUpdating = False 'this probably doesn't really help in my case
        Range(Cells(2, 1), Cells(lastRow * dupeCount - dupeCount + 1, lastColumn)) = resultArr
    Application.ScreenUpdating = True
End Sub
andrewb
  • 1,129
  • 5
  • 9
1

With my computer (Windows 10, Excel 2010, 8 GB intern memory) and with values in the range A2:AM1001 (=1000 rows, which should be 58000 rows, ending in row 58001 after running the macro), I did a test with the 5 macro's above (each macro 3 x tested in every time a new file). These are the results:

  1. Foxfire And Burns And Burns: Sub test()--> Length of time: 57, 53, and 55 seconds. Result: ok.

  2. FaneDuru: Sub duplicaterows() --> After 6 minutes the macro was still running and I stopped it manually. At that moment 80 (of the 1000) rows (x 57) had been copied.

  3. FaneDuru: Sub duplicaterows_() --> The macro came with an error at this line: "Intersect(…." Error: "Object or block variable With is not set"

  4. FaneDuru: Sub duplicateRowsArrays() --> This macro did absolutely nothing.

  5. andrewB: Sub dupeRows() The macro stops after a few seconds. Only column A has the just values, other columns do not (they didn't change).

I myself wrote the macro below and on my computer it gives the correct result in 30 seconds, but I know there are faster ways. Assumption: the data are in a sheet with the name "Sheet1", adjust if necessary.

Sub Copy_Insert()
Dim x As Long
With Sheets("Sheet1")
x = .Range("a" & .Rows.Count).End(xlUp).Row
Application.ScreenUpdating = False
Do Until x = 1
.Rows(x).Copy
.Rows(x & ":" & x + 56).EntireRow.Insert
x = x - 1
Loop
Application.CutCopyMode = False
Application.ScreenUpdating = True
End With
End Sub
alpha
  • 21
  • 3
  • Did you understand that the third version returns **in the next sheet**? Did you look there? I tested it and worked as it should. The second version used to have a mistake, corrected using `rngUR.EntireColumn).Value2`... – FaneDuru Feb 20 '23 at 18:37
  • I see; the macro is very fast, but works not as it should. The first row is only once copied, and the copies must start in row 2. That's easy to fix, I think. – alpha Feb 20 '23 at 19:33
  • What "fast" does mean? You presented some time durations in your "analysis"... Why would you need/want to copy **the header** more than once? Based on what do you appreciate that "works not as it should"? – FaneDuru Feb 20 '23 at 19:42
  • I don't want the header to be copied! But when you look at the image of ts [here](https://i.stack.imgur.com/yblYz.png) you can see that the first row to be copied is row 2 with the values row1 - row1 - row1 - etc. That row, you copy only once! _"What "fast" does mean?_ I mean: fast, compared with other 'solutions' in this topic. – alpha Feb 20 '23 at 19:59
  • I do not know how you tested it. It starts inserting from the second row **inclusively**. Maybe you have some hidden rows there, or something I cannot check. And I thought that "fast" should be translated in the same way. I mean, how many minutes, seconds... – FaneDuru Feb 20 '23 at 20:06
  • In my first post I explained how i have tested the macro's! I don't have hidden rows and there is nothing wrong with my Excel 2010. Every test I started with a new file. To be able to compare properly, the macro's must give the correct solution and your macro doesn't do that (the first row with data is only copied 1 time instead of 57 times). I told you that twice and this is the third and last time. Ask others to test your macro (I did !) and they will come to the same conclusion. For me there is no point in discussing this further. – alpha Feb 20 '23 at 20:56
  • I suspect that my macro only worked for one column because you had no values in the first row, is this correct? The sub determines the number of columns by checking for the last cell with data on the first row. Thank you for doing this by the way! – andrewb Feb 21 '23 at 02:57