(1) If by dynamic you mean that the data will increase in number but the same 8 codes will always be used then a single formula works.
The following function is the same as before but allows you to keep the data where it is, and it accounts for all 8 data types.
=SUM(IFERROR(INDEX(B2:J2,,MATCH(M3,B3:J3,0)),0),IFERROR(INDEX(B2:J2,,MATCH(M4,B3:J3,0)),0),IFERROR(INDEX(B2:J2,,MATCH(M5,B3:J3,0)),0),IFERROR(INDEX(B2:J2,,MATCH(M6,B3:J3,0)),0),IFERROR(INDEX(B2:J2,,MATCH(M7,B3:J3,0)),0),IFERROR(INDEX(B2:J2,,MATCH(M8,B3:J3,0)),0),IFERROR(INDEX(B2:J2,,MATCH(M9,B3:J3,0)),0))/COUNTA(M3:M100)
(2) If the data increases with many new codes and you don't want to be adding a "IFERROR(INDEX(B2:J2,,MATCH(M3,B3:J3,0)),0)" for each new possible code then I think a macro is the best solution.
The following is a code that will allow for any number of new codes and an increase in the data set. I took the liberty of assuming that the data continues on to the right of the existing data and so I moved your output range
exactly 4 rows down.
Code:
Sub AverageFinder()
Dim CriteriaCounter As Integer
Dim RangeCounter As Integer
Dim RunningTotal As Double
Dim RunningCount As Integer
Dim i As Integer
Dim j As Integer
RunningTotal = 0
RunningCount = 0
CriteriaCounter = Application.WorksheetFunction.CountA(Range("M7:M100"))
RangeCounter = Application.WorksheetFunction.CountA(Range("B3:HH3"))
For i = 1 To CriteriaCounter
For j = 1 To RangeCounter
If Cells(i + 6, 13).Value = Cells(3, j + 1).Value Then
RunningTotal = RunningTotal + Cells(2, j + 1).Value
RunningCount = RunningCount + 1
End If
Next j
Next i
Range("N7").Value = RunningTotal / RunningCount
End Sub
(3) If you are trying to achieve something else entirely I suggest you be extremely descriptive.