将行转置为单列,同时复制其他列中的数据

Transposing rows into a single column while copying data in other columns

我正在从 SQL 中提取数据,需要将一些行转置到列中,同时复制其他唯一的数据 table 需要一个公式来读取所有列并粘贴新行和复制数据。 这只是一个例子,具体取决于我需要在一列中转置尽可能多的行的日子。原始数据超过 50,000 行 欢迎任何建议

之前

Order   Line    Item    Day Day2   Day3  Day4  Day5  Day6   Day7
2000    1      Apple    Mon Tue    Wed         Fri   Sat    Sun  
2000    2      Orange   Mon               Thu               Sun  
etc...

之后

Order   Line    Item    Day
2000    1       Apple   Mon
2000    1       Apple   Tue
2000    1       Apple   Wed
2000    1       Apple   Fri
2000    1       Apple   Sat
2000    1       Apple   Sun
2000    2      Orange   Mon
2000    2      Orange   Thu
2000    2      Orange   Sun

这是一种快速而肮脏的方法。 运行 这可能需要几分钟,但这就是处理那么多行所需要的时间。

50,000x7 = 350,000 行,因此如果您有 Excel 的任何最新版本,您可以将输出放在另一个工作表上。我在 2010 年,行数限制为 1,048,576。

这假设数据在 Sheet1 上,我们将把它写到 Sheet2。

在您 VBA IDE 中转到工具菜单和 select 参考。 Select“Microsoft ActiveX 数据对象 2.8 库。

