Private Type pointXY
  X  As Single
  Y  As Single
End Type
Private Sub calcPolygonArea_test()
  Debug.Print calcPolygonArea(100, 100, 100, 300, 300, 400, 400, 250, 300, 0)
  Debug.Print calcPolygonArea(300, 300, 300, 100, 0, 0, -100, 400)
  Debug.Print calcPolygonArea(50, 150, 200, 50, 350, 150, 350, 250, 250, 320, 200, 250, 150, 350, 100, 250)
  Debug.Print calcPolygonArea(100, 100, 300, 100, 400, 300, 100, 300)
End Sub
Function calcPolygonArea(ParamArray vertices()) As Single
  Dim t&, aX&, aY&, sX&, sY&, i&, u%, c As Integer, d%
  Dim p() As pointXY
 
  u = UBound(vertices) - 1
  If u < 4 Or u Mod 2 <> 0 Then
    calcPolygonArea = 0
    Exit Function
  End If
  u = (u + 2) / 2
  ReDim p(1 To u + 1)
  For i = 1 To u
    p(i).X = vertices(i * 2 - 2)
    p(i).Y = vertices(i * 2 - 1)
  Next
  p(i).X = vertices(0)
  p(i).Y = vertices(1)
  For i = 1 To u
    c = InOrOut(p, i)
    Select Case c
    Case 0:
    Case -1: t = t + (p(i).X + p(i + 1).X) * (p(i).Y - p(i + 1).Y)
    Case 1:
    End Select
  Next
  calcPolygonArea = VBA.Abs(t / 2)
End Function
Function InOrOut(p() As pointXY, ByVal index As Integer) As Integer
  'k = length(p)
  'Chýìc nãng xác ðiònh viò trí cuÒa ðiêÒm (p0.X, p0.Y) týõng ðôìi
  'ðêìn ðýõÌng bao khép kín ðýõòc xác ðiònh bõÒi n ðiêÒm võìi
  'toòa ðôò p (i), p (i), i = 1, 2, ..., k
  '
  'ÐiêÒm 1 phaÒi giôìng võìi ðiêÒm k
  'Giá triò hàm ðýõòc traÒ vêÌ ():
  '1: ðiêÒm nãÌm bên trong ðýõÌng viêÌn
  '-1: ðiêÒm nãÌm ngoài ðýõÌng viêÌn
  '0: ðiêÒm nãÌm trên ðýõÌng viêÌn
'************************************************* ********************
    Dim kross As Integer, i As Integer
    Dim pp As Single, k As Integer, p0 As pointXY
    k = UBound(p)
    If index > k Or k < 1 Then
      InOrOut = -10
      Exit Function
    End If
    p0 = p(index)
    'KhõÒi taòo hàm
    InOrOut = 0
    'KhõÒi taòo kross, môòt biêìn theo doÞi
    'bãÌng bao nhiêu lâÌn bán kính thãÒng ngang
    'doÌng bãìt ðâÌu taòi (p0.X, p0.Y) và theo chiêÌu dýõng (phía bên tay phaÒi)
    'hýõìng truòc x chãòn ðýõÌng bao
    '(ÐýõÌng bao có thêÒ có các ðiÒnh võìi góc lõìn hõn 180 ðôò)
    kross = 0
    'VoÌng qua tâìt caÒ các mãòt cuÒa ðýõÌng viêÌn
    For i = 1 To k - 1
        'Nêìu caònh giýÞa ðiÒnh i và i + 1 nãÌm hoàn toàn phía trên
        'hoãòc thâìp hõn ðiêÒm (p0.X, p0.Y), boÒ qua nó (không có ðiêÒm chãòn)
        If (p(i).Y > p0.Y And p(i + 1).Y > p0.Y) Or (p(i).Y < p0.Y And p(i + 1).Y < p0.Y) Then GoTo NextItem
        'Nêìu caònh nãÌm ngang, tránh tính toán ðiêÒm chãòn bãÌng nôòi suy
        'viÌ seÞ có môòt phép chia cho sôì không
        If p(i).Y = p(i + 1).Y Then
            'Nó phaÒi ðýõòc xác ðiònh nêìu ðiêÒm (p0.X, p0.Y) nãÌm trên ðoaòn ngang này
            If (p(i).X > p0.X And p(i + 1).X > p0.X) Or (p(i).X < p0.X And p(i + 1).X < p0.X) Then GoTo NextItem
            'Nêìu không, chúng ta ðaÞ hoàn tâìt!
            Exit For
        End If
        'Tính pp, toòa ðôò cuÒa ðiêÒm mà ðoaòn nôìi võìi
        'các caònh i và i + 1 và ðýõÌng thãÒng nãÌm ngang ði qua (p0.X, p0.Y) giao nhau
        pp = p(i).X + (p0.Y - p(i).Y) * ((p(i + 1).X - p(i).X) / (p(i + 1).Y - p(i).Y))
        'Dâìu cuÒa pp-p0.X xác ðiònh viò trí cuÒa ðiêÒm chãòn so võìi (p0.X, p0.Y)
        If pp - p0.X > 0 Then
            'Ðánh chãòn õÒ bên phaÒi: bôò ðêìm gia tãng (nhýng chiÒ khi ðiêÒm ðánh chãòn không nói dôìi
            'trên ðiÒnh ðâÌu tiên, ðêÒ tránh ðêìm cùng môòt ðiêÒm chãòn hai lâÌn!)
            If p0.Y <> p(i).Y Then kross = kross + 1
        ElseIf pp - p0.X = 0 Then
            Exit For
        End If
        'Nêìu chôìt chãòn nãÌm õÒ bên trái, không thýòc hiêòn hành ðôòng nào và tiêìp tuòc
NextItem:
    Next
    'Nêìu sôì ðiêÒm giao nhau là sôì chãÞn, ðiêÒm (p0.X, p0.Y) nãÌm ngoài ðýõÌng bao
    'Nêìu nó kyÌ quãòc thiÌ nó nãÌm bên trong
    InOrOut = IIf(kross Mod 2 = 0, -1, 1)
End Function