Uso de la función Index and Match en Excel VBA VLookup

Tengo una fórmula de Excel que uso a menudo que hace un VLookup. Tiene un incrustado Index/Match que da el último valor numérico en la columna "M".
La fórmula de la hoja de trabajo es esta:

=VLOOKUP(INDEX($M$10:$M75,MATCH(9.99999999999999E+307,$M$10:$M75)),Data,4)

Celular $M75 siendo la celda de la fila en la que se encuentra esta fórmula. Hay celdas numéricas, no numéricas y en blanco en la Columna M, pero las ID que quiero son siempre numéricas.

Así que estoy tratando de escribir una función personalizada que me permita simplemente escribir =current()

Esto es lo que tengo:

Function Current()
  Dim LookupRange As Variant
  Dim indexVar As Variant
  LookupRange = Range("$M$1:M" & ActiveCell.Row)
  indexVar = Application.Index(Range(LookupRange), Application.Match(9.99999999999999E+307, Range(LookupRange)))
  Current = Application.WorksheetFunction.VLookup(indexVar, Worksheets("Info").Range("Data"), 4)
End Function

He intentado usar diferentes tipos de variables (String, Long, Variant) pero parece que no puedo hacer que la función funcione.
No sé si esto es suficiente información, pero ¿alguien puede ver si me estoy perdiendo algo?
Solo consigo #VALUE!
Usando Excel 2013 en Windows 7

preguntado el 29 de septiembre de 13 a las 22:09

Antes de ir a VBA, ¿su función de Excel devuelve resultados correctos? -

Revise su código y determine 1) es el valor asignado a LookupRange de acuerdo? 2) es el valor asignado a indexVar ¿correcto? -

@ sam092 - Mi fórmula original funciona correctamente. -

@DavidZemens: My LookupRange muestra el rango correcto si lo convierto en una cadena. Y si convierto indexVar en una cadena y uso una macro para insertar una fórmula vLookup en una celda de mi hoja, me da el número de ID correcto. Pero las cadenas no funcionan cuando intento hacer Vlookup en VBA. -

Está bien, déjame probar algunas cosas... -

1 Respuestas

Hay algunos problemas con este código que no concuerdan con su descripción.

  • LookupRange es una matriz variante. Cuando pruebo esto, plantea un 1004 Method 'Range' of object '_Global' failed error en la asignación a indexVar.
  • Si yo Dim LookupRange As String según sus comentarios, también recibo un Type Mismatch error.

Como LookupRange debe ser un rango, lo declaro como un rango, y uso el Set palabra clave en la instrucción de asignación.

Set lookupRange = Range("$M$10:$M" & ActiveCell.Row)
  • Posible error tipográfico en su asignación a lookupRange. En su fórmula, originalmente usa $M$1, pero en la función que usas $M$10.

Si comienza este rango en $M$10e intente evaluar la fórmula en cualquier celda entre las filas 1-9, obtendrá un error.

En una nota relacionada, si no hay valores numéricos en el capítulo respecto a la lookupRange, esto devolverá un error, por ejemplo, poniendo Current() en la celda M2 hace un rango de búsqueda de M1:M2, donde no tengo datos numéricos.

enter image description here

No estoy seguro de cómo quiere manejar esto, pero mi respuesta incluye una forma de evitar ese error. Puede modificar según sea necesario. Finalmente:

  • Confiando en ActiveCell.Row parece una mala idea, ya que esta fórmula puede volver a calcular con resultados no deseados.

En su lugar, haga de este un argumento requerido para la fórmula, que luego puede llamar desde la hoja de trabajo como: =Current(Row()).

Poniéndolo todo junto, creo que esto debería funcionar, y proporciono un ejemplo/escape para el error de coincidencia no encontrada. :

Public Function Current(r As Long)
    Const bigNumber As Double = 9.99999999999999E+307
    Dim wsInfo As Worksheet: Set wsInfo = Worksheets("Info")
    Dim lookupRange As Range
    Dim indexVar As Long
    Dim myVal As Variant

    Set lookupRange = Range("$M$1:$M" & r)
    If Not Application.WorksheetFunction.Sum(lookupRange) = 0 Then
        indexVar = Application.Index(lookupRange, Application.Match(bigNumber, lookupRange))
        myVal = Application.WorksheetFunction.VLookup(indexVar, wsInfo.Range("Data"), 4)
    Else:
        myVal = "No numbers found in: " & lookupRange.Address
    End If
    Current = myVal

End Function

ACTUALIZAR DESDE COMENTARIOS

Puede añadir Application.Volatileaquí antes de las declaraciones de variables. Esto debería obligar a volver a calcular:

siempre que se produzca un cálculo en cualquier celda de la hoja de cálculo.

Sin embargo, esto no forzará el cálculo cuando los valores en otras hojas de trabajo (por ejemplo, su Worksheets("Info") es otra hoja de trabajo) cambio.

Para forzar el recálculo cada vez que activa la hoja que contiene el =Current(Row()) función, podría poner esto en el módulo de código de la hoja de trabajo:

Private Sub Worksheet_Activate()
    Me.Calculate
End Sub

Esto es probablemente lo más cerca que puede estar: de replicar el nativo VLOOKUP funcionalidad sin utilizar realmente un VLOOKUP fórmula.

Notas adicionales:

Favoreciendo las variables correctamente/fuertemente tipadas, declaro indexVar as Long y crea una variable de doble precisión para 9.99999999999999E+307 (es más fácil trabajar de esta manera). También creo una variable de objeto de hoja de trabajo, nuevamente, me resulta más fácil trabajar con ellos.

Respondido 14 Jul 15, 19:07

Eso funciona y me da la información correcta. Lo interesante es que no vuelve a calcular si el número que habría encontrado cambia. ¿Es esto debido al índice/coincidencia? - Brad

Se actualizará si entro en la celda, pero no por sí mismo como lo hacen otras funciones de Vlookup. ¿Esto se debe a que el índice/coincidencia solo se ejecuta una vez cuando se ingresa la función? - Brad

Esto no es un Vlookup función :) es simplemente usar el Vlookup para buscar un valor de desplazamiento coincidente. Agregaré algunos comentarios adicionales a mi respuesta para aclarar/sugerir lo que podría hacer. - david zemens

Si esto resuelve su problema, @Brad, marque la respuesta como "Aceptada". ¡Salud! - david zemens

Gracias por toda tu ayuda. Es extraño porque tengo una función que usa el mismo método vlookup, excepto que en lugar de calcular 'indexVar' con índice/coincidencia, le doy una celda que contiene una fórmula de índice/coincidencia. Y eso vuelve a calcular cada vez que hay un cambio. - Brad

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.