jueves, 26 de octubre de 2017

VBA: Importar Calendario desde Outlook a Excel

Días atrás vimos como crear citas en el calendario de Outlook desde nuestra hoja de cálculo (ver).

Hoy veremos el proceso contrario, cómo recuperar información de las citas del calendario de Outlook y verlas listadas en nuestras hoja de cálculo.


Es una macro que emplea las mismas propiedades que en el proceso anterior comentado.

Como peculiaridad hemos incluido un 'filtro' por fecha de inicio de las Citas, para que devuelva únicamente aquellas que comiencen en el momento actual y hasta treinta días después.

Añadimos el siguiente código en un módulo estándar de nuestro proyecto de VB:

Sub ListaCitasdeOutlook()
Dim olApp As Object, olNS As Object, olCalendario As Object
Dim Cita As Object
Dim fila As Long

Dim FechaIni As Date, FechaFin As Date
FechaIni = Now         'el día actual
FechaFin = (Now + 30)  'hasta 30 días después

'Trabajamos sobre Outlook
Set olApp = CreateObject("Outlook.Application")
Set olNS = olApp.GetNamespace("MAPI")
'declaramos el objeto de la carpeta de los Calendarios
'(9 equivale a la carpeta del Calendario)
Set olCalendario = olNS.GetDefaultFolder(9)
'Ordenamos las Citas por Fecha de Inicio
Set misCitas = olCalendario.Items
misCitas.Sort "[Start]", False

'cabecera en nuestra hoja de cálculo
Range("A1:L1").Value = Array("Asunto", "Fecha-Hora Inicio", "Fecha-Hora fin", "Cuerpo", _
    "Duración(minutos)", "Ubicación", "Categoria", "Organizador", _
    "Asitentes invitados", "Asistentes opcionales", "Mostar como", "Todo el día")
'completamos los datos desde la fila 2 de la hoja seleccionada
fila = 2
'recorremos todas las citas del calendario
For Each Cita In misCitas
    If Cita.Start >= FechaIni And Cita.Start <= FechaFin Then
        Cells(fila, "A").Value = CStr(Cita.Subject)     'Asunto
        Cells(fila, "B").Value = Cita.Start             'Fecha + Hora Inico
        Cells(fila, "C").Value = Cita.End               'Fecha + Hora Fin
        Cells(fila, "D").Value = Cita.Body              'Cuerpo o texto
        Cells(fila, "E").Value = Cita.Duration          'Duración
        Cells(fila, "F").Value = Cita.Location          'Ubicación
        Cells(fila, "G").Value = Cita.Categories        'Categoria
        Cells(fila, "H").Value = Cita.Organizer         'Organizador
        Cells(fila, "I").Value = Cita.RequiredAttendees 'Asistentes
        Cells(fila, "J").Value = Cita.OptionalAttendees 'Asistentes
        Cells(fila, "K").Value = Cita.BusyStatus        'Tipo de estado
        '0-Disponible, 1-Provisional, 2-Ocupado, 3-Fuera de la oficina o 4-Trabajando en otro lugar
        Cells(fila, "L").Value = Cita.AllDayEvent       'marcado como evento de Todo el día
        
        'preparamos para siguiente fila
        fila = fila + 1
    End If
Next Cita

MsgBox "Proceso finalizado"
'liberamos memoria
Set Cita = Nothing
Set olCalendario = Nothing
Set olNS = Nothing
Set olApp = Nothing
End Sub

Tras ejecutar nuestra macro veremos la lista de citas...

martes, 24 de octubre de 2017

Alargar las barras de error hasta los ejes

Veremos hoy un sencillo truco que nos permitirá extender o alargar hasta los ejes (vertical y horizontal primarios) las barras de error; consiguiendo un aspecto como el de la imagen siguiente:

Alargar las barras de error hasta los ejes



Como se puede observar en el ejemplo hemos construido un gráfico de dispersión con dos series de datos,
y empleando el truco que contaremos a continuación hemos conseguido prolongar las barras de datos hasta los ejes primarios, haciendo más fácil determinar su posición de coordenadas.


