我有几百行数据,其中一列包含学生姓名,一列包含作业 ID,一列包含分数。我正在寻找 MS Excel 中预处理数据集的方法,可以使用内置函数或 VB 宏,以便将分数组织成一系列以学生姓名为标签的分数。如果可能的话,我想在绘制图表时使用作业 ID 作为 y 轴标签。MS Excel 中是否有用于预处理此类数据的宏或函数?
A. B. C.
1 Name ID Score
2 Al 1000 97%
3 Rob 1000 93%
4 Jack 1000 95%
5 Al 1001 92%
6 Rob 1001 97%
7 Tim 1001 98%
8 Jack 1001 93%
转换为
A. B. C.
1 Name 1000 1001
2 Al 97% 92%
3 Rob 93% 97%
4 Jack 95% 93%
5 Tim 98%
答案1
更新:
尝试插入一个数据透视表。
答案2
数据透视表列 (VBA 解决方案)
- 第一列包含行标签 (R)。您想要旋转第二列,其中包含列标签 (C)。第三列包含值 (V)。
- 该解决方案将涵盖前一种解决方案,它通常可能以不同的形式出现,例如,您可能想要旋转第一列,有多个行标签或列标签,值在另一列中,如果有重复项,您可能想要求和,等等。因此,我建议您研究另一种简单的方法(除了
PivotTable
)使用PowerQuery
(以前Get & Transform
)和大量选项来做到这一点。 - 调整(使用)常量部分中的值。
Option Explicit
Sub PivotRCV()
Const sName As String = "Sheet1"
Const sFirst As String = "A1"
Const dName As String = "Sheet1"
Const dFirst As String = "E1"
Dim wb As Workbook: Set wb = ThisWorkbook
' Create a reference to the Source Range ('srg').
Dim sws As Worksheet: Set sws = wb.Worksheets(sName)
Dim srg As Range: Set srg = RefColumns(sws.Range(sFirst).Resize(, 3))
If srg Is Nothing Then Exit Sub ' empty columns, not even headers
Dim srCount As Long: srCount = srg.Rows.Count
If srCount = 1 Then Exit Sub ' only headers, no data
' Write the unique row labels to the Row Labels Array ('rLabels').
Dim srrg As Range
Set srrg = srg.Columns(1).Resize(srCount - 1).Offset(1)
Dim rLabels As Variant: rLabels = ArrUniqueColumnRange(srrg)
If IsEmpty(rLabels) Then Exit Sub ' only error values and/or blanks
' Write the unique column labels to the Column Labels Array ('cLabels').
Dim scrg As Range
Set scrg = srg.Columns(2).Resize(srCount - 1).Offset(1)
Dim cLabels As Variant: cLabels = ArrUniqueColumnRange(scrg)
If IsEmpty(cLabels) Then Exit Sub ' only error values and/or blanks
' Write values from the Source Range to the Source Array ('sData').
Dim sData As Variant: sData = srg.Value
' Define the Destination Array ('dData').
Dim drCount As Long: drCount = UBound(rLabels) + 2 ' both +1 - zero-based...
Dim dcCount As Long: dcCount = UBound(cLabels) + 2 ' ... +1 - headers
Dim dData As Variant: ReDim dData(1 To drCount, 1 To dcCount)
' Write to Destination Array.
dData(1, 1) = sData(1, 1) ' First (Row Label) Header
Dim n As Long
For n = 0 To drCount - 2 ' Row Labels
dData(n + 2, 1) = rLabels(n)
Next n
For n = 0 To dcCount - 2 ' Column Labels
dData(1, n + 2) = cLabels(n)
Next n
Dim r As Long
Dim c As Long
For n = 2 To srCount ' Values
r = Application.Match(sData(n, 1), rLabels, 0) + 1
c = Application.Match(sData(n, 2), cLabels, 0) + 1
dData(r, c) = sData(n, 3)
Next n
' Create a reference to the Destination Range ('drg').
Dim dws As Worksheet: Set dws = wb.Worksheets(dName)
Dim drg As Range: Set drg = dws.Range(dFirst).Resize(drCount, dcCount)
' Write to the Destination Range.
'drg.Clear
drg.Value = dData
' Format the Destination Range.
With drg.Rows(1) ' Headers
.Font.Bold = True
End With
With drg.Resize(drCount - 1, dcCount - 1).Offset(1, 1) ' Values
.NumberFormat = "0%"
End With
' Inform user.
MsgBox sData(1, 2) & " column pivoted successfully.", _
vbInformation, "Pivot RCV"
End Sub
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Purpose: Creates a reference to the range from a row range
' ('FirstRowRange') to the row range containing
' the bottom-most non-empty cell in the given row's columns.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Function RefColumns( _
ByVal FirstRowRange As Range) _
As Range
If FirstRowRange Is Nothing Then Exit Function
With FirstRowRange.Rows(1)
Dim lCell As Range
Set lCell = .Resize(.Worksheet.Rows.Count - .Row + 1) _
.Find("*", , xlFormulas, , xlByRows, xlPrevious)
If lCell Is Nothing Then Exit Function ' empty range
Set RefColumns = .Resize(lCell.Row - .Row + 1)
End With
End Function
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Purpose: Returns the unique values of a one-column range in an array.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Function ArrUniqueColumnRange( _
ColumnRange As Range) _
As Variant
If ColumnRange Is Nothing Then Exit Function
Dim Data As Variant
Dim rCount As Long
With ColumnRange.Columns(1)
rCount = .Rows.Count
If rCount = 1 Then
ReDim Data(1 To 1, 1 To 1): Data(1, 1) = .Value
Else
Data = .Value
End If
End With
With CreateObject("Scripting.Dictionary")
.CompareMode = vbTextCompare
Dim Key As Variant
Dim r As Long
For r = 1 To rCount
Key = Data(r, 1)
If Not IsError(Key) Then
If Len(Key) > 0 Then
.Item(Key) = Empty
End If
End If
Next r
If .Count = 0 Then Exit Function ' only error values and/or blanks
ArrUniqueColumnRange = .Keys
End With
End Function