jueves, 26 de diciembre de 2013

VBA: Emitiendo sonidos desde VBA en Excel.

Un par de veces en las últimas semanas me han preguntado por la posibilidad de emitir sonidos controlados desde nuestros proyectos de VBA. POr lo que en la entrada del día, explicaré una manera rápida de conseguirlo.

Por supuesto nos podríamos conformar con la instrucción .Beep que emite un sonido sin más al llamarlo en nuestras macros. Por ejemplo:
Sub sonido()
Beep
End Sub


Pero lo que hoy veremos será algo más completo; ya que podremos hacer sonar cualquier sonido que se nos antoje, sin necesidad de ningún reproductor de media.... Lo primero que deberíamos tener es el archivo de sonido (.wav)
Para nuestra macro emplearemos la función API PlaySound que se encuentra en la librería de Windows winmm.dll. Asi que emplearemos la instrucción Declare que se usa en el nivel de módulo para declarar referencias a procedimientos externos que están en una biblioteca de vínculos dinámicos(DLL).

Por tanto en la parte de arriba de nuestro módulo dentro de un proyecto de VBA, antes de cualquier otra sentencia, insertaremos el siguiente código:

Private Declare Function PlaySound Lib "winmm.dll" Alias "PlaySoundA" _
(ByVal lpszName As String, ByVal hModule As Long, ByVal dwFlags As Long) As Long



Los parámetros asociadas a la variable dwFlags son:
Const SND_SYNC = &H0 ' (por defecto) Reproduce el sonido 'sincrónicamente'. Se interrumpe la ejecución de nuestro código hasta la finalización del sonido!!.
Const SND_ASYNC = &H1 ' Reproduce el sonido 'sincrónicamente'. El código continúa sin necesidad de que el sonido finalice.
Const SND_NODEFAULT = &H2 ' En caso no se encuntre el sonido determinado no reproduciría el sonido por defecto, es decir, no sonaría nada...
Const SND_LOOP = &H8 ' Se reproduce el sonido ininterrumpidamente hasta que se ejecute de nuevo la función.
Const SND_NOSTOP = &H10 ' El sonido no se para antes de reproducir el sonido especificado.

Otras constantes:
Const SND_APPLICATION = &H80
Const SND_ALIAS = &H10000
Const SND_ALIAS_ID = &H110000
Const SND_FILENAME As Long = &H20000
Const SND_MEMORY = &H4
Const SND_NOWAIT = &H2000
Const SND_PURGE = &H40
Const SND_RESOURCE = &H40004

Es posible ver algo más de documentación en la página de Microsoft (ver)


Podemos crear entonces la siguiente macro, dentro de un módulo, que reproduzca el sonido elegido. En el ejemplo he optado por un sonido estándar de Windows (el famoso tada!!), que podemos encontrar en la ruta C:\Windows\Media\

Public Sub SonidoControlado()
    'definimos dos constantes para localizar la ruta y el nombre del archivo
    Const RutaSonido As String = "C:\Windows\Media\"    'la ruta del fichero
    Const ArchivoSonido As String = "tada.wav"          ' ojo, porque el fichero de sonido debe tener extensión wave
    Dim Sonido As String
    'construimos la ruta completa del archivo de sonido
    Sonido = RutaSonido & ArchivoSonido
    
    'llamamos a la función sndPlaySound32
    Call PlaySound(Sonido, &H1, &H1 Or &H20000)
End Sub



Por supuesto, igualmente podríamos haber asociado nuestra macro a un evento del libro o de la hoja, por ejemplo, cada vez que selecionemos una celda (evento _Worksheet_SelectionChange):

Private Declare Function PlaySound Lib "winmm.dll" _
    Alias "PlaySoundA" (ByVal lpszName As String, ByVal hModule As Long, ByVal dwFlags As Long) As Long
''''''''''''''''''''''''''''''''''''''''''''''''''''''
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
 'definimos dos constantes para localizar la ruta y el nombre del archivo
    Const RutaSonido As String = "C:\Windows\Media\"    'la ruta del fichero
    Const ArchivoSonido As String = "tada.wav"          ' ojo, porque el fichero de sonido debe tener extensión wave
    Dim Sonido As String
    'construimos la ruta completa del archivo de sonido
    Sonido = RutaSonido & ArchivoSonido
    
    'llamamos a la función sndPlaySound32
    Call PlaySound(Sonido, &H1, &H1 Or &H20000)
