Move and Rearrange Data based on Header

ruinedelf

New Member
Joined
Dec 6, 2023
Messages
35
Office Version
  1. 365
  2. 2021
Platform
  1. Windows
  2. MacOS
Hiya, another quandary for me. I've been able to prompt up a script that does the following:

1. Define a destination table (table 1).
2. Define a source table (table 2).
3. Move columns from table 2 to table 1 based on column header.

The script works wonderfully with one caveat: there cannot be any empty cells in table 1's header row. However, the situation I'm in requires those blank cells to be present. What would need to be modified in order to do so? Hope someone can help out!

Please see below for the script I currently have:

VBA Code:
Sub CopyAndRearrangeData()
    Dim ws As Worksheet
    Set ws = ThisWorkbook.Sheets("ALS Import") ' Change "ALSImport" to your sheet's name
    
    ' Find the last column in row 1 of the sheet
    Dim lastColumn As Long
    lastColumn = ws.Cells(1, ws.Columns.Count).End(xlToLeft).Column
    
    Dim table1Range As Range
    Set table1Range = ws.Range("A2").Resize(53, lastColumn) ' ws.Range (Destination Table Starting Row), Resize (# of Rows, # of Columns)
    
    Dim table2HeaderRow As Range
    Set table2HeaderRow = ws.Range("A61").Resize(1, ws.Cells(61, ws.Columns.Count).End(xlToLeft).Column) ' ws.Range (Source Table Starting Row)
    
    Dim i As Integer
    For i = 1 To table1Range.Columns.Count
        Dim header As String
        header = table1Range.Cells(1, i).Value
        
        Dim headerIndex As Long
        headerIndex = 0
        
        For Each cell In table2HeaderRow
            If cell.Value = header Then
                headerIndex = cell.Column
                Exit For
            End If
        Next cell
        
        If headerIndex > 0 Then
            Dim destColumn As Range
            Set destColumn = table1Range.Columns(i)
            
            Dim sourceColumn As Range
            Set sourceColumn = ws.Cells(61, headerIndex).Resize(ws.Cells(ws.Rows.Count, headerIndex).End(xlUp).Row - 60)
            
            ' Copy the data
            sourceColumn.Copy Destination:=destColumn.Resize(sourceColumn.Rows.Count, 1)
            destColumn.NumberFormat = "General"
            
            ' Clear the source data (Table 2)
            sourceColumn.Clear
        End If
    Next i
    
    Application.CutCopyMode = False
End Sub
 

Excel Facts

What is =ROMAN(40) in Excel?
The Roman numeral for 40 is XL. Bill "MrExcel" Jelen's 40th book was called MrExcel XL.
Oh dangit. Early celebration.

Tried it on another set of sample data, and I'm getting a Run-time error 1004 - Unable to get the Match property of the Worksheet Function class.

I'm guessing that this error is because it's assuming that every header in the source table can be found in the destination table?

I may have forgotten to mention that sometimes, parts of the source data is not required. For instance, there may be times there's Analyte 150 in the source data, but no Analyte 150 in the destination data, because it's just not needed.

...My bad.
 
Upvote 0
OK, replace the relevant part of the code with:
VBA Code:
Dim i As Long
    For Each c In SrcHdr
        If WorksheetFunction.CountIf(DstHdr, c) > 0 Then
        i = WorksheetFunction.Match(c, DstHdr, 0)
            With ws.Range(Cells(62, c.Column), ws.Cells(ws.Cells(Rows.Count, c.Column).End(xlUp).Row, c.Column))
                .Copy ws.Cells(3, i)
                .Delete shift:=xlUp
            End With
        End If
    Next c
 
Upvote 0
This returns the same error (1004- unable to get the Match property of the WorksheetFunction class) on the following line:

VBA Code:
i = WorksheetFunction.Match(c, DstHdr, 0)
 
Upvote 0
It doesn't error for me when I test it on sample data - where the header in the source range doesn't exist in the destination range:
Destination
ruinedelf.xlsm
ABCDEFGHI
1FMP Field 1FMP Field 2FMP Field 3FMP Field 4FMP Field 5FMP Field 6FMP Field 7FMP Field 8FMP Field 9
2Analyte 1Analyte 2Analyte 3Analyte 4Analyte 5Analyte 6Analyte 7Analyte 8
3
Sheet1