Private Sub CommandButton1_Click()

    Dim ws   As Excel.Worksheet
    Dim rs   As New ADODB.Recordset
    Dim lRow As Long

    'Add fields to your recordset for storing data.  This is how we will store the original data so we can process it after we read it.
    With rs
        .Fields.Append "Order", adInteger
        .Fields.Append "Line", adInteger
        .Fields.Append "Item", adChar, 25
        .Fields.Append "Day", adChar, 10
        .Fields.Append "Day2", adChar, 10
        .Fields.Append "Day3", adChar, 10
        .Fields.Append "Day4", adChar, 10
        .Fields.Append "Day5", adChar, 10
        .Fields.Append "Day6", adChar, 10
        .Fields.Append "Day7", adChar, 10
        .Open
    End With

    lRow = 2 'Start at two if there is a header row...
    Set ws = ActiveWorkbook.Sheets("Sheet1")
    ws.Activate

    'Loop through the rows and record the data
    Do While lRow <= ws.UsedRange.Rows.count

        If ws.Range("A" & lRow).Value <> "" Then
            rs.AddNew
            rs.Fields("Order").Value = ws.Range("A" & lRow).Value
            rs.Fields("Line").Value = ws.Range("B" & lRow).Value
            rs.Fields("Item").Value = ws.Range("C" & lRow).Value
            rs.Fields("Day").Value = ws.Range("D" & lRow).Value
            rs.Fields("Day2").Value = ws.Range("E" & lRow).Value
            rs.Fields("Day3").Value = ws.Range("F" & lRow).Value
            rs.Fields("Day4").Value = ws.Range("G" & lRow).Value
            rs.Fields("Day5").Value = ws.Range("H" & lRow).Value
            rs.Fields("Day6").Value = ws.Range("I" & lRow).Value
            rs.Fields("Day7").Value = ws.Range("J" & lRow).Value
            rs.Update
        End If

        lRow = lRow + 1
        ws.Range("A" & lRow).Activate
    Loop

    'Switch to the second worksheet
    Set ws = Nothing
    Set ws = ActiveWorkbook.Sheets("Sheet2")
    ws.Activate

    lRow = 1

    If rs.RecordCount > 0 Then
        rs.MoveFirst
    End If

    Do While rs.EOF = False

        If Trim(rs.Fields("Day").Value) <> "" Then
            ws.Range("A" & lRow).Value = rs.Fields("Order").Value
            ws.Range("B" & lRow).Value = rs.Fields("Line").Value
            ws.Range("C" & lRow).Value = rs.Fields("Item").Value
            ws.Range("D" & lRow).Value = rs.Fields("Day").Value
            lRow = lRow + 1
        End If

        If Trim(rs.Fields("Day2").Value) <> "" Then
            ws.Range("A" & lRow).Value = rs.Fields("Order").Value
            ws.Range("B" & lRow).Value = rs.Fields("Line").Value
            ws.Range("C" & lRow).Value = rs.Fields("Item").Value
            ws.Range("D" & lRow).Value = rs.Fields("Day2").Value
            lRow = lRow + 1
        End If

        If Trim(rs.Fields("Day3").Value) <> "" Then
            ws.Range("A" & lRow).Value = rs.Fields("Order").Value
            ws.Range("B" & lRow).Value = rs.Fields("Line").Value
            ws.Range("C" & lRow).Value = rs.Fields("Item").Value
            ws.Range("D" & lRow).Value = rs.Fields("Day3").Value
            lRow = lRow + 1
        End If

        If Trim(rs.Fields("Day4").Value) <> "" Then
            ws.Range("A" & lRow).Value = rs.Fields("Order").Value
            ws.Range("B" & lRow).Value = rs.Fields("Line").Value
            ws.Range("C" & lRow).Value = rs.Fields("Item").Value
            ws.Range("D" & lRow).Value = rs.Fields("Day4").Value
            lRow = lRow + 1
        End If

        If Trim(rs.Fields("Day5").Value) <> "" Then
            ws.Range("A" & lRow).Value = rs.Fields("Order").Value
            ws.Range("B" & lRow).Value = rs.Fields("Line").Value
            ws.Range("C" & lRow).Value = rs.Fields("Item").Value
            ws.Range("D" & lRow).Value = rs.Fields("Day5").Value
            lRow = lRow + 1
        End If

        If Trim(rs.Fields("Day6").Value) <> "" Then
            ws.Range("A" & lRow).Value = rs.Fields("Order").Value
            ws.Range("B" & lRow).Value = rs.Fields("Line").Value
            ws.Range("C" & lRow).Value = rs.Fields("Item").Value
            ws.Range("D" & lRow).Value = rs.Fields("Day6").Value
            lRow = lRow + 1
        End If

        If Trim(rs.Fields("Day7").Value) <> "" Then
            ws.Range("A" & lRow).Value = rs.Fields("Order").Value
            ws.Range("B" & lRow).Value = rs.Fields("Line").Value
            ws.Range("C" & lRow).Value = rs.Fields("Item").Value
            ws.Range("D" & lRow).Value = rs.Fields("Day7").Value
            lRow = lRow + 1
        End If

        ws.Range("A" & lRow).Activate
        rs.MoveNext
    Loop
End Sub

也许您可以修改 SQL 查询,例如使用 UNION 直接 return 结果? :

SELECT 'Order', Line, Item, Day1 AS Day 
FROM Table1 as T1
WHERE NOT IsNull(Day1)
UNION
SELECT 'Order', Line, Item, Day2 AS Day
FROM Table1
WHERE NOT IsNull(Day2)
UNION
SELECT 'Order', Line, Item, Day3 AS Day
FROM Table1
WHERE NOT IsNull(Day3)
UNION
SELECT 'Order', Line, Item, Day4 AS Day
FROM Table1
WHERE NOT IsNull(Day4)
UNION
SELECT 'Order', Line, Item, Day5 AS Day
FROM Table1
WHERE NOT IsNull(Day5)
UNION
SELECT 'Order', Line, Item, Day6 AS Day
FROM Table1
WHERE NOT IsNull(Day6)
UNION
SELECT 'Order', Line, Item, Day7 AS Day
FROM Table1
WHERE NOT IsNull(Day7)