Macro Para Extraer Valores De Fecha Máximo y Mínimo
De nuevo en busca de un poco de ayuda por acá. Se trata de lo siguiente: tengo una hoja con dos columnas, en la columna "A" van las fechas y en la columna "B" los precios.
Quisiera extraer los valores máximos o mínimos entre dos fechas, según se especifique para un numero determinado de registros.
Es decir, en una celda escribo una fecha inicial, en otra una fecha final, en otra "mínimo": o "máximo", según convenga y en otra celda "5", estas celdas actuarían como filtro dando como resultado al ejecutar la macro un rango de fechas y precios atendiendo al filtro especificado.
Tengo Excel 2016
1 respuesta
este es el resultado de la macro
Y esta es la macro solo cambia las referencias A1, e1, e2, e4 y e5 por las referencias que estés usando
Sub filtrar() Dim funcion As WorksheetFunction Set DATOS = Range("a1").CurrentRegion Set funcion = WorksheetFunction fecha_i = Range("e1") fecha_f = Range("e2") parametro = UCase(Range("e4")) With DATOS cuenta = funcion.CountIfs(.Columns(1), ">=" & CDbl(fecha_i), .Columns(1), "<=" & CDbl(fecha_f)) fila = funcion.Match(CDbl(fecha_i), .Columns(1), 0) Set FECHAS = .Rows(fila).Resize(cuenta) If parametro = "MÍNIMO" Then Range("D5") = "VALOR MINIMO" Range("E5") = funcion.Min(FECHAS.Columns(2)) Else Range("D5") = "VALOR MÁXIMO" Range("E5") = funcion.Max(FECHAS.Columns(2)) End If End With Set DATOS = Nothing: Set FECHAS = Nothing Set funcion = Nothing End Sub
Gracias por su oportuna respuesta. La macro funciona, pero creo que la explicación que di no fue suficientemente clara. Es decir la macro me devuelve el el precio mas alto para el rango de fecha especificado; pero lo que yo pretendí exponer es que dado un rango de fechas y un numero de fechas determinado y un parámetro, me devolviera cuales son las fechas con sus respectivos precios. Adjunto un capture
Entonces prueba con esta macro
Sub filtrar() Dim funcion As WorksheetFunction Set DATOS = Range("a2").CurrentRegion Set funcion = WorksheetFunction fecha_i = Range("e2") fecha_f = Range("e3") parametro = UCase(Trim(Range("e5"))) dias = Val(Range("e4")) Set resultado = Range("g2").Resize(dias, 2) With DATOS cuenta = funcion.CountIfs(.Columns(1), ">=" & CDbl(fecha_i), .Columns(1), "<=" & CDbl(fecha_f)) fila = funcion.Match(CDbl(fecha_i), .Columns(1), 0) Set fechas = .Rows(fila).Resize(cuenta) If parametro = "MÍNIMO" Then For i = 1 To dias res = funcion.Small(fechas.Columns(2), i) fila = funcion.Match(res, fechas.Columns(2), 0) With resultado .Cells(i, 2) = res .Cells(i, 1) = fechas.Cells(fila, 1) .Cells(i, 1).NumberFormat = "dd/mm/yyyy" End With Next i Else For i = 1 To dias res = funcion.Large(fechas.Columns(2), i) fila = funcion.Match(res, fechas.Columns(2), 0) With resultado .Cells(i, 2) = res .Cells(i, 1) = fechas.Cells(fila, 1) .Cells(i, 1).NumberFormat = "dd/mm/yyyy" End With Next i End If End With Set DATOS = Nothing: Set fechas = Nothing Set funcion = Nothing End Sub
Gracias amigo James Bond. Solo un detalle. La parte que se refiere al parametro no pude hacerla funcionar.
Veo en tu macro una linea que se refiere a "If parámetro = "MÍNIMO" Then", pero la macro da el mismo resultado independientemente
que el valor de la celda correspondiente sea "Minimo" o "Maximo", lo cual no es lo que se busca.
Lo que se busca es que si el valor es "Minimo" devuelva x cantidad de resultados correspondientes a los precios minimos y sus fechas;
de igual forma si el valor que se escoge es "Máximo" x cantidad de resultados correspondientes a los precios máximos y sus fechas
Hay un detalle en mi maquina el mínimo y el máximo lo pone con acentos así mínimo, máximo, así que tuve que poner en la macro la condición if con MÍNIMO solo cambia en la macro este parámetro por MÍNIMO así con letras mayúsculas. Y con esto la macro debe responder
Saludos de nuevo. He estado trabajando con esta macro y me ha sido de mucha utilidad, pero me gustaría sacarle un poco mas. Se trata de lo siguiente: he agregado otras columnas a las fechas y he he creado 4 categorías de resultados, a saber el valor máximo superior, el valor máximo inferior, el valor mínimo superior y el valor mínimo inferior; siempre que se aplique el filtro descrito. He logrado que la modificación funcione, pero inconsistentemente.
Como no tengo suficientes cono
Sub MaxMax()
Range("q8:r26").Select
Selection.ClearContents
Dim funcion As WorksheetFunction
Set DATOS = Range("a8:a500").CurrentRegion
Set funcion = WorksheetFunction
fecha_i = Range("r1")
fecha_f = Range("r2")
parametro = UCase(Trim(Range("r4")))
dias = Val(Range("r3"))
Set resultado = Range("q7").Resize(dias, 2)
With DATOS
cuenta = funcion.CountIfs(.Columns(1), ">=" & CDbl(fecha_i), .Columns(1), "<=" & CDbl(fecha_f))
fila = funcion.Match(CDbl(fecha_i), .Columns(1), 0)
Set fechas = .Rows(fila).Resize(cuenta)
If parametro = "Minimo" Then
For i = 1 To dias
res = funcion.Small(fechas.Columns(2), i)
fila = funcion.Match(res, fechas.Columns(2), 0)
With resultado
.Cells(i, 2) = res
.Cells(i, 1) = fechas.Cells(fila, 1)
.Cells(i, 1).NumberFormat = "dd/mm/yyyy"
End With
Next i
Else
For i = 1 To dias
res = funcion.Large(fechas.Columns(3), i)
fila = funcion.Match(res, fechas.Columns(3), 0)
With resultado
.Cells(i, 2) = res
.Cells(i, 1) = fechas.Cells(fila, 1)
.Cells(i, 1).NumberFormat = "dd/mm/yyyy"
End With
Next i
End If
End With
Set DATOS = Nothing: Set fechas = Nothing
Set funcion = Nothing
Range("q7:r26").Select
ActiveWorkbook.Worksheets("MaxMin").Sort.SortFields.Clear
ActiveWorkbook.Worksheets("MaxMin").Sort.SortFields.Add2 Key:=Range("r7:r26") _
, SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
With ActiveWorkbook.Worksheets("MaxMin").Sort
.SetRange Range("q7:r26")
.Header = xlGuess
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
Range("r7:r26").Select
Selection.NumberFormat = "0.00000000"
Range("r7").Select
End Sub
Sub MaxMin()
Range("q32:r51").Select
Selection.ClearContents
Dim funcion As WorksheetFunction
Set DATOS = Range("a8:a500").CurrentRegion
Set funcion = WorksheetFunction
fecha_i = Range("r1")
fecha_f = Range("r2")
parametro = UCase(Trim(Range("r29")))
dias = Val(Range("r3"))
Set resultado = Range("q32").Resize(dias, 2)
With DATOS
cuenta = funcion.CountIfs(.Columns(1), ">=" & CDbl(fecha_i), .Columns(1), "<=" & CDbl(fecha_f))
fila = funcion.Match(CDbl(fecha_i), .Columns(1), 0)
Set fechas = .Rows(fila).Resize(cuenta)
If parametro = "Minimo" Then
For i = 1 To dias
res = funcion.Small(fechas.Columns(2), i)
fila = funcion.Match(res, fechas.Columns(2), 0)
With resultado
.Cells(i, 2) = res
.Cells(i, 1) = fechas.Cells(fila, 1)
.Cells(i, 1).NumberFormat = "dd/mm/yyyy"
End With
Next i
Else
For i = 1 To dias
res = funcion.Large(fechas.Columns(12), i)
fila = funcion.Match(res, fechas.Columns(12), 0)
With resultado
.Cells(i, 2) = res
.Cells(i, 1) = fechas.Cells(fila, 1)
.Cells(i, 1).NumberFormat = "dd/mm/yyyy"
End With
Next i
End If
End With
Set DATOS = Nothing: Set fechas = Nothing
Set funcion = Nothing
Range("q32:r51").Select
ActiveWorkbook.Worksheets("MaxMin").Sort.SortFields.Clear
ActiveWorkbook.Worksheets("MaxMin").Sort.SortFields.Add2 Key:=Range("r32:r51") _
, SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
With ActiveWorkbook.Worksheets("MaxMin").Sort
.SetRange Range("q32:r51")
.Header = xlGuess
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
Range("r32:r51").Select
Selection.NumberFormat = "0.00000000"
Range("r32").Select
End Sub
Sub MinMax()
Range("q56:r75").Select
Selection.ClearContents
Dim funcion As WorksheetFunction
Set DATOS = Range("a8:a500").CurrentRegion
Set funcion = WorksheetFunction
fecha_i = Range("r1")
fecha_f = Range("r2")
parametro = UCase(Trim(Range("r53")))
dias = Val(Range("r3"))
Set resultado = Range("q56").Resize(dias, 2)
With DATOS
cuenta = funcion.CountIfs(.Columns(1), ">=" & CDbl(fecha_i), .Columns(1), "<=" & CDbl(fecha_f))
fila = funcion.Match(CDbl(fecha_i), .Columns(1), 0)
Set fechas = .Rows(fila).Resize(cuenta)
If parametro = "Minimo" Then
For i = 1 To dias
res = funcion.Small(fechas.Columns(4), i)
fila = funcion.Match(res, fechas.Columns(4), 0)
With resultado
.Cells(i, 2) = res
.Cells(i, 1) = fechas.Cells(fila, 1)
.Cells(i, 1).NumberFormat = "dd/mm/yyyy"
End With
Next i
Else
For i = 1 To dias
res = funcion.Large(fechas.Columns(4), i)
fila = funcion.Match(res, fechas.Columns(4), 0)
With resultado
.Cells(i, 2) = res
.Cells(i, 1) = fechas.Cells(fila, 1)
.Cells(i, 1).NumberFormat = "dd/mm/yyyy"
End With
Next i
End If
End With
Set DATOS = Nothing: Set fechas = Nothing
Set funcion = Nothing
Range("q56:r75").Select
ActiveWorkbook.Worksheets("MaxMin").Sort.SortFields.Clear
ActiveWorkbook.Worksheets("MaxMin").Sort.SortFields.Add2 Key:=Range("r56:r75") _
, SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
With ActiveWorkbook.Worksheets("MaxMin").Sort
.SetRange Range("q56:r75")
.Header = xlGuess
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
Range("r56:r75").Select
Selection.NumberFormat = "0.00000000"
Range("r56").Select
End Sub
cimientos, clone la macro original para hacer una por cada categoría de resultados y cambie algunos valores, he aquí lo que hice:
Se entiende mejor si subes una pantalla con la información que agregaste y el resultado que quieres lograr.
Así como lo planteas es otra macro la que tiene que hacerse para que de los resultados como se muestra en la imagen
la macro hace 4 filtros a la vez y esta es la macro
Sub filtrar_maximos_minimos() inicio = Range("f2") Final = Range("f3") cantidad = Range("f4") Set datos = Range("a1").CurrentRegion datos.AutoFilter inicio = ">=" & Format(inicio, "mm/dd/yyyy") Final = "<=" & Format(Final, "mm/dd/yyyy") ActiveSheet.Range(datos.Address).AutoFilter Field:=1, Criteria1:= _ inicio, Operator:=xlAnd, Criteria2:=Final datos.SpecialCells(xlCellTypeVisible).Copy Destination:=Range("k1") Set tabla = Range("k1").CurrentRegion With tabla filas = .Rows.Count .Sort key1:=Range(.Columns(2).Address), order1:=xlDescending, Header:=xlYes End With datos.AutoFilter Range("e9").Resize(1000, 6).Clear Set tabla1 = Range("e9").Resize(cantidad, 2) Set tabla2 = Range("h9").Resize(cantidad, 2) Set tabla3 = tabla1.Rows(cantidad + 4).Resize(cantidad, 2) Set tabla4 = tabla2.Rows(cantidad + 4).Resize(cantidad, 2) tabla1.Value = tabla.Cells(2, 1).Resize(cantidad, 2).Value tabla2.Value = tabla.Cells(filas - cantidad + 1, 1).Resize(cantidad, 2).Value With tabla filas = .Rows.Count .Sort key1:=Range(.Columns(3).Address), order1:=xlDescending, Header:=xlYes End With With tabla3 .Columns(1).Value = tabla.Cells(2, 1).Resize(cantidad, 1).Value .Columns(2).Value = tabla.Cells(2, 3).Resize(cantidad, 1).Value .Cells(0, 1) = "PRECIO MINIMO MAS ALTO" End With With tabla4 .Columns(1).Value = tabla.Cells(2, 1).Resize(cantidad, 1).Value .Columns(2).Value = tabla.Cells(filas - cantidad + 1, 3).Resize(cantidad, 1).Value .Cells(0, 1) = "PRECIO MINIMO MAS BAJO" End With tabla.Clear Set tabla = Nothing: Set tabla1 = Nothing Set tabla2 = Nothing: Set tabla3 = Nothing: Set tabla4 = Nothing End Sub
- Compartir respuesta