viernes, 2 de septiembre de 2011

VBA: La función MsgBox en una macro.

Es frecuente encontrarnos en algunas de nuestra macros, especialmente cuando queremos interrelacionarnos con la ejecución de ésta, esta función MsgBox, mediante la cual se muestra un mensaje en un cuadro de diálogo, a la espera de que el usuario pulse algunos de los botones habilitados.
¿Cuáles son los parámetros de esta función y qué podemos esperar de ella?.
Veamos en primer lugar la Sintáxis:
MsgBox(Prompt[, Buttons][, Title][, Helpfile, Context])
donde el Prompt se mostrará en nuestro Cuadro diálogo como parte del texto,
el siguiente parametro Buttons corresponde a alguno o varios de las siguientes posibilidades (mostraré los más habituales):
  • VbOKOnly: Muestra un botón 'Aceptar'
  • VbOKCancel:Muestra los botones 'Aceptar' y 'Cancelar'
  • VbAbortRetryIgnore: Muestra los botones 'Anular', 'Reintentar' e 'Ignorar'
  • VbYesNoCancel: Muestra los botones 'Sí', 'No' y 'Cancelar'
  • VbYesNo: Muestra los botones 'Sí' y 'No'
  • VbRetryCancel: Muestra los botones 'Reintentar' y 'Cancelar'.
  • VbCritical: Muestra el icono de mensaje crítico.
  • VbQuestion: Muestra el icono de pregunta de advertencia.
  • VbExclamation: Muestra el icono de mensaje de advertencia.
  • VbInformation: Muestra el icono de mensaje de información.

el parametro de Title añade en la cabecera del cuadro diálogo el texto deseado; y por último Helpfile que identifica cuál es el archivo de 'Ayuda' asociado a nuestro Cuadro diálogo (si especificamos Helpfile, también se debe especificar Context).

La interacción con este cuadro diálogo se realizará a través de las respuestas obtenidas tras pulsar los botones, ya que cada respuesta pulsada (cada botón pulsado) devuelve alguno de estos valores:
  1. Si pulsamos el botón 'Aceptar', vbOK
  2. Si pulsamos el botón 'Cancelar', vbCancel
  3. Si pulsamos el botón 'Anular', vbAbort
  4. Si pulsamos el botón 'Reintentar', vbRetry
  5. Si pulsamos el botón 'Ignorar', vbIgnore
  6. Si pulsamos el botón 'Sí', vbYes
  7. Si pulsamos el botón 'No', vbNo


Pero veámoslo con un sencillo ejemplo.
Supongamos que deseamos generar un proceso que nos pregunte al inicio de éste, si deseamos Continuar con el resto de nuestra macro; por hacerlo sencillo, sólo queremos que se nos cambie el color de fondo de la celda A1 de la 'Hoja1' a amarillo, y que además escriba en dicha celda, en rojo, el texto 'macro 'amarillo' completada'.

Sub amarillo()
'fondo de la celda amarillo
Sheets("Hoja1").Range("A1").Interior.Color = 65535
'color de la fuente rojo
Sheets("Hoja1").Range("A1").Font.Color = -16776961
Sheets("Hoja1").Range("A1").Value = "macro 'amarillo' completada"    
End Sub



El trabajo consistirá en asignar, con la función MsgBox, los botones 'Sí' y 'No'.
Nuestro código a incluir en un módulo del Editor de VBA será:

Sub CuadroDialogo()
'www.excelforo.blogspot.com
Dim respuesta As Variant
'asignamos una variable a la función MsgBox
respuesta = MsgBox("Texto del Prompt... ¿continuamos con la macro?", _
vbYesNo, "Título del Cuadro diálogo")
'Evaluamos la respuesta dada sobre el cuadro diálogo
If respuesta = vbYes Then amarillo Else Exit Sub
'si pulsamos el botón 'Sí' entonces ejecutamos la macro 'amarillo',
'si pulsamos 'No' entonces terminamos y salimos de la macro.
End Sub



Al ejecutar la macro CuadroDialogo nos aparecerá:


Sabiendo que si pulsamos 'Sí' nuestra macro 'CuadroDialogo' llamará o ejecutará la macro 'amarillo', mientras que si pulsamos el 'No' directamente saldremos del procedimiento Sub, acabando el proceso.

