Home > Enterprise >  How can I automatically change the dimensions of my data by copy and pasting?
How can I automatically change the dimensions of my data by copy and pasting?

Time:02-23

I have some data that takes up 4 columns and 1400 rows. Every 15th row corresponds to a different city, which is named in column A. For example, rows 1-14 might be Tokyo, but rows 15-28 Toronto. For now, we can ignore column A. Is there any way to automatically copy and paste each remaining 14 row and 3 column block such that they will all appear side-by-side?

My ultimate goal is to put a header row of merged cells made from column A above each 14 by 3 block in order to give them a title. However, I must first extract the required 14 by 3 blocks. I presume that this is the job for a VBA macro?

For example, part of my data looks like this:

Location Team Staff Sales
Toronto 1 1100 55
Toronto 2 2100 56

[...12 more Toronto rows]

Location Team Staff Sales
Tokyo 21 7100 75
Tokyo 42 3100 16
Tokyo 35 9200 41

etc

My best attempt so far was to take this raw data and reference it on another sheet with =RAW!$B1:$D14 and drag that formula down through the hundreds of rows, copy the result, and then transpose it. This gave me the correct output, but each 14 by 3 block was separated by a 11 by 14 block of empty cells. I wanted them side-by-side.

CodePudding user response:

Please, test the next code. It uses arrays and their slice arrays and returns in the next sheet. You can choose any destination sheet you need. If you test it as it is, you must be sure that another sheet exists after the active one (to be processed) and it is empty:

Sub CopySlicesOf15()
  Dim sh As Worksheet, shDest As Worksheet, lastR As Long, arr, arrSlice, arrH, arrA
  Dim cellInit As Range, iPaste As Long, lastArrR As Long, i As Long, k As Long
  
  Set sh = ActiveSheet  'use here the sheet to be processed
  Set shDest = sh.Next  'use here the sheet where to return the processed result
  Set cellInit = shDest.Range("A2")     'the cell where to start pasting the slice arrays from
  lastR = sh.Range("B" & sh.rows.count).End(xlUp).row 'you use 1400 instead if you like that...
  arrA = sh.Range("A1:A" & lastR).value 'place the range in an array for faster iteration
  arr = sh.Range("B1:D" & lastR).value  'place the rang in an aray, for faster iteration and slicijg
  ReDim arrH(Int(lastR / 15)   1)       'redim the array keeping the future headers
  For i = 1 To UBound(arr) Step 15      'iterate between the main array in steps of 15 rows:
        arrH(k) = arrA(i, 1): k = k   1 'place the appropriate header in the headers array
        If i > (UBound(arr) - 15) Then
            lastArrR = i   (UBound(arr) - i)  'the slice numbere of rows for the last slice
        Else
            lastArrR = i   14                 'until the last slice, the slice numbere of rows will be 15
        End If
        'extract the necessary slice array:
        arrSlice = Application.Index(arr, Evaluate("row(" & i & ":" & lastArrR & ")"), Evaluate("column(A:C)"))
        'drop the array content at once in the appropriate cells:
        shDest.Range("A2").Offset(0, iPaste).Resize(IIf(UBound(arr) = i, 1, UBound(arrSlice)), 3).value = arrSlice: iPaste = iPaste   3
  Next i
  
  iPaste = 1                                  'reinitialize the variable
  For i = 1 To UBound(arrH)                   'iterate between the headers array
    shDest.cells(1, iPaste).value = arrH(i)   'place the header name in the cell
    'merge cells and center:
    With shDest.Range(shDest.cells(1, iPaste), shDest.cells(1, iPaste).Offset(0, 2))
        .merge
        .HorizontalAlignment = xlCenter
    End With
    iPaste = iPaste   3 ' increment the variable for next cell to paste the header
  Next
End Sub
  • Related