1

I have categories as listed in columns: Company name, 1st name, last name, number of units, unit 1, unit 2, unit 3, unit 4, family, email, etc. Each company has its on row. However some companies can have multiple units at the same time. I want to separate the companies by their units.

Picture of Sheet1.
1st image When I start the VBA code, I want it to be copied to Sheet2 to look like the 2nd picture.

2nd image

Everything on the spreadsheets are made up.

My code displaces the columns but doesn't condense the columns I want into one column.
Also, I don't know how to copy from sheet to sheet.

Sub Button2_Click()

Dim cr As Long 'current row
Dim cc As Long 'current column

For cr = 2 To 11
    For cc = 8 To 11 Step 2
        If Cells(cr, cc).Value = "R" Then
            'make column 13 (M) in current row = unit
            Cells(cr, 13).Value = Cells(1, cc).Value
        End If
    Next
Next
End Sub
VBasic2008
  • 44,888
  • 5
  • 17
  • 28
  • You don't indicate what your coding problem is, but, for one thing, you have an undeclared and undefined variable (`unit`). You also don't describe the logic you want to use to move the columns around. I don't understand why MS makes NOT requiring variable declaration the default. I suggest you select `Tools/Options/Editor` and check `Require Variable Declaration`. This will place `Option Explicit` at the start of any new module. To correct **this** module, enter it manually at the beginning. – Ron Rosenfeld Jun 29 '22 at 19:00
  • 1
    BTW, your screenshot of data is virtually useless for doing proper troubleshooting. It cannot be copy/pasted into a worksheet. Having to manually enter the data is discouraging to those who might assist you. To make the data useful edit your question to post it as text, perhaps using this [Markdown Tables Generator](http://www.tablesgenerator.com/markdown_tables). – Ron Rosenfeld Jun 29 '22 at 19:06
  • With regard to your comment about etiquette, I suggest you continue your other two question threads, so as to eventually "close them out" before starting a new one. – Ron Rosenfeld Jun 29 '22 at 19:07
  • @RonRosenfeld I have commented on other posts I have posted. As a matter of fact, I have thanked a person who responded to me on my 1st posts. The other person that commented on my other post, I did not respond because I deleted the post. I see your other comments. I am willing to learn from you and others on how to posts just as long as long as the comments are respective (in which some have not been). – blackmamba89 Jun 29 '22 at 19:14
  • What @RonRosenfeld is saying that to help you, we need sample data to debug and it's tedious to transfer a pic into cells. Help us to help you. – findwindow Jun 29 '22 at 19:19
  • @findwindow that makes sense. That I completely understand. In that case, I will try to edit my post to reflect your suggestion. – blackmamba89 Jun 29 '22 at 19:27
  • 1
    If I am not mistaken, what you want to do is called “unpivot”. For example, this could be a starting point: https://stackoverflow.com/questions/36365839/transpose-multiple-columns-to-multiple-rows-with-vba – Anonymous Jun 29 '22 at 20:39
  • @Anonymous thank you so much! You helped me out a lot. The link you gave helped me find my solution. Cheers! – blackmamba89 Jun 30 '22 at 00:02
  • @blackmamba89 Great. Is there a way to mark my post with the link for the next person looking for this issue? Cheers! – Anonymous Jun 30 '22 at 02:26

2 Answers2

1

Transform Data (Unpivot)

  • Adjust (play with) the values in the constants section.
Option Explicit

Sub TransformData()

    ' 1. Define constants (the arrays obviously aren't constants).

    ' s - source (read from)
    ' sd - source data (no headers)
    ' d - destination (write to)
    ' r - row
    ' c - column
    ' u - unpivot (columns)
    ' v - value (columns)
    
    ' Source
    Const sName As String = "Sheet1"
    ' These columns will be unpivoted...
    Dim suCols() As Variant: suCols = VBA.Array(8, 9, 10, 11)
    ' ... while these columns will be just copied except for the 0 column...
    Dim svCols() As Variant: svCols = VBA.Array(12, 4, 0, 5, 6, 2, 3)
    ' which is a 'place holder' for the pivot column.
    ' The 'svCols' array 'tells' that column 12 will be written to column 1,
    ' column 4 will be written to column 2, the unpivot columns will be written
    ' to column 3, ... etc.
    
    ' Destination
    Const dName As String = "Sheet2"
    Const dFirstCellAddress As String = "A1"
    Const duTitle As String = "Unit Name"

    ' 2. Reference the workbook.
    Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
    
    ' 3. Reference the source worksheet ('sws'), the source range ('srg')
    ' and the source data range ('sdrg'). Also, write the number of rows
    ' of each of the ranges to variables ('srCount', 'sdrCount')
    Dim sws As Worksheet: Set sws = wb.Worksheets(sName)
    Dim srg As Range: Set srg = sws.Range("A1").CurrentRegion ' has headers
    Dim srCount As Long: srCount = srg.Rows.Count ' incl. headers
    Dim sdrCount As Long: sdrCount = srCount - 1 ' excl. headers
    Dim sdrg As Range: Set sdrg = srg.Resize(sdrCount).Offset(1) ' no headers
    
    ' 4. The Number of Destination Rows and Columns
    
    ' Determine the number of destination rows ('drCount').
    
    Dim suUpper As Long: suUpper = UBound(suCols)
    Dim drCount As Long: drCount = 1 ' headers
    
    Dim su As Long
    
    For su = 0 To suUpper
        drCount = drCount + sdrCount _
            - Application.CountBlank(sdrg.Columns(suCols(su)))
    Next su
    
    ' Determine the number of destination columns ('dcCount').
    Dim svUpper As Long: svUpper = UBound(svCols)
    Dim dcCount As Long: dcCount = svUpper + 1
    
    ' 5. The 2D One-Based Arrays
    
    ' Write the values from the source range to an array ('sData').
    Dim sData As Variant: sData = srg.Value
    
    ' Define the destination array ('dData').
    Dim dData As Variant: ReDim dData(1 To drCount, 1 To dcCount)
    
    ' 6. Write the values from the source array to the destination array.
    
    ' Write headers.
    
    Dim sValue As Variant
    Dim sv As Long
    
    For sv = 0 To svUpper
        If svCols(sv) = 0 Then ' unpivot
            sValue = duTitle
        Else ' value
            sValue = sData(1, svCols(sv))
        End If
        dData(1, sv + 1) = sValue
    Next sv
    
    ' Write data.
    
    Dim dr As Long: dr = 1 ' headers are already written
    
    Dim sr As Long
    
    For sr = 2 To srCount
        For su = 0 To suUpper
            sValue = sData(sr, suCols(su))
            If Not IsEmpty(sValue) Then
                dr = dr + 1
                For sv = 0 To svUpper
                    If svCols(sv) = 0 Then ' unpivot
                        sValue = sData(sr, suCols(su))
                    Else ' value
                        sValue = sData(sr, svCols(sv))
                    End If
                    dData(dr, sv + 1) = sValue
                Next sv
            End If
        Next su
    Next sr
    
    ' 7. Write the results to the destination worksheet.
    
    ' Reference the destination worksheet.
    Dim dws As Worksheet: Set dws = wb.Worksheets(dName)
    ' Clear previous data.
    dws.Cells.Clear
    
    ' Write the new values.
    With dws.Range(dFirstCellAddress).Resize(, dcCount)
        ' Write the values from the destination array
        ' to the destination worksheet.
        .Resize(drCount).Value = dData
        ' Apply simple formatting:
        ' Headers.
        .Font.Bold = True
        ' Entire Columns
        .EntireColumn.AutoFit
    End With
    
    ' Save the workbook.
    'wb.Save
    
    ' 8. Inform to not wonder if the code has run or not.
    
    MsgBox "Data transformed.", vbInformation
    
End Sub
VBasic2008
  • 44,888
  • 5
  • 17
  • 28
  • thank you very much. This code worked perfectly for what I was trying to do! – blackmamba89 Jun 30 '22 at 06:20
  • Hey, again thank you so much for your answer. You really helped me a lot. I have one more question: array suCols = 8,9,10,11 turns into one column as you stated. Is it possible to add another array that turns into a 2nd column? Any suggestions on how to do that without messing up the code. I tried creating new variables but it messed it up. – blackmamba89 Jul 02 '22 at 07:28
0

VBA here is a sledgehammer to crack a nut.

It is easily done with a Pivot Table.
To get the rows with multiple units to have separate records for each unit: in M1 put Use_Unit.
In M2 =H2 and drag down.
Then in a area below the current data (say starting at row 1002):
In A1002 =A2 and drag across and down, except that in M1002 put =if(I2="","Ignore", I2) (or I1002).
Similarly for third and fourth blocks, looking ad J and K respectively.
Then do the Pivot Table, and filter out Unit_Use = Ignore

zsalya
  • 454
  • 4
  • 8