Comencemos pues a partir de nuestros datos en A1:D3.
Sin seleccionar ningún dato insertamos un gráfico de dispersión.
Accedemos a la opción de Seleccionar datos (desde la cinta de opciones o haciendo clic derecho sobre el gráfico).
Se abrirá la ventana diálogo para seleccionar el origen de los datos y presionaremos el botón de Agregar nueva serie.

La primera serie será para el 'Concepto A' para lo cual indicaremos como valores de X la celda A3 y como valores de Y la celda B3

Alargar las barras de error hasta los ejes



De forma similar agregamos la segunda serie para el 'Concepto B', indicando como valores de X la celda C3 y como valores de Y la celda D3

Alargar las barras de error hasta los ejes



Ajustamos las escalas de ambos ejes para que vayan de 0 hasta 50.
Cambiamos el Título del gráfico y añadimos la Leyenda en la parte inferior.
Tendremos esto:

Alargar las barras de error hasta los ejes



Nos queda los últimos pasos.
Ahora añadimos las Barra de error verticales y horizontales a las dos series, de tipo Porcentaje.
Lo podemos hacer desde el gráfico o desde la cinta de opciones. En la Barra de herramientas del gráfico Agregamos elemento de gráfico > Barras de error > Porcentaje

Alargar las barras de error hasta los ejes



Ahora seleccionamos, una a continuación de la otra, las Barras de error horizontales y cambiamos las opciones de:
- Dirección a Menos
- Cuantía de error - Porcentaje a 100%

Alargar las barras de error hasta los ejes



De forma similar para las Barras de error verticales donde cambiamos las opciones de:
- Dirección a Menos
- Cuantía de error - Porcentaje a 100%

Alargar las barras de error hasta los ejes



Y listo, tenemos nuestros puntos representados en el gráfico, con unas líneas que se extienden hasta los ejes, facilitando la lectura...

jueves, 19 de octubre de 2017

VBA: Rellenar Citas del Calendario de Outlook desde Excel

En la macro de hoy veremos como trasladar datos recogidos en una hoja de Excel hacia nuestro calendario de Outlook.
En concreto para nuestro ejemplo necesitamos una hoja en nuestro Libro de Excel llamada 'xlsCalendario' y un calendario en Outlook llamado 'Excelforo' (obviamente podrás ajustar ambas cosas posteriormente sobre el código).

Advertir además que esta macro tiene en cuenta la existencia de varías cuentas de Outlook gestionadas al mismo tiempo, y dentro de cada cuenta disponemos de las carpetas estándar: Entrantes, Enviados, ..., Calendario, etc.
Es importante saber que Outlook se autogestiona basándose en un sistema de Carpetas y Subcarpetas, donde poder localizar la diferente información.


Nuestro objetivo, por tanto, consiste en crear, desde la información contenida en celdas de Excel, diferentes Citas en el Calendario Outlook, completando información requerida habitualmente al generar una Nueva cita.

VBA: Rellenar Citas del Calendario de Outlook desde Excel



Mis datos a trasladar desde Excel a Outlook:

VBA: Rellenar Citas del Calendario de Outlook desde Excel



En concreto los campos con los que vamos a crear nuestras citas son:
Asunto
Dia Inicio - Hora Inicio
Dia Finalización - Hora Finalización
Cuerpo o Texto de la Cita
Ubicación
Categoría
Estado/Mostrar como:
Todo el día


Añadimos el siguiente código en un módulo estándar de nuestro proyecto de VB:

Sub AñadirCitas_a_Calendario_Outlook()
'trasladamos citas desde Excel hacía el Calendario de Outlook

Dim olApp As Object
Dim olNs As Object
Dim olCarpetas As Object, olSubcarpetas As Object
Dim olCalendarios As Object
Dim objCita As Object

Dim sh As Worksheet
Dim i As Long, UF As Long

On Error Resume Next
'Creamos el objeto para la aplicación MS Outlook y abrimos
Set olApp = GetObject(, "Outlook.Application")
If olApp Is Nothing Then Set olApp = CreateObject("Outlook.Application")
On Error GoTo 0

