Cara, eu uso assim e funciona:
no evento columnclick do teu listview:
Private Sub lsv_ColumnClick(ByVal ColumnHeader As MSComctlLib.ColumnHeader)
OrdenaLvw lsv, ColumnHeader
End Sub
num modulo qualquer:
Public Sub OrdenaLvw(ByVal LVW As MSComctlLib.ListView, ByVal ColCabecalho As MSComctlLib.ColumnHeader)
'Ordena o ListView conforme a coluna especificada.
If LVW.SortKey = ColCabecalho.Index - 1 Then
LVW.SortOrder = IIf(LVW.SortOrder = lvwAscending, lvwDescending, lvwAscending)
Else
LVW.SortOrder = lvwAscending
End If
LVW.SortKey = ColCabecalho.Index - 1
LVW.Sorted = True
End Sub
Cada clique no cabeçalho de uma coluna do listview, ordena ascendente, um próximo clique na mesma coluna ordena descendente.
O porém é que tudo é considerado texto, portanto 20 vai vir antes de 3.
Uma solução que eu uso é criar mais colunas (que ficam ocultas) com os valores preenchidos com zero na frente até ficarem com 20 digitos cada e as datas preenchidas no formato yyyymmdd também em colunas ocultas. Daí eu uso uns ifs no evento columclick para identificar colunas com valores ou datas e ordenar pela correspondente (oculta).