Home > Software engineering >  Convert Each Data set into 1 row
Convert Each Data set into 1 row

Time:10-26

Im trying to make a macro on Excel using VBA that will transpose each Data set into 1 row only.

Initial Format of Table

No.               1
Code              A1B1
Date              10/25/21
No.               2
Code              A2B2
Date              10/26/21

Outcome should be like this in Sheet2

No.       Code          Date
1         A1B2        10/25/21
2         A2B2        10/26/21

I tried to copy Row that contain "No.". But I want it to be extracted to cell B2. Where should I start?

    Sub CopyNo()
  Dim LastRow As Long
  LastRow = Worksheets("Sheet1").Cells(Rows.Count, "A").End(xlUp).Row
  With Worksheets("Sheet2").Range("A1:A" & LastRow)
    Worksheets("Sheet1").Range("A1:A" & LastRow).EntireRow.Copy .Range("A1")
    With .Offset
      .Replace "No.", "=No.", xlPart
      On Error Resume Next
      .Offset(1).SpecialCells(xlConstants).EntireRow.Delete
      On Error GoTo 0
      .Replace "=No.", "No.", xlPart
    End With
  End With
End Sub

CodePudding user response:

This is a type of Pivot Table, but with no aggregation of the results (Not something that can be done in the regular Pivot Tables for Excel)

But you can do this in Power Query, available in Windows Excel 2010 and Office 365

To use Power Query

  • Select some cell in your Data Table
  • Data => Get&Transform => from Table/Range
  • When the PQ Editor opens: Home => Advanced Editor
  • Make note of the Table Name in Line 2
  • Paste the M Code below in place of what you see
  • Change the Table name in line 2 back to what was generated originally.
  • Read the comments in the code and explore the Applied Steps to understand the algorithm

M Code

let

//Read in the data
//Change table name in next line to actual table name in your worksheet
    Source = Excel.CurrentWorkbook(){[Name="Table22"]}[Content],

//Custom function
//see credits for explanation
    pivot = fnPivotAll(Source, "Column1","Column2"),

//set data types
    #"Changed Type" = Table.TransformColumnTypes(pivot,{
            {"No.", Int64.Type}, 
            {"Code", type text},
            {"Date", type date}})
in
    #"Changed Type"

Note that you will need to use a custom function for this solution

  • To enter the custom function:
    • Data => GetData => From other sources => Blank Query
    • When the PQ Editor opens: Home => Advanced Editor
      • Replace the code with the code below
      • over on the right hand menu, change Query Name to fnPivotAll
      • See the link in the credits for understanding the algorithm and reason for doing it this way.
//credit: Cam Wallace  https://www.dingbatdata.com/2018/03/08/non-aggregate-pivot-with-multiple-rows-in-powerquery/
//rename fnPivotAll

(Source as table,
    ColToPivot as text,
    ColForValues as text)=> 

let
     PivotColNames = List.Buffer(List.Distinct(Table.Column(Source,ColToPivot))),
     #"Pivoted Column" = Table.Pivot(Source, PivotColNames, ColToPivot, ColForValues, each _),
 
    TableFromRecordOfLists = (rec as record, fieldnames as list) =>
    
    let
        PartialRecord = Record.SelectFields(rec,fieldnames),
        RecordToList = Record.ToList(PartialRecord),
        Table = Table.FromColumns(RecordToList,fieldnames)
    in
        Table,
 
    #"Added Custom" = Table.AddColumn(#"Pivoted Column", "Values", each TableFromRecordOfLists(_,PivotColNames)),
    #"Removed Other Columns" = Table.RemoveColumns(#"Added Custom",PivotColNames),
    #"Expanded Values" = Table.ExpandTableColumn(#"Removed Other Columns", "Values", PivotColNames)
in
    #"Expanded Values"

`enter image description here

CodePudding user response:

Transpose Vertical Data

  • It is assumed that your data is contiguous (no empty rows (or empty columns)) and it starts in cell A1.
  • It is assumed that the destination headers are already written (in this case in the range A1:C1).
  • Adjust the values in the constants section.
Option Explicit

Sub TransposeVerticalData()
    Const ProcTitle As String = "Transpose Vertical Data"
    
    ' Source
    Const sName As String = "Sheet1"
    Const sCriteriaList As String = "No.,Code,Date"
    Const shColumn As Long = 1 ' Header Column
    Const svColumn As Long = 2 ' Value Column
    ' Destination
    Const dName As String = "Sheet2"
    Const dFirst As String = "A2"
    ' Workbook
    Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
    
    ' Source (Worksheet, Range, Rows Count, Data Array, Criteria Array)
    Dim sws As Worksheet: Set sws = wb.Worksheets(sName)
    Dim srg As Range: Set srg = sws.Range("A1").CurrentRegion.Resize(, svColumn)
    Dim srCount As Long: srCount = srg.Rows.Count
    Dim sData As Variant: sData = srg.Value
    Dim sCriteria() As String: sCriteria = Split(sCriteriaList, ",")
    
    ' Destination (Rows Count, Columns Count, Data Array)
    Dim drCount As Long
    drCount = Application.CountIf(srg.Columns(1), sCriteria(0))
    If drCount = 0 Then Exit Sub
    Dim dcCount As Long: dcCount = UBound(sCriteria)   1
    Dim dData As Variant: ReDim dData(1 To drCount, 1 To dcCount)
    
    ' Additional 'For Next Loop' Variables
    Dim sValue As Variant ' Source Value (First Column of the Source Array)
    Dim sIndex As Variant ' Index of the Source Value in Source Criteria Array
    Dim sr As Long ' Source Array Rows Counter
    Dim dr As Long ' Destination Array Rows Counter
    
    ' Write the values from the Source Array to the Destination Array.
    For sr = 1 To srCount
        sValue = sData(sr, shColumn)
        sIndex = Application.Match(sValue, sCriteria, 0)
        If IsNumeric(sIndex) Then ' Number i.e. 'sValue' found in 'sCriteria'
            If sIndex = 1 Then ' i.e. 'sValue = sCriteria(0)'
                dr = dr   1
            'Else ' i.e. 'sValue <> sCriteria(0)'
            End If
            dData(dr, sIndex) = sData(sr, svColumn) ' write
        'Else ' Error Value i.e. 'sValue' not found in 'sCriteria'
        End If
    Next sr
    
    ' Write the values from the Destination Array to the Destination Range
    ' (Worksheet, First Cell, Range).
    Dim dws As Worksheet: Set dws = wb.Worksheets(dName)
    Dim dfCell As Range: Set dfCell = dws.Range(dFirst)
    Dim drg As Range: Set drg = dfCell.Resize(drCount, dcCount)
    drg.Value = dData
    
    ' Clear the Clear Range, the range below the Destination Range, to remove
    ' possibly remaining data of a previously larger data set.
    Dim dcrg As Range: Set dcrg = _
        drg.Resize(dws.Rows.Count - drg.Row - drCount   1).Offset(drCount)
    dcrg.Clear

    ' Inform.
    MsgBox "Vertical data transposed.", vbInformation, ProcTitle

End Sub
  • Related