'determinamos cuál es la última fila con datos
Set sh = Sheets("xlsCalendario")
UF = sh.Cells(sh.Rows.Count, "A").End(xlUp).Row

If Not olApp Is Nothing Then
    'Inicia una sesión de usuario en MAPI
    Set olNs = olApp.GetNamespace("MAPI")
    olNs.LogOn
    
    'buscamos, con el doble bucle, entre todas las carpetas de Outlook
    'y entre todos los Calendarios existentes el que se llame 'Excelforo'
    For Each olCarpetas In olNs.Folders
        For Each olSubcarpetas In olCarpetas.Folders
        ''''''''
        If olSubcarpetas.Name = "Calendario" Then
        For Each olCalendarios In olSubcarpetas.Folders
             'con el nombre de nuestro Calendario!!
            If olCalendarios.Name = "Excelforo" Then
                'y recorremos todos los datos de la hoja de cálculo
                For i = 2 To UF
                    'Generamos una nueva cita
                    Set objCita = olCalendarios.Items.Add(1)
                    'y la completamos con la info de la hoja en Excel
                    With objCita
                        'el Asunto
                        .Subject = sh.Range("A" & i).Value
                        'la Hora de Inicio
                        .Start = CDate(sh.Range("B" & i).Value) & Chr(32) & CDate(sh.Range("C" & i).Value)
                        'la Hora de finalización
                        .End = CDate(sh.Range("D" & i).Value) & Chr(32) & CDate(sh.Range("E" & i).Value)
                        'el Texto o Cuerpo de la cita
                        .Body = sh.Range("F" & i).Value
                        'la Ubicación de la cita
                        .Location = sh.Range("G" & i).Value
                        'la categoría que le asignamos
                        .Categories = sh.Range("H" & i).Value
                        'Mostrar como: 0-Disponible, 1-Provisional, 2-Ocupado, 3-Fuera de la oficina o 4-Trabajando en otro lugar
                        .BusyStatus = sh.Range("I" & i).Value
                        'si activamos una cita de Todo el día
                        .AllDayEvent = sh.Range("J" & i).Value
                        '.ReminderSet = True        'si queremos tener activa el recordatorio (15 minutos antes, por defecto)
                         .Save   'guardamos la cita
                    End With
                Next i

                'si hemos dado en el bucle con el Calendario buscado
                'salimos de éste (dejamos de buscarlo)
                Exit For
            End If
           
        Next olCalendarios
        End If
        Next olSubcarpetas
    Next olCarpetas
End If

'liberamos memoria de los objetos definidos
Set olApp = Nothing
Set olNs = Nothing
Set olStore = Nothing
Set olCal = Nothing
Set objAppt = Nothing
Set xlSheet = Nothing
Exit Sub
End Sub



El resultado tras la ejecución es el esperado:

VBA: Rellenar Citas del Calendario de Outlook desde Excel



Como observamos se crean las citas en nuestro Calendario, incluyendo todas las propiedades definidas...

martes, 17 de octubre de 2017

VBA: El Scroll en las macros de Excel

En muchas ocasiones, seguro nos ha pasado a todos, al emplear el asistente de grabación de macros y hacer uso de la rueda del ratón se ha activado el Scroll y nos deja grabado en nuestro procedimiento una línea similar a esta....
ActiveWindow.SmallScroll Down:=45

Lo que significa este instrucción y otras posibilidades de este método es de lo que vamos a hablar hoy.


Veamos algunos usos en una macro añadida dentro de un módulo estándar de nuestro proyecto de VB:

Sub El_Scroll_en_VBA_Excel()
'activamos la hoja 1 de nuestro libro de trabajo
ThisWorkbook.Sheets(1).Activate

''''''''''''''''''''''''''''''''''''''''''''''''''''''
'Opciones para situarse concretamente en la ventana activa
'Hacemos Scroll vertical y horizontal hasta la fila 1 y columna 1
ActiveWindow.ScrollRow = 1      'indicamos el número de la fila destino
ActiveWindow.ScrollColumn = 1   'indicamos el número de la columna destino
MsgBox ActiveWindow.VisibleRange.Cells(1, 1).Address

