How to “flatten” or “collapse” a 2D Excel table into 1D?

前端 未结 9 898
[愿得一人]
[愿得一人] 2020-11-28 05:02

I have a two dimensional table with countries and years in Excel. eg.

        1961        1962        1963        1964
USA      a           x            g           


        
相关标签:
9条回答
  • 2020-11-28 05:18

    I developed another macro because I needed to refresh the output table quite often (input table was filled by other) and I wanted to have more info in my output table (more copied column and some formulas)

    Sub TableConvert()
    
    Dim tbl As ListObject 
    Dim t
    Rows As Long
    Dim tCols As Long
    Dim userCalculateSetting As XlCalculation
    Dim wrksht_in As Worksheet
    Dim wrksht_out As Worksheet
    
    '##block calculate and screen refresh
    Application.ScreenUpdating = False
    userCalculateSetting = Application.Calculation
    Application.Calculation = xlCalculationManual
    
    '## get the input and output worksheet
    Set wrksht_in = ActiveWorkbook.Worksheets("ressource_entry")'## input
    Set wrksht_out = ActiveWorkbook.Worksheets("data")'## output.
    
    
    '## get the table object from the worksheet
    Set tbl = wrksht_in.ListObjects("Table14")  '## input
    Set tb2 = wrksht_out.ListObjects("Table2") '## output.
    
    '## delete output table data
    If Not tb2.DataBodyRange Is Nothing Then
        tb2.DataBodyRange.Delete
    End If
    
    '## count the row and col of input table
    
    With tbl.DataBodyRange
         tRows = .Rows.Count
         tCols = .Columns.Count
    End With
    
    '## check every case of the input table (only the data part)
    For j = 2 To tRows '## parse all row from row 2 (header are not checked)
        For i = 5 To tCols '## parse all column from col 5 (first col will be copied in each record)
            If IsEmpty(tbl.Range.Cells(j, i).Value) = False Then
                '## if there is time enetered create a new row in table2 by using the first colmn of the selected cell row and cell header plus some formula
                Set oNewRow = tb2.ListRows.Add(AlwaysInsert:=True)
                oNewRow.Range.Cells(1, 1).Value = tbl.Range.Cells(j, 1).Value
                oNewRow.Range.Cells(1, 2).Value = tbl.Range.Cells(j, 2).Value
                oNewRow.Range.Cells(1, 3).Value = tbl.Range.Cells(j, 3).Value
                oNewRow.Range.Cells(1, 4).Value = tbl.Range.Cells(1, i).Value
                oNewRow.Range.Cells(1, 5).Value = tbl.Range.Cells(j, i).Value
                oNewRow.Range.Cells(1, 6).Formula = "=WEEKNUM([@Date])"
                oNewRow.Range.Cells(1, 7).Formula = "=YEAR([@Date])"
                oNewRow.Range.Cells(1, 8).Formula = "=MONTH([@Date])"
            End If
       Next i
    Next j
    ThisWorkbook.RefreshAll
    
    '##unblock calculate and screen refresh
    Application.ScreenUpdating = True 
    Application.Calculate
    Application.Calculation = userCalculateSetting
    
    End Sub
    
    0 讨论(0)
  • 2020-11-28 05:18

    updated ReversePivotTable function so i can specify number of header columns and rows

    Sub ReversePivotTable()
    '   Before running this, make sure you have a summary table with column headers.
    '   The output table will have three columns.
        Dim SummaryTable As Range, OutputRange As Range
        Dim OutRow As Long
        Dim r As Long, c As Long
    
        Dim lngHeaderColumns As Long, lngHeaderRows As Long, lngHeaderLoop As Long
    
        On Error Resume Next
        Set SummaryTable = ActiveCell.CurrentRegion
        If SummaryTable.Count = 1 Or SummaryTable.Rows.Count < 3 Then
            MsgBox "Select a cell within the summary table.", vbCritical
            Exit Sub
        End If
        SummaryTable.Select
    
        Set OutputRange = Application.InputBox(prompt:="Select a cell for the 3-column output", Type:=8)
        lngHeaderColumns = Application.InputBox(prompt:="Header Columns")
        lngHeaderRows = Application.InputBox(prompt:="Header Rows")
    '   Convert the range
        OutRow = 2
        Application.ScreenUpdating = False
        'OutputRange.Range("A1:D3") = Array("Column1", "Column2", "Column3", "Column4")
        For r = lngHeaderRows + 1 To SummaryTable.Rows.Count
            For c = lngHeaderColumns + 1 To SummaryTable.Columns.Count
                ' loop through all header columns and add to output
                For lngHeaderLoop = 1 To lngHeaderColumns
                    OutputRange.Cells(OutRow, lngHeaderLoop) = SummaryTable.Cells(r, lngHeaderLoop)
                Next lngHeaderLoop
                ' loop through all header rows and add to output
                For lngHeaderLoop = 1 To lngHeaderRows
                    OutputRange.Cells(OutRow, lngHeaderColumns + lngHeaderLoop) = SummaryTable.Cells(lngHeaderLoop, c)
                Next lngHeaderLoop
    
                OutputRange.Cells(OutRow, lngHeaderColumns + lngHeaderRows + 1) = SummaryTable.Cells(r, c)
                OutputRange.Cells(OutRow, lngHeaderColumns + lngHeaderRows + 1).NumberFormat = SummaryTable.Cells(r, c).NumberFormat
                OutRow = OutRow + 1
            Next c
        Next r
    End Sub
    
    0 讨论(0)
  • 2020-11-28 05:30

    @Adam Davis's answer is perfect, but just in case you're as clueless as I am about Excel VBA, here's what I did to get the code working in Excel 2007:

    1. Open the workbook with the Matrix that needs to be flattened to a table and navigate to that worksheet
    2. Press Alt-F11 to open the VBA code editor.
    3. On the left pane, in the Project box, you'll see a tree structure representing the excel objects and any code (called modules) that already exist. Right click anywhere in the box and select "Insert->Module" to create a blank module file.
    4. Copy and paste @Adman Davis's code from above as is into the blank page the opens and save it.
    5. Close the VBA editor window and return to the spreadsheet.
    6. Click on any cell in the matrix to indicate the matrix you'll be working with.
    7. Now you need to run the macro. Where this option is will vary based on your version of Excel. As I'm using 2007, I can tell you that it keeps its macros in the "View" ribbon as the farthest right control. Click it and you'll see a laundry list of macros, just double click on the one called "ReversePivotTable" to run it.
    8. It will then show a popup asking you to tell it where to create the flattened table. Just point it to any empty space an your spreadsheet and click "ok"

    You're done! The first column will be the rows, the second column will be the columns, the third column will be the data.

    0 讨论(0)
提交回复
热议问题