PowerQuery offers a more efficient solution than using a VBA script to transform your table.
- Select a cell within the source table and press Ctrl+T to convert it into a structured table (ListObject).
- On the Excel ribbon, navigate to Data > From Table/Range (if you skip the first step, this will automatically create a table for you).
- Edit the PowerQuery formula as shown below.
- Use the Save & Load option in the PowerQuery ribbon to output the results to a new worksheet.
let
Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
#"Changed Type" = Table.TransformColumnTypes(Source,{{"Sample", type text}, {"Index", type text}, {"Value", type number}}),
#"Pivoted Column" = Table.Pivot(#"Changed Type", List.Distinct(#"Changed Type"[Index]), "Index", "Value", List.Sum)
in
#"Pivoted Column"

If you prefer to use a VBA script instead
Option Explicit
Sub Demo()
Dim oDic1 As Object, oDic2 As Object, rngData As Range
Dim i As Long, j As Long, sKey As String
Dim arrData, arrTemp()
Set oDic1 = CreateObject("scripting.dictionary")
Set oDic2 = CreateObject("scripting.dictionary")
Set rngData = Sheets("Source").Range("A1").CurrentRegion ' change sheet name as needed
' load table into an array
arrData = rngData.Value
For i = LBound(arrData) + 1 To UBound(arrData)
sKey = arrData(i, 1)
If Not oDic1.exists(sKey) Then ' get unique list of Sample
oDic1(sKey) = ""
End If
sKey = arrData(i, 2)
If Not oDic2.exists(sKey) Then ' get unique list of IndexN
oDic2(sKey) = oDic2.Count + 1
End If
Next i
Dim iCol As Long: iCol = oDic2.Count
oDic1.RemoveAll
Dim iColIdx As Long
For i = LBound(arrData) + 1 To UBound(arrData)
sKey = arrData(i, 1)
If Not oDic1.exists(sKey) Then ' init. array for each sample
ReDim arrTemp(iCol)
arrTemp(0) = arrData(i, 1)
oDic1(sKey) = arrTemp
Else
arrTemp = oDic1(sKey)
End If
iColIdx = oDic2(arrData(i, 2))
arrTemp(iColIdx) = arrTemp(iColIdx) + arrData(i, 3) ' get sum
oDic1(sKey) = arrTemp
Next i
Sheets.Add ' creat new sheet for ouput
' populate header row
Range("A1") = "Sample"
Range("B1").Resize(1, iCol).Value = Application.Transpose(oDic2.keys)
' write output to sheet
Range("A2").Resize(oDic1.Count, iCol + 1).Value = Application.Transpose(Application.Transpose(oDic1.items()))
Set oDic1 = Nothing
End Sub
Microsoft documentation:
Range.Resize property (Excel)
Range.CurrentRegion property (Excel)
Dictionary object
Excel formulas (provided by @Mayukh Bhattacharya)
=PIVOTBY(A2:A29,B2:B29,C2:C29,SINGLE,,0,,0)