'Hacemos Scroll vertical y horizontal hasta la fila 2 y columna 2
ActiveWindow.ScrollRow = 2
ActiveWindow.ScrollColumn = 2
MsgBox ActiveWindow.VisibleRange.Cells(1, 1).Address

'... o hacia la celda E13
'(que se quedará en la parte superior izquierda de la ventana activa)
ActiveWindow.ScrollRow = 13
ActiveWindow.ScrollColumn = 5
MsgBox ActiveWindow.VisibleRange.Cells(1, 1).Address
''''''''''''''''''''''''''''''''''''''''''''''''''''''
'Opciones para desplazarse desde donde estemos
'Scroll hacia abajo de tres filas (desde donde estemos)
ActiveWindow.SmallScroll Down:=3
MsgBox ActiveWindow.VisibleRange.Cells(1, 1).Address

'Scroll de tres columnas hacia la izquierda.
ActiveWindow.SmallScroll ToLeft:=2
MsgBox ActiveWindow.VisibleRange.Cells(1, 1).Address
''''''''''''''''''''''''''''''''''''''''''''''''''''''
'También podemos emplear el Scroll dentro de los distintos paneles
Range("D8").Select  'seleccionamos la celda D8
'aplicamos la división de la ventana en varios 'paneles'
'No confundir Dividir con Inmovilizar paneles!!
ActiveWindow.Split = True
'nos desplazamos con el Scroll hacia la fila 10 y columna 10 (col J) del cuarto Panel
'Paneles numerado de izquierda a derecha y de arriba abajo
'1--2
'3--4
ActiveWindow.Panes(4).ScrollRow = 10
ActiveWindow.Panes(4).ScrollColumn = 10
MsgBox ActiveWindow.Panes(4).VisibleRange.Cells(1, 1).Address

'Eliminamos la división
ActiveWindow.Split = False
End Sub



Como hemos comprobado tenemos algunas propiedades interesantes:
1-ScrollRow y ScrollColumn que desplazan el scroll, en su parte superior izquierda a la fila y/o columna que indiquemos.
2-SmallScroll con sus opciones: Down, Up, ToLeft y ToRight. Que nos desplazan desde nuestra posición actual hacia la dirección indicada.

Por otra parte, se incluye al final de nuestra macro ejemplo, el uso del objeto Pane que nos permitirá controlar el Scroll dentro de los diferentes paneles existentes en nuestra hoja.
Hemos dividido la ventana empleado la propiedad .Split.


Para cerciorarse del correcto movimiento del Scroll entre las celdas de la hoja, he incorporado un MsgBox que muestre la dirección de la celda superior izquierda de lo que estamos viendo... para lo cual usamos otra propiedad:
.VisibleRange
para trabajar sobre lo que estamos viendo en cada momento.

jueves, 12 de octubre de 2017

VBA: Reemplazar en PowerPoint desde Excel.

Hoy, en respuesta a la cuestión lanzada por un lector, respecto a la manera de reemplazar textos, palabras o caracteres en una diapositiva de PowerPoint desde Excel, aprenderemos algunos métodos sencillos.

Partimos de la siguiente diapositiva (en una Presentación ya creada), con unos objetos insertados.
En concreto me interesa trabajar sobre el Cuadro de texto...

VBA: Reemplazar en PowerPoint desde Excel.


Como se observa tenemos el mismo texto escrito en dos objetos... sin embargo, en todo momento trabajaremos única y exclusivamente sobre el cuadro de texto (llamado 'CuadroTexto1').

Insertamos nuestra macro en un módulo estándar de nuestro proyecto de VB dentro de nuestro Libro de trabajo de Excel.

Sub ReemplazarDatoExcelaPPT()
Dim oPPT As Object, oPrsn As Object, oSlide As Object
Dim oShape1 As Object
Dim ficheroPPT As String

'La ruta completa de la presentación de PPT
ficheroPPT = "E:\excelforo\Excel_a_PPt.pptx"