26 comentarios:

  1. Gracias x la explicacion, muy muy util :)

    ResponderEliminar
  2. Necesito saber algo, si quiero hacer un menú tal como estos de botones pero que despliegue unos botones definidos por mi ¿Cómo lo haría?

    ResponderEliminar
  3. Es decir boton 1 :Ingresar datos, boton 2:realizar calculos,.... etc

    ResponderEliminar
    Respuestas
    1. Hola que tal, Samuel0579??
      espero estés bien.
      En el caso que planteas, con botones tan concretos, tendrías que crearte tu propio UserForm, añadiendo un Label para el texto del prompt, es decir para que aparezca el mensaje que deeemos, y luego tantos CommandButton como requieras:
      1 - Ingresar datos
      2 - Realizar cálculos
      etc

      Pero ojo, por que luego tendrías que añadir el código que realizara esas acciones asociadas.
      Puede leer algo al respecto en
      http://excelforo.blogspot.com.es/2011/12/crear-un-formulario-userform-en-excel-i.html
      y en
      http://excelforo.blogspot.com.es/2011/12/crear-un-formulario-userform-en-excel-y.html
      Slds

      Eliminar
  4. Muchas gracias. Era exactamente lo que necesitaba, ya tengo una macro con las acciones a realizar, solo me falta enlazar todo con la respuesta de cada boton al programa original. Imaginate lo desesperado que andaba por eso que habia hecho un menu que funcionaba introduciendo 1, 2 o 3 en un inputbox (Arcaico no? jeje). De verdad muchas gracias

    ResponderEliminar
    Respuestas
    1. Bueno, Samuel
      Arcaico o no, lo importante era que funcionase.
      Me alegro haberte podido ayudar.
      Slds

      Eliminar
  5. Tengo una macro asignada a un botón ActiveX y le quiero poner la función vbokcancel pero cuando le doy a cancelar me ejecuta la macro igualmente.
    La macro se llama "Confirma", el texto del mensaje es: deseas confirmar la factura? con un icono de advertencia y con el titulo de la ventanilla...Mensaje de advertencia.
    Soy nuevo en esto, me podríais poner paso a paso tal y como lo tengo que poner pues me parece un poco lioso todavía, un saludo.

    ResponderEliminar
    Respuestas
    1. Hola Fran,
      creo puedes referirte a esto:

      Sub confirma()

      MsgBox "Deseas confirmar la factura?", vbOKCancel + vbExclamation, "Mensaje de Advertencia"

      End Sub

      Saludos

      Eliminar
    2. Hola de nuevo, he puesto todo esto entre el inicio (Private) y fin de la acción (End sub) y me da error de compilación, se esperaba end sub!.
      Yo lo tenia mas menos igual solo que el nombre de la macro lo tenia antes de cerrar con end sub... me funcionaba pero los botones aceptar y cancelar me funcionaban igual, ejecutaban la macro cuando yo lo que quería es que al cancelar no hiciera nada y quedara todo como estaba...de la forma que me indicas no me deja o no se ponerlo bien a lo mejor.
      Haber si puedes echarme una manilla pues estoy pez en esto, muchísimas gracias por atender me, un saludo.

      Eliminar
    3. Fran,
      copiame literalmente lo que tengas...
      lo que te dejé era una macro completa, desde el comienzo (Sub ...) hasta el final (End Sub); no puede ser te falle.

      En lo que te mandé no hay funcionalidad asociada al presionar los botones, eso se debe configurar según las direcciones que pretendas tomar.

      Saludos

      Eliminar
    4. Muchísimas gracias por atender me, un saludo.

      Eliminar
  6. hola. si me pueden ayudar se los agradeceria mucho.
    Lo que quiero es cuando un usuario modifique o elimine algun contenido de una celda, que les aparezca un mensaje de si o no y que cuando el usuario escoja si, que pueda modifica o eliminar el contenido y cuando responda de que no, que no haga nada.

    ResponderEliminar
    Respuestas
    1. Hola Roberto,
      una duda un poco larga... y complicada de configurar.

      Se trataría de añadir un evento _Change en la ventana de código de la hoja en cuestión; a su vez configurar un condicional que controle la respuesta.

      Te doy la pista de por donde empezar:
      Private Sub Worksheet_Change(ByVal Target As Range)
      borrar = MsgBox("Confirma el borrado", vbYesNo)
      If borrar = vbYes Then Target.Delete
      End Sub

      El tema es algo más complejo, por que este evento se ejecuta tras la acción de cambio (o borrado)...

      Espero te oriente en tu búsqueda
      Saludos

      Eliminar
  7. Hola Ismael, como estas?
    tengo una duda, cuando toco el boton imprimir en la parte superior yo pedi que me aparesca un MsgBox advirtiendo si faltan datos y luego que aparezcan dos botones "aceptar" y "cancelar"

    Private Sub Workbook_BeforePrint(cancel As Boolean)

    MsgBox "FALTAN DATOS", vbYesNo

    end sub

    eso es facil , ahora como hago para asignar que aceptar me deje imprimir y cancelar no me deje.??

    ResponderEliminar
    Respuestas
    1. Hola Walter,
      tienes que asociar un camino a la posible respuesta con un condicional:
      Private Sub Workbook_BeforePrint(cancel As Boolean)

      pregunta=MsgBox "FALTAN DATOS", vbYesNo

      if pregunta=VbYes then
      ....[el código para que imprima]
      else
      ....[o nada o un código de salida del procedimiento]
      end if

      end sub

      Saludos

      Eliminar
  8. Buena tarde. Una ayuda importante. Tengo un archivo en excel que autosuma en una celda a medida que ingreso cantidades, multiplica por el valor unitario, y totaliza. La pregunta es: Cuando se alcanza un límite o cupo, que código debo escribir para que no me permita avanzar a la celda siguiente, hasta que cambie la cantidad? Gracias.

    Private Sub Worksheet_SelectionChange(ByVal Target As Range)

    If Range("e149").Value > 70000 Then
    MsgBox ("Excedió su cupo Máximo $70.000!!!")
    End If

    ResponderEliminar
  9. Éste es el código que he colocado hasta ahora. Me genera el mensaje, pero me permite avanzar, La idea es que no lo permita hasta que cambie la ultima cantidad que excede el cupo o límite.

    ResponderEliminar
  10. Hola deseo que me ayuden en algo, al pulsar la X de un MsgBox, el proceso continua. yo deseo que me ayuden como detener la macro al pulsar la X del cuadro de MsgBox. gracias

    ResponderEliminar
    Respuestas
    1. Hola,
      no creo posible tal cosa...
      pero si se puede deshabilitar empleando tipo de respuesta vbYesNo:

      MsgBox "Con vbYesNo se desactiva el botón X de cerrar", vbYesNo, "Acción"

      Espero te sirva
      Saludos

      Eliminar
  11. HOla, sigue pendiente tu duda? YO cabo de implementar algo parecido en un libro que utilizo para calcular costos; luego de capturar datos y almacenarlos en otra hoja (con otra macro), agregué un botón de formulario que hace justo lo que quieres, despliega un msgbox en pantalla que pregunta si estás seguro de borrar los datos (no comprendo por que al borrarlos con una macro no funciona ctrl+z para "recuperarlos", si cancelas se cierra y no pasa nada, si aceptas borra y aparece otro msgbox: te comparto mi código:

    Sub BorrarLona()
    '
    ' BorrarLona Macro
    '

    Resultado = MsgBox("Confirme que desea borrar los datos. Este procedimiento NO es reversible.", vbOKCancel, "¡ADVERTENCIA!")
    If Resultado = vbOK Then
    Range("H18,K18,L18,M18,I22,J22,J24").Select
    Range("J24").Activate
    Selection.ClearContents
    MsgBox "Datos eliminados"
    Else
    End If

    End Sub

    La clave para lo que quieres es usar If- Then, ligando el Then con el fin de la macro. Saludos!

    ResponderEliminar
  12. Hola Ismael buenas tardes.
    Muy interesante la función msgbox. Ya la estoy aplicando en el archivo que uso a diario y constantemente en mi trabajo. Sin embargo, me surge una duda, necesito aplicar msgbox en una hoja y el msgbox tiene que dar muchos mensajes según las condiciones que le indique. Por ejemplo:

    Si la celda A1 es diferente a la celda A300 entonces el msgbox seria “Hay diferencia en las celdas A1 y A300, favor resisar”
    Si la celda B1 es diferente a la celda B300 entonces el msgbox seria “Hay diferencia en las celdas B1 y B300, favor resisar”
    Si la celda C1 es diferente a la celda C300 entonces el msgbox seria “Hay diferencia en las celdas B1 y B300, favor resisar”
    Y así sucesivamente. Son más de 100 comparaciones que debe hacer la función msgbox en la hoja, y por ende será un mensaje para cada SI según cada caso. Estoy segura que es posible, pero no concibo la forma de hacerlo. Si está en tus manos poder ayudarme te lo agradezco de antemano.

    ResponderEliminar
    Respuestas
    1. Hola,
      puedes hacer un bucle que recorra las 300 celdas:
      for each celda in range("A1:KN1")
      if celda.value<>celda.offset(300,0).value then msgbox "hay diferencias.."
      next celda

      Slds

      Eliminar
    2. Hola Ismael buenas tardes. Me documentaré sobre el tema de bucle porque no tengo ni idea de que se trata. Mis conocimientos sobre macros con realmente mínimos. Muy agradecida por tu ayuda. Saludos

      Eliminar
    3. Hola,
      un bucle es por ejemplo el
      for each celda in range("A1:KN1")
      ...
      next celda
      que te indicaba.

      Pero algo de idea tendrás cuando ya estás empleando MsgBox en tu procedimiento, no??
      ;-)

      Slds

      Eliminar

Nota: solo los miembros de este blog pueden publicar comentarios.