Source (note Analyte 33)
ruinedelf.xlsm
ABCDEF
61Analyte 5Analyte 33Analyte 1Analyte 6Analyte 7Analyte 2
62234456464357234<623467
636346324234<4<2234546890
Sheet1

After running this code:
VBA Code:
Option Explicit
Sub Demo()
    'Get the sheet name
    Dim ws As Worksheet
    Set ws = Worksheets("Sheet1")   '<-- change as needed
    
    'Dim the range variables
    Dim SrcHdr As Range, DstHdr As Range, c As Range
    
    'Set the range variables
    Set SrcHdr = ws.Range(ws.Cells(61, 1), ws.Cells(61, ws.Rows("61").Find("*", , xlFormulas, , 2, 2).Column))
    Set DstHdr = ws.Range(ws.Cells(2, 1), ws.Cells(2, ws.Rows("2").Find("*", , xlFormulas, , 2, 2).Column))
    
    'Loop through each cell in the source header range,
    'find the matching header in the destination row,
    'and copy the data from the source to the destination
    Dim i As Long
    For Each c In SrcHdr
        If WorksheetFunction.CountIf(DstHdr, c) > 0 Then
        i = WorksheetFunction.Match(c, DstHdr, 0)
            With ws.Range(Cells(62, c.Column), ws.Cells(ws.Cells(Rows.Count, c.Column).End(xlUp).Row, c.Column))
                .Copy ws.Cells(3, i)
                .Delete shift:=xlUp
            End With
        End If
    Next c
End Sub
I get this in the destination:
ruinedelf.xlsm
ABCDEFGHI
1FMP Field 1FMP Field 2FMP Field 3FMP Field 4FMP Field 5FMP Field 6FMP Field 7FMP Field 8FMP Field 9
2Analyte 1Analyte 2Analyte 3Analyte 4Analyte 5Analyte 6Analyte 7Analyte 8
36435723467234234<6
4<45468906346<2234
Sheet1

Leaving this in the source:
ruinedelf.xlsm
ABCDEF
61Analyte 5Analyte 33Analyte 1Analyte 6Analyte 7Analyte 2
624564
63324234
Sheet1
 
Upvote 0
It's still failing on my end. I created a new workbook with just the reference headers, pasted data, and the module.

Have a gander at this: LINK and see if you can reproduce it on your end?
 
Upvote 0
I'll have to leave this until tomorrow (my time) as life's caught up.
 
Upvote 0
Last response for the day (this worked with your latest sample)
VBA Code:
Option Explicit
Sub CutAndRearrangeData()
    'Get the sheet name
    Dim ws As Worksheet
    Set ws = Worksheets("Sheet1")   '<-- change as needed
    
    'Dim the range variables
    Dim SrcHdr As Range, DstHdr As Range, c As Range
    
    'Set the range variables
    Set SrcHdr = ws.Range(ws.Cells(61, 1), ws.Cells(61, ws.Rows("61").Find("*", , xlFormulas, , 2, 2).Column))
    Set DstHdr = ws.Range(ws.Cells(2, 1), ws.Cells(2, ws.Rows("2").Find("*", , xlFormulas, , 2, 2).Column))
    SrcHdr.Select
    DstHdr.Select
    'Loop through each cell in the source header range,
    'find the matching header in the destination row,
    'and copy the data from the source to the destination
    Dim i As Long, rFind As Range
    For Each c In SrcHdr
        With ws.Rows("2:2")
        Set rFind = .Find(c, Lookat:=xlWhole)
        If Not rFind Is Nothing Then
        i = WorksheetFunction.Match(c, DstHdr, 0)
            With ws.Range(Cells(62, c.Column), ws.Cells(ws.Cells(Rows.Count, c.Column).End(xlUp).Row, c.Column))
                .Copy ws.Cells(3, i)
                .Delete shift:=xlUp
            End With
        End If
        End With
    Next c
End Sub
 
Upvote 0
Solution
Last response for the day (this worked with your latest sample)
Yup, this one works for what I had! I'll have to try it with some live data (and still waiting on a Mac test), but it looks promising!

Thanks again!
 
Upvote 0

Forum statistics

Threads
1,215,071
Messages
6,122,964
Members
449,094
Latest member
Anshu121

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