End Sub

37 comentarios:

  1. Estimados expertos:
    Necesito ayuda con un problema de sonido en Excel para resumir:
    - Tengo una celda "A90" cuyos valores varían desde 1 hasta 9.
    - Tengo archivos de audio en WAV cuyos nombres son "1.wav", "2.wav", etc hasta "9.wav" en una carpeta definida.
    Lo que deseo es relacionar la reproducción de cada audio dependiendo del valor de la celda "A90" al ejecutar la macro, lo logré con una serie de condiciones concatenadas de IF THEN pero para 70 u 80 archivos de audio es demasiado complicado, pero con la macro siguiente:

    Private Declare PtrSafe Function PlaySound Lib "winmm.dll" _
    Alias "PlaySoundA" (ByVal lpszName As String, ByVal hModule As Long, ByVal dwFlags As Long) As Long
    Public Sub SonidoControlado1()
    Dim Sonido As String
    Dim s As Integer
    Const RutaSonido As String = "D:\Datos\Audios\"
    s = 1
    Do
    If Range("A90").Value <> s Then
    s = s + 1
    Else
    Sonido = RutaSonido & Range("A90").Value & ".wav"
    Call PlaySound(Sonido, &H1, &H1 Or &H20000)
    End If
    Loop
    End Sub

    El excel se loquea, y no le veo el error si pudieran ayudarme se los agradecería.
    Saludos
    Mco

    ResponderEliminar
    Respuestas
    1. Hola,
      cuando empleas un bucle del tipo DO..LOOP siempre debes definir cuál es el límite del bucle, de lo contrario ocurrirá lo que te ha pasado.. (bloqueo),
      Hay varias formas de controlarlo
      DO...
      LOOP UNTIL(/WHILE) ...
      ''''''''''''''''''''''''''''''''''''''''''
      DO UNTIL(/WHILE)...
      LOOP

      En tu caso podrías
      Do UNTIL s=9
      ...
      Loop

      Un saludo

      Eliminar
  2. Estimados expertos yo no se mucho de excel pero necesito saber como reprodusco un archivo de audio wav automaticamente en el momento que se llena cualquier celda, de antemano les agradesco su ayuda.

    ResponderEliminar
    Respuestas
    1. Hola,
      podrías asociar la macro descrita a un evento _Change en la ventana de código de la hoja en cuestión..
      Un saludo

      Eliminar
    2. Gracias experto por atender mi llamado, esta es la macro que hasta ahora tengo hecha, lo que me falta es que se active cada vez que se llene cualquier celda del rango C:C.

      Private Declare Function PlaySound Lib "winmm.dll" _
      Alias "PlaySoundA" (ByVal lpszName As String, _
      ByVal hModule As Long, ByVal dwFlags As Long) As Long
      Private Const SND_ASYNC = &H1
      Private Const SND_FILENAME = &H20000
      Public Sub Tocar(ByVal ArchivoWav As String)
      PlaySound ArchivoWav, _
      ByVal 0&, _
      SND_FILENAME Or SND_ASYNC
      End Sub
      Sub paratocar()
      Tocar "C:\Users\Gflores\Documents\LASER.WAV"
      tiempo = Now + TimeValue("00:00:01")
      End Sub

      Eliminar
    3. Hola,
      fíjate en la última parte de la entrada.. verás un procedimiento
      Private Sub Worksheet_SelectionChange(ByVal Target As Range)

      En tu caso debería ser
      Private Sub Worksheet_Change(ByVal Target As Range)

      esto te hará saltar el sonido cuando alguna celda cambie.. si quieres limitar el evento a un rango concreto (columna C:C), entonces anidarías dentro del procedimiento el método Intersect. Algo así:
      If Not Intersect(target, Range("C:C")) Is Nothing Then
      ...resto de tu código....
      End if

      Un saludo

      Eliminar
    4. Experto nuevamente agradesco tu ayuda, ya trate de hacer los cambios sugeridos pero no me funciona, reconosco que tal vez no los estoy haciendo bien por eso me tomo el atravimiento de pedirte un favor, mi macros si funciona cunado la activo de forma manual si emite el sonido, lo que quiero es que lo haga de forma automatica a la hora que se llene cualquier celda de la columna C, me podras ayudar a completar el codigo que te envie y anexarle esta condicion, gracias.

      Eliminar
    5. Hola..
      bueno, pensé que bastaría con la indicación
      ;-)

      Aquí lo tienes completo (OJO!! Incluir el código en la ventana de la Hoja!!!)

      Private Declare Function PlaySound Lib "winmm.dll" _
      Alias "PlaySoundA" (ByVal lpszName As String, ByVal hModule As Long, ByVal dwFlags As Long) As Long
      ''''''''''''''''''''''''''''''''''''''''''''''''''''''
      Private Sub Worksheet_Change(ByVal Target As Range)
      Const RutaSonido As String = "C:\Windows\Media\"
      Const ArchivoSonido As String = "tada.wav"
      Dim Sonido As String

      Sonido = RutaSonido & ArchivoSonido

      If Not Intersect(Target, Range("C:C")) Is Nothing Then
      Call PlaySound(Sonido, &H1, &H1 Or &H20000)
      End If

      End Sub

      Saludos

      Eliminar
    6. Hola experto, ya hice lo recomendado y aun no se reporduce te anexo el codigo tal y como esta en la ventana del modulo1 de VBA y como te comento si reproduce el sonido siempre y cuando la habra desde ver macros y ejecutar, solo falta una condicion que la ejecute en automatico al llenar cualquier celda de la columna C.
      disculpa la insistencia pero es un trabajo que necesito terminar, tambien entiendo si ya no tubieras tiempo de ayudarme no hay problema, gracias.

      Private Declare Function PlaySound Lib "winmm.dll" _
      Alias "PlaySoundA" (ByVal lpszName As String, _
      ByVal hModule As Long, ByVal dwFlags As Long) As Long
      Private Const SND_ASYNC = &H1
      Private Const SND_FILENAME = &H20000
      ______________________________________________________
      Public Sub Tocar(ByVal ArchivoWav As String)
      PlaySound ArchivoWav, _
      ByVal 0&, _
      SND_FILENAME Or SND_ASYNC
      End Sub
      __________________________________________________
      Sub paratocar()
      Tocar "C:\Users\Gflores\Documents\LASER.WAV"
      tiempo = Now + TimeValue("00:00:01")
      End Sub

      Eliminar
    7. Como te detallaba en los comentarios anteriores el código debe incluirse en la ventana de código de la hoja en cuestión NO de un módulo!!!
      Un cordial saludo!

      Eliminar
    8. Perfecto!!! lo logre gracias a ti experto, te agradesco mucho tu ayuda y tu paciencia,eres una gran persona por compartir tus conocimientos a los que no sabemos, gracias!!!!! :-)

      Eliminar
    9. Experto saludos, nuevamente tengo otro conflicto, como le hago si en la hoja1 tengo ya otro codigo, y anexo el que me pasaste y respete la funcion de los dos, anexo el otro codigo.

      Private Sub Worksheet_Change(ByVal Target As Range)
      If Not Application.Intersect(Target, Range("A:A")) Is Nothing Then
      Range("G" & Target.Row) = Date
      Range("H" & Target.Row) = Format(Now, "hh:mm")
      End If
      End Sub

      Eliminar
    10. Hola,
      basta incluir uno dentro de otro:

      Private Declare Function PlaySound Lib "winmm.dll" _
      Alias "PlaySoundA" (ByVal lpszName As String, ByVal hModule As Long, ByVal dwFlags As Long) As Long
      ''''''''''''''''''''''''''''''''''''''''''''''''''''''
      Private Sub Worksheet_Change(ByVal Target As Range)
      Const RutaSonido As String = "C:\Windows\Media\"
      Const ArchivoSonido As String = "tada.wav"
      Dim Sonido As String

      Sonido = RutaSonido & ArchivoSonido

      If Not Intersect(Target, Range("C:C")) Is Nothing Then
      Call PlaySound(Sonido, &H1, &H1 Or &H20000)
      End If

      If Not Application.Intersect(Target, Range("A:A")) Is Nothing Then
      Range("G" & Target.Row) = Date
      Range("H" & Target.Row) = Format(Now, "hh:mm")
      End If

      End Sub

      Saludos

      Eliminar
  3. buenas
    espero que me podáis ayudar
    quiero que al lanzar una macro que dura un par de minutos suene un archivo de sonido mp3 (no wav) de fondo (si es posible que no se vea ningún reproductor)
    que enpiece al arrancar la macro y que se pare cuando la macro finalice
    ¿es factible?
    saludos

    ResponderEliminar
    Respuestas
    1. Hola Manuel,
      en principio si se podría hacer sonar un archivo de sonido .mp3.. otra cosa sería sincronizarla con el tiempo de ejecución de una macro...

      Tendría que investigarlo, pero cuando lanzas un archivo de sonido, hasta donde yo sé, este debe finalizar por sí solo...

      Saludos

      Eliminar
  4. buenas tardes Ismael
    mi macro está en un módulo de outlook
    la macro extrae ciertos datos de emails entrantes y los copia en una página de excel
    a su vez, esos datos son completados importando otros complementarios de un archivo excel muy grande (por eso la macro tarda tanto)
    finalmente, se genera un email que adjunta el libro de Excel creado y que se envía a las personas interesadas
    todo este proceso dura entre dos y tres minutos
    la idea es crear un userform con WindonsMediaplayer (u otra manera que lea archivos mp3) que active un archivo mp3 que suene en NO MODAL en tanto que dura la macro
    no sé si es necesario sincronizar la música con la macro
    espero que no, porque he probado con un userform con una imagen; insertando en mi código las instrucciones “UserForm1.Show False” y “Unload UserForm1” el userform se abre al arrancar la macro y lo cierro antes del "end sub" de la macro
    ¿es posible hacer algo similar con la música, iniciarla al comienzo de la macro como NO MODAL y apagarla al final antes de "end sub"?
    ¿cómo podría insertar en código para el archivo de sonido? y, sobre todo, ¿dónde debo insertarlo; en mi macro de outlook o dentro de módulo del userform?
    gracias y disculpa tantas preguntas
    un abrazo, tu trabajo no tiene precio sobre todo para los que ni hablamos ni leemos en inglés

    ResponderEliminar
    Respuestas
    1. Bueno, si tienes pensado incluir el .mp3 en un control windowsMediaPlayer dentro del userForm, siempre podrás 'apagar' la música con la orden:
      WindowsMediaPlayer1.Controls.stop

      o simplemente cerrando el formulario que lo contenga...

      Por otra parte cargar el audio (mp3) en el userform sería sencillo, bastaría incluir en el evento Initialize:
      Private Sub UserForm_Initialize()
      WindowsMediaPlayer1.URL = "C:\Ruta\Kalimba.mp3"
      End Sub

      Espero te pueda servir.
      Saludos cordiales

      Eliminar
  5. Buenos días Ismael
    Lamento molestar otra vez
    He creado el userform con el control de WindowsMediaPlayer1
    He insertado en el código del userform el evento “inicialize” con la instrucción
    WindowsMediaPlayer1.URL = "C:\Users\XXXXXXXXX\Music\06 - Streamside Songbirds.mp3"
    Cuando ejecuto el propio código del evento se muestra el userform y comienza a sonar la música
    Sin embargo, cuando corro la macro principal, que está en Outlook, y habiendo incluido al principio la instrucción “userform1.Show false” se abre el userform1 pero no suena. En la pantalla de WindowsMediaPlayer aparece un pequeño texto que dice “Conectando…”
    El caso es que la macro acaba haciendo desaparecer el userform con la instrucción “unload userform1” sin que haya llegado a sonar
    Ni idea del por qué. Entiendo que el userform es NO modal gracias al argumento “false” y la música debería sonar mientras corre la macro principal. . .sólo se me ocurre que, de alguna manera, la instrucción “xlapp.Application.FileDialog(msoFileDialogOpen) “ que abre un cuadro para escoger un archivo para seleccionarlo, y que está inmediatamente después de “userform1.Show false” , “le roba el protagonismo” a la instrucción “userform1.Show false” pero no lo sé
    ¿Se te ocurre algo?
    Por otro lado, he intentado variar el tamaño de éste y otro userform para que ocupen la totalidad de la pantalla con instrucciones del tipo
    Private sub userform_activate
    With application
    Me.height = . height
    Me.width = .width
    End with
    Y siempre me da error 438. ¿sabes por qué no me reconoce las variables?
    Como siempre, muchísimas gracias

    ResponderEliminar
    Respuestas
    1. prueba forzando el inicio de la música con
      WindowsMediaPlayer1.Controls.play

      Respecto a
      Private sub userform_activate
      With application
      Me.height = . height
      Me.width = .width
      End with
      End sub

      debe funcionarte sin problemas... ¿¿no sé que no comprende Excel de esto??
      Slds

      Eliminar
  6. buenas tardes Ismael
    Muchísimas gracias por la rápida respuesta
    probaré lo de forzar el WMP mañana dios mediante
    con relación a
    Private sub userform_activate
    With application
    Me.height = . height
    Me.width = .width
    End with
    End sub
    la macro no está en un módulo de excel sino en uno de Outloot y el userform también está en el proyecto de Outlook
    la macro desde abre un libro de excel, y se crea y se salva otro que se adjunta al email generado por la macro
    creo que en outlook esas instrucciones no son válidas como lo son en excel (que he probado satisfactoriamente) pero no soy capaz de encontrar nada en la web habiendo probado muchas formas distintas de armar el código
    no sé si el hecho de llamar al menú para escoger el archivo de Excel a abrir “congela” la reproducción de la música
    he adjuntado el comienzo de la macro para que te hagas una idea
    en cuanto al tema de que la música suene en paralelo a la ejecución de la macro creo que el argumento showmodal está correctamente definido en FALSE en las Propiedaes del userform
    me sabe muy mal darte tantas molestias pero si puedes ayudarme estupendo, si no puedes por falta de tiempo dímelo
    saludos


    Sub EXPORTAR_EMAIL_INFORMA_A_EXCEL()

    UserForm1.Show False

    On Error GoTo ErrHandler

    Dim olItem As Outlook.MailItem
    Dim vText() As String
    Dim sText As String
    Etc, etc

    Set xlapp = CreateObject("Excel.Application")
    With xlapp
    .Visible = True
    .EnableEvents = False
    End With

    xlapp.Application.ScreenUpdating = False

    Set myfile = xlapp.Application.FileDialog(msoFileDialogOpen)

    ResponderEliminar
    Respuestas
    1. Hola Manuel,
      aunque los códigos deben ser similares, cada aplicación en realidad tiene sus peculiaridades...
      quizá obtengas la solución a ese problema puntual en un foro específico de OutLook...la verdad, se me escapa si existen diferencias importantes (
      claramente debe haberlas cuando te falla, y en Excel ese código funciona)

      :(

      Eliminar
  7. buenos días Ismael
    te agradezco muchísimo todo el esfuerzo
    sigo buscando pero hasta ahora no he tenido suerte
    ¿conoces algún buen foro en castellano de automatización de outlook?
    saludos y muchas gracias por tu buena disposicìón
    ayudas mucho y a muchos

    ResponderEliminar
  8. Como aplico esto en un entorno de 64 bits? Me dice que tengo que agregarle un PtrSafe pero no se donde...

    ResponderEliminar
    Respuestas
    1. Hola Josué,
      Debería funcionarte como te indico a continuación. Agrégalo antes de function:

      Private Declare PtrSafe Function PlaySound Lib "winmm.dll" Alias "PlaySoundA" _
      (ByVal lpszName As String, ByVal hModule As Long, ByVal dwFlags As Long) As Long

      ojo por que al montarlo así no funcionaría para otras versiones....
      Saludos

      Eliminar
  9. Hola Ismael. Excelente Foro!

    Tengo una pregunta, ¿puedo correr varias macros simultaneamente en vba excel? por ejemplo cinco cronometros con diferentes tiempos? Cada macro está en un módulo y está asignada a un boton de inicio. Cada cronometro al finalizar, debe emitir una alerta y cambiar los colores de una celda como alarma. Al momento que un cronometro termina y está emitiendo la alarma y cambiando los colores, los otros cronometros se detienen hasta que se finaliza la que ha terminado. Luego continuan contando. Es un temporizador más que un cronometro, va decrementando.

    Agradezco tu ayuda de antemano.

    ResponderEliminar
  10. hola perdon estoy tratando de hacer la macro pero me encuentro trabado en algo te paso mi codigo y me ayudas a integrar?? creo que solo es lo que le falta


    Private Sub Worksheet_Change(ByVal Target As Range)


    If Not Application.Intersect(Target, Range("B:B")) Is Nothing Then
    Range("I" & Target.Row) = Date
    Range("J" & Target.Row) = Format(Now, "hh:mm:ss")
    Range("V" & Target.Row) = Format(Now, "hh:mm:ss")

    Range("T" & Target.Row).FormulaR1C1 = "=IF(RC[-10]="""","""",NOW()-RC[-10])"
    Range("U" & Target.Row).FormulaR1C1 = _
    "=IF(RC[-11]="""","""",IF(MINUTE(RC[-1])<=1,""VERDE"",IF(MINUTE(RC[-1])<=2,""AMARILLO"",IF(MINUTE(RC[-1])>=3,""ROJO"",""""))))"

    ElseIf Not Application.Intersect(Target, Range("S:S")) Is Nothing Then
    Range("L" & Target.Row) = Format(Now, "hh:mm:ss")
    Range("N" & Target.Row).FormulaR1C1 = "=RC[-1]-RC[-4]"
    Range("M" & Target.Row).Formula = "=RC[-1]"
    End If



    End Sub

    en que parte debo incluir tu macro para que funcione, quiero que se active el sonido cada que el rango de celdas de "u" se ponga la palabra amrillo como resultado de mi macro anterior espero que me puedas ayudar saludos!!!!!

    ResponderEliminar
    Respuestas
    1. Hola Iván,
      yo incluiría el código del sonido antes de
      ElseIf Not ...

      bastaría algo así:
      If Range("U" & Target.Row).Value = "AMARILLO" Then Call PlaySound(Sonido, &H1, &H1 Or &H20000)

      obviamente definiendo previamente todas sus variables.

      Saludos

      Eliminar
    2. gracias Ismael

      ya he tratado de definir las variables pero me da el error siguiente "El numero de argumentos es incorrecto o la asignacion de propiedad no es valida"


      te adjunto mi codigo

      Private Sub Worksheet_Change(ByVal Target As Range)


      If Not Application.Intersect(Target, Range("B:B")) Is Nothing Then
      Range("I" & Target.Row) = Date
      Range("J" & Target.Row) = Format(Now, "hh:mm:ss")
      Range("V" & Target.Row) = Format(Now, "hh:mm:ss")

      Range("T" & Target.Row).FormulaR1C1 = "=IF(RC[-10]="""","""",NOW()-RC[-10])"
      Range("U" & Target.Row).FormulaR1C1 = _
      "=IF(RC[-11]="""","""",IF(MINUTE(RC[-1])<=1,""VERDE"",IF(MINUTE2(RC[-1])<=2,""AMARILLO"",IF(MINUTE(RC[-1])>=3,""ROJO"",""""))))"
      Const RutaSonido As String = "C:\MisArchivos\IVAN\notification ri"
      Const ArchivoSonido As String = "notification ri.wav"
      Dim Sonido As String
      Sonido = RutaSonido & ArchivoSonido


      If Range("U" & Target.Row).Value = "AMARILLO" Then
      Call playsound(Sonido, &H1, &H1 Or &H20000)



      ElseIf Not Application.Intersect(Target, Range("S:S")) Is Nothing Then
      Range("L" & Target.Row) = Format(Now, "hh:mm:ss")
      Range("N" & Target.Row).FormulaR1C1 = "=RC[-1]-RC[-4]"
      Range("M" & Target.Row).Formula = "=RC[-1]"
      End If


      End If






      End Sub


      o sera acaso que lo tengo que poner en un modulo separado???


      saludos!!!

      Eliminar
    3. Este comentario ha sido eliminado por el autor.

      Eliminar
    4. Hola Iván,
      no olvides incluir antes del evento, al principio de todo (lee despacio lo explicado en el post):
      Private Declare Function PlaySound Lib "winmm.dll" Alias "PlaySoundA" _
      (ByVal lpszName As String, ByVal hModule As Long, ByVal dwFlags As Long) As Long

      En total en la ventana de código de la hoja en cuestión, el código completo sería:
      Private Declare Function PlaySound Lib "winmm.dll" Alias "PlaySoundA" _
      (ByVal lpszName As String, ByVal hModule As Long, ByVal dwFlags As Long) As Long

      Private Sub Worksheet_Change(ByVal Target As Range)

      If Not Application.Intersect(Target, Range("B:B")) Is Nothing Then
      Range("I" & Target.Row) = Date
      Range("J" & Target.Row) = Format(Now, "hh:mm:ss")
      Range("V" & Target.Row) = Format(Now, "hh:mm:ss")

      Range("T" & Target.Row).FormulaR1C1 = "=IF(RC[-10]="""","""",NOW()-RC[-10])"
      Range("U" & Target.Row).FormulaR1C1 = _
      "=IF(RC[-11]="""","""",IF(MINUTE(RC[-1])<=1,""VERDE"",IF(MINUTE(RC[-1])<=2,""AMARILLO"",IF(MINUTE(RC[-1])>=3,""ROJO"",""""))))"

      'definimos dos constantes para localizar la ruta y el nombre del archivo
      Const RutaSonido As String = "C:\Windows\Media\" 'la ruta del fichero
      Const ArchivoSonido As String = "tada.wav" ' ojo, porque el fichero de sonido debe tener extensión wave
      Dim Sonido As String
      'construimos la ruta completa del archivo de sonido
      Sonido = RutaSonido & ArchivoSonido
      'llamamos a la función sndPlaySound32
      If Range("U" & Target.Row).Value = "AMARILLO" Then Call PlaySound(Sonido, &H1, &H1 Or &H20000)
      ElseIf Not Application.Intersect(Target, Range("S:S")) Is Nothing Then
      Range("L" & Target.Row) = Format(Now, "hh:mm:ss")
      Range("N" & Target.Row).FormulaR1C1 = "=RC[-1]-RC[-4]"
      Range("M" & Target.Row).Formula = "=RC[-1]"
      End If
      End Sub

      Saludos

      Eliminar
    5. hola, ya lo intente pero me marca el error de que el sistema es de 64 bit, sabes como se soluciona???


      saludos!!!

      Eliminar
    6. Hola Ivan,
      para luchar con la incompatibilidad en ciertos puntos entre 32bits-64bits lee este post de Microsoft:
      https://msdn.microsoft.com/en-us/library/ee691831.aspx

      Básicamente hay que incluir el texto:
      Declare PtrSafe Function ...
      dependiendo del caso

      Saludos

      Eliminar
    7. gracias Ismael



      ya pude corregir el error de la compatibilidad de la macro, pero ahora no me llama ningun sonido cuando se cumple la condicion, la ruta de sonido es correcta y la extension del archivo es .wav, y no logro dar con el error, sabes si en lugar de llamar el archivo desde el fichero se podra insertar en el propio documento como un objeto??? sera mas facil?? gracias de antemano y una disculpa por todos los problemas, y los post son muy buenos el que recomendaste esta muy bien explicado gracias

      Eliminar
  11. Buenas tardes Sr. Ismael, estoy un poco verde en estos temas de Excel, pero buscandole y a prueba y error, encontre como hacer para llevar el conteo de los días que lleva un vencimiento de unas fechas, pero me gustaría hacer un Macro para que estas fechas emitan un Sonido automático cuando se llegue a cierto tiempo (ejemplo: Carlos tiene 90 días de plazo para pagar [Lo que deseo es que cuando le queden 15 días, una alarma suene automáticamente]).

    Le agradecería me ayudara con esta duda, de antemano muchas gracias.

    ResponderEliminar
    Respuestas
    1. Hola,
      podrías incorporar un evento _Open en el explorador de proyecto, en 'ThisWorkbook' para que lance un proceso parecido al del post, pero condicionado al valor de la celda donde has calculado días a vencimiento.. para que cuando sea <15 haga sonar la 'alarma'.
      OJO, por que esto no te identificará a priori cuál es, simplemente oirás un sonido.
      Sinceramente me parece más práctico aplicar u sencillo formato condicional y que las celdas que cumplan la condición aparezcan con algún formato.

      Saludos

      Eliminar