'Definimos el objeto de trabajo PowerPoint
On Error Resume Next
Set oPPT = GetObject(, "PowerPoint.Application")
'controlamos posibles errores
If Err.Number <> 0 Then
    'y creamos el objeto, i.e., la presentación
    Set oPPT = CreateObject("PowerPoint.Application")
End If
Err.Clear
On Error GoTo 0
'hacemos visble la aplicación (voluntario.. pero recomendable)
oPPT.Visible = True

'Abriremos nuestra presentación
Set oPrsn = oPPT.Presentations.Open(ficheroPPT)
'accedemos a la primera diapositiva...
Set oSlide = oPrsn.Slides(1)
'...y nos centramos en las autoformas, cuadros de texto, etc
'(es importante tener controlado el destino previamente!!!)
Set oShape1 = oSlide.Shapes("CuadroTexto 1")

'nos centramos en la segunda palabra contenida en el cuadro de texto
Set rngTexto1 = oShape1.TextFrame.TextRange.Words(Start:=2, Length:=1)
'indicamos por que debemos cambiar esa palabra
rngTexto1.Text = "Palabra_Cambiada "

'otra posibilidad es cambiar caracteres...
'por ejemplo, cambiamos los 5 primeros caracters
Set rngTexto2 = oShape1.TextFrame.TextRange.Characters(Start:=1, Length:=5)
'indicamos por que debemos cambiar esa palabra
rngTexto2.Text = "Cambio Excel "

'y otra posibilidad mas empleadno Reemplazar...
'por ejemplo, cambiamos el texto 'PPT' por 'PowerPoint'
Set rngTexto3 = oShape1.TextFrame.TextRange.Replace(findwhat:="PPT", replacewhat:="PowerPoint")

'guardamos y cerramos la aplicación (PPT)
'oPPPrsn.Save
'oPPPrsn.Close
'oPPApp.Quit

'y liberamos memoria
Set oPPT = Nothing
Set oPrsn = Nothing
Set oSlide = Nothing
Set oShape1 = Nothing
Set rngTexto1 = Nothing: Set rngTexto2 = Nothing: Set rngTexto3 = Nothing
End Sub



Al ejecutar la macro comprobamos cómo solo se ve afectado el contenido del cuadro de texto, y de acuerdo a nuestras tres instrucciones.
Los métodos a emplear, de entre los tres descritos, dependerá de la precisión que necesitemos... o de la información previa sobre la ubicación/localización de los textos a cambiar.


El resultado:

VBA: Reemplazar en PowerPoint desde Excel.

martes, 10 de octubre de 2017

VBA: Rellenar objetos en Power Point desde celdas de Excel

La idea del post de hoy es comprobar cómo podemos rellenar, con el contenido de nuestras celdas de Excel, algunos objetos de una presentación de PowerPoint.

Primero tenemos que tener una presentación ya generada, con diferentes objetos ya insertados.
Veamos un ejemplo:

VBA: Rellenar objetos en Power Point desde celdas de Excel


En mi ejemplo dispongo de:
- un objeto Título
- un cuadro de texto (CuadroTexto 1)
- una autoforma (Elipse 1)
- un gráfico...

Es fundamental, para facilitar la labor, tener identificados los objetos sobre los que vamos a trabajar (volcar la información desde Excel).
Puedes mostrar el panel de selección para este fin.


En nuestra hoja de cálculo, dentro de un libro de trabajo, tenemos la información a trasladar:

VBA: Rellenar objetos en Power Point desde celdas de Excel


Es importante que sepas que, con lo que describiremos a continuación, no se traspasan los formatos dados en Excel... por ejemplo, si te fijas en la celda A5, en realidad, el valor de la celda es 1234!!, y no lo que mediante un formato personalizado se visualiza!!.
Esto vale para cualquier tipo de formato!!.


Añadimos el siguiente código en un módulo estándar de nuestro proyecto de VB:

Sub TrasladarDatoExcelaPPT()
Dim oPPT As Object, oPrsn As Object, oSlide As Object
Dim oShape1 As Object, oShape2 As Object
Dim ficheroPPT As String

'La ruta completa de la presentación de PPT
ficheroPPT = "E:\excelforo\Excel_a_PPt.pptx"

'Definimos el objeto de trabajo PowerPoint
On Error Resume Next
Set oPPT = GetObject(, "PowerPoint.Application")
'controlamos posibles errores
If Err.Number <> 0 Then
    'y creamos el objeto, i.e., la presentación
    Set oPPT = CreateObject("PowerPoint.Application")
End If
Err.Clear
On Error GoTo 0
'hacemos visble la aplicación (voluntario.. pero recomendable)
oPPT.Visible = True

'Abriremos nuestra presentación
Set oPrsn = oPPT.Presentations.Open(ficheroPPT)
'accedemos a la primera diapositiva...
Set oSlide = oPrsn.Slides(1)
'...y nos centramos en las autoformas, cuadros de texto, etc
'(es importante tener controlado el destino previamente!!!)
Set oShape1 = oSlide.Shapes("CuadroTexto 1")
Set oShape2 = oSlide.Shapes("Elipse 1")

'modificamos el texto del Título
oSlide.Shapes.Title.TextFrame.TextRange.Text = "Modificación realizada"
'y finalmente llevamos el contenido de la celda A1 de la hoja1 de nuestro libro
'al objeto 1 (al cuadro de texto)
oShape1.TextFrame.TextRange.Text = _
    ThisWorkbook.Sheets(1).Range("A1").Value
'y el contenido de la celda A5 a la Elipse de la diapositiva
oShape2.TextFrame.TextRange.Text = _
    ThisWorkbook.Sheets(1).Range("A5").Value

'guardamos y cerramos la aplicación (PPT)
'oPPPrsn.Save
'oPPPrsn.Close
'oPPApp.Quit

'y liberamos memoria
Set oPPT = Nothing
Set oPrsn = Nothing
Set oSlide = Nothing
Set oShape1 = Nothing
Set oShape2 = Nothing
End Sub



Estamos listos... Ya podemos ejecutar nuestra macro.
Podremos ver como se van produciendo los cambios hasta llegar al resultado final:

jueves, 5 de octubre de 2017

VBA: Un bucle FOR EACH inverso.

Todos conocemos el parámetro Step dentro de un bucle FOR...NEXT, con el que podemos controlar el sentido del recorrido al definirlo con un -1:
For x=10 to 1 Step -1
'nuestro código
Next c


Pero, ¿qué ocurre si nuestro bucle es un FOR EACH...NEXT???
Tenemos un problema ya que este bucle no admite el parámetro de salto o sentido Step... obligándonos el proceso a recorrer nuestro rango siempre en el mismo sentido de izquierda a derecha y de arriba abajo...
Nuestra meta: Recorrer el rango de derecha a izquierda y de abajo hacia arriba.


Para solucionar nuestro problema convertiremos nuestro bucle FOR EACH ...NEXT en un bucle FOR...NEXT, y para conseguir el recorrido inverso deseado usaremos la propiedad .Item del objeto Range.
Esta propiedad nos permite reconocer cada celda de un rango definido con un número índice único.


Veamos el efecto en los siguientes procedimientos:

Sub ForEach_INVERSO()
Dim lng As Long, x As Long
Dim rng As Range

'definimos el rango de estudio
Set rng = Range("A1:C5")
x = 0
For lng = rng.Cells.Count To 1 Step -1
    'rng(lng) es una forma abreviada para representar rng.Item(lng)
    'si el valor de la celda es par...
    If rng(lng).Value Mod 2 = 0 Then
        rng(lng).Interior.Color = vbRed
        'trasladamos la dirección a la columna E
        Cells(1 + x, "E").Value = rng(lng).Address
        x = x + 1
    End If
Next lng
End Sub
''''''''''''''''''''''''''''''''
''''''''''''''''''''''''''''''''
''''''''''''''''''''''''''''''''
Sub ForEach_DIRECTO()
Dim lng As Long, x As Long
Dim rng As Range

'definimos el rango de estudio
Set rng = Range("A1:C5")
x = 0
For Each celda In rng
    'rng(lng) es una forma abreviada para rng.item(lng)
    'si el valor de la celda es par...
    If celda.Value Mod 2 = 0 Then
        celda.Interior.Color = vbRed
        'trasladamos la dirección a la columna F
        Cells(1 + x, "F").Value = celda.Address
        x = x + 1
    End If
Next celda
End Sub



Si ejecutamos ambos procedimientos, el DIRECTO y el INVERSO, veremos...

VBA: Un bucle FOR EACH inverso.



Comprobamos en las columnas E y F el sendero tomado por uno y otro procedimiento...

martes, 3 de octubre de 2017

Valor más próximo por defecto o por exceso

Hoy proporcionaremos la manera de localizar el valor más próximo por exceso o por defecto (por encima o por debajo) dentro de un rango.

Todo nace a partir de la duda planteada por un usuario en u comentario:
[...]Como hago para buscar el valor mas aproximado ya sea superior o inferior.
Ejemplo:
Columna A
5
10
13
100
120
122
105
y si en otro base de datos tengo otra columna A con la siguiente información
14
101
119
Quiero que al hacer la búsqueda de esta ultima información me arroje el resultado mas próximo ya sea inferior o superior, es decir que para el 14 me arroje el 13, para el 101 me de el 100 y para el 119 me arroje el 120.
Como podrás ver en el primero y segundo identifico el 13 y 100 que son los valores mas próximo inferiores y en el ultimo caso identifico el mas próximo superior.[...]


Veamos el planteamiento:

Valor más próximo por defecto o por exceso



Nos fijamos en la fórmula matricial desarrollada:
=INDICE($B$2:$B$8;COINCIDIR(MIN(ABS($B$2:$B$8-D4));ABS($B$2:$B$8-D4);0))
la clave está en la regla matemática que nos dice que el valor más próximo es aquel valor mínimo entre las diferencias de los distintos valores y el valor buscado.
Esto es, con COINCIDIR localizamos la posición de la mínima diferencia en valor absoluto (entre los diferentes valores del rango y el valor buscado) y todas las diferencias, igualmente en valor absoluto, del dicho valor buscado con los valores del rango.

Por ejemplo, si buscamos el valor 14 entre los valores del rango, tendríamos como diferencias del valor absoluto:
9
4
1
86
106
108
111
donde el valor mínimo se consigue en el importe más próximo, en este caso el 13...

Valor más próximo por defecto o por exceso



Solucionando la cuestión del lector.

Otro problema relacionado sería conocer, para un valor buscado, cuáles son las cantidades por encima o por debajo (por exceso o por defecto) para dicho valor.
Para descubrir estos valores podemos optar al menos por dos métodos.

Una primer manera podría ser empleando matricialmente las funciones SI y MIN o MAX según el valor buscado (por defecto o por exceso):



Las primeras fórmulas matriciales serían.
1-para los valores por encima:
=MIN(SI($B$2:$B$8>=D4;$B$2:$B$8))
retornando el valro más bajo de entre los que sean mayores, es decir, justo el que esté por encima (o sea igual).
2-para los valores por debajo:
=MAX(SI($B$2:$B$8<=D4;$B$2:$B$8))
en este caso la fórmula nos devuelve de entre los valores inferiores (o iguales) el más alto, o lo que es lo mismo el dato que está justo por debajo.


Otra forma de conseguir el mismo dato, sin fórmulas matriciales, sería combinando las funciones CONTAR.SI y K.ESIMO.MAYO O K.ESIMO.MENOR.
1-para los valores por encima:
=K.ESIMO.MAYOR($B$2:$B$8;CONTAR.SI($B$2:$B$8;">="&D9))
contando el número de valores que existen por encima del valor buscado, para luego devolver el que se encuentra en esa posición (de mayor a menor) entre los valores ordenados... i.e., el valor justo por encima del buscado.
2-para los valores por debajo:
=K.ESIMO.MENOR($B$2:$B$8;CONTAR.SI($B$2:$B$8;"<="&D9))
contando el número de valores que existen por debajo del valor buscado, para luego devolver el que se encuentra en esa posición (de menor a mayor) entre los valores ordenados... i.e., el valor justo por debajo del buscado.


Dos formas de encontrar los valores que rodean el dato buscado...