这是一种非常通用的 depivot 方法,可以处理多个行/列标题。
在运行之前选择源表中的一个单元格(注意 - 这使用CurrentRegion
如果您的表有完全空白的行或列,那么将会失败)。
Sub UnpivotIt()
Dim numRowHeaders As Long, numColHeaders As Long
Dim numRows As Long, numCols As Long, rng As Range
Dim rngOut As Range, r As Long, c As Long, i As Long, n As Long
Dim arrIn, arrOut, outRow As Long
arrIn = Selection.CurrentRegion.Value
numRowHeaders = Application.InputBox("How many header rows?", Type:=1)
numColHeaders = Application.InputBox("How many header columns?", Type:=1)
Set rngOut = Application.InputBox("Select output (top-left cell)", Type:=8)
Set rngOut = rngOut.Cells(1) 'in case >1 cells selected
numRows = UBound(arrIn, 1)
numCols = UBound(arrIn, 2)
ReDim arrOut(1 To ((numRows - numRowHeaders) * (numCols - numColHeaders)), _
1 To (numRowHeaders + numColHeaders + 1))
outRow = 0
For r = (numRowHeaders + 1) To numRows
For c = (numColHeaders + 1) To numCols
'only copy if there's a value
If Len(arrIn(r, c)) > 0 Then
outRow = outRow + 1
i = 1
For n = 1 To numColHeaders 'copy column headers
arrOut(outRow, i) = arrIn(r, n)
i = i + 1
Next n
For n = 1 To numRowHeaders '...row headers
arrOut(outRow, i) = arrIn(n, c)
i = i + 1
Next n
arrOut(outRow, i) = arrIn(r, c) '...and the value
End If
Next c
Next r
rngOut.Resize(outRow, UBound(arrOut, 2)).Value = arrOut
End Sub