miércoles, 3 de junio de 2015

VBA: Una función personalizada para devolver datos ordenados.

La idea del trabajo de hoy es obtener un listado ordenado (en sentido descendente-de mayor a menor-) mediante una UDF, o función personalizada en VBA.
Supongamos el siguiente origen de información, del cual queremos obtener un listado a parte con aquellos registros cuyo número de unidades sea mayor, por ejemplo, los cinco primeros.. aunque, con esta personalización podrías obtener aquellas posiciones que deseáramos.



Construiremos una función que realice por nostros la búsqueda de los valores que necesitemos, la posterior ordenación interna, y acabe devolviendo el valor ya ordenado...
Lo interesante es que apoyándonos en nuestro propio Tipo de datos (ver cómo) desplegaremos no solo los valores numéricos ('unidades') si no también el resto de datos de esos registros...


El proceso completo de la función es:
1- carga de datos en nuestra Array (matriz)
2- ordenación de esos datos siguiendo el modelo burbuja (ver)
3- la función acaba devolviendo un dato según el argumento 'tipo' seleccionado.. quien retornará una de las propiedades del Type.


Insertamos el código de la función en un módulo estándar de nuestro proyecto de VBA desde el editor de VB:

Type Referencias
'definimos un tipo de dato personalizado con tres propiedades....
    Uds As Integer
    NumRef As String
    DSArt As String
End Type
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Function ordenado(rng As Range, orden As Integer, tipo As String)
'el argumento tipo nos dirigirá hacia una o otra propiedad de nuestro tipo de dato
'tipo puede ser: 'producto', 'descripcion' o 'unidades'

Application.Volatile
'contamos celdas con datos, no vacías...
Num = Application.WorksheetFunction.CountA(rng)
Dim matriz() As Referencias
ReDim matriz(1 To Num) As Referencias

'rellenamos nuestra matriz con los valores con datos
x = 1
For Each celda In rng
    If celda.Value <> 0 Then
        matriz(x).Uds = Val(celda.Value)
        matriz(x).NumRef = celda.Offset(0, -2).Value
        matriz(x).DSArt = celda.Offset(0, -1).Value
        x = x + 1
    End If
Next celda

'reordenarmos empleando el método de burbuja
Dim strTemp As Referencias
Dim i As Long, j As Long
Dim lngMin As Long, lngMax As Long
lngMin = 1
lngMax = x - 1
'ordenado por Burbuja
For i = lngMin To lngMax - 1
  For j = i + 1 To lngMax
    If Val(matriz(i).Uds) < Val(matriz(j).Uds) Then
      'para unidades
      strTemp.Uds = Val(matriz(i).Uds)
      matriz(i).Uds = Val(matriz(j).Uds)
      matriz(j).Uds = Val(strTemp.Uds)
      'para Cod Artículo
      strTemp.NumRef = matriz(i).NumRef
      matriz(i).NumRef = matriz(j).NumRef
      matriz(j).NumRef = strTemp.NumRef
      'para Descripción
      strTemp.DSArt = matriz(i).DSArt
      matriz(i).DSArt = matriz(j).DSArt
      matriz(j).DSArt = strTemp.DSArt
    End If
  Next j
Next i

'devolvemos un dato u otro según el argumento 'tipo'
If tipo = "unidades" Then
    ordenado = matriz(orden).Uds
ElseIf tipo = "descripcion" Then
    ordenado = matriz(orden).DSArt
ElseIf tipo = "producto" Then
    ordenado = matriz(orden).NumRef
Else
    ordenado = "error"
End If
End Function

En la celda F3 introduciremos la función: =ordenado($C$3:$C$21;$E3;F$2) donde alimentamos los argumentos creados en nuestra UDF. primer argumento: rango de los valores (campo unidades). segundo argumento: posición deseada; recuerda el orden es descendente. Posición 1 el mayor valor, etc.. tercer argumento: dato deseado (unidades, producto o descripción) Como veíamos en la imagen de más arriba, el orden obtenido responde a lo que pretendíamos...

No hay comentarios:

Publicar un comentario en la entrada