🚀The world's best VBA AI has evolved. ExcelMaster is now an autonomous Agent.Read more →
Back to Blog

VBA PowerPoint en Excel — crear diapositivas, pegar gráficos y no cerrar nunca la presentación del usuario

|

VBA PowerPoint en Excel — crear diapositivas, pegar gráficos y no cerrar nunca la presentación del usuario

TL;DR — Desde Excel, PowerPoint es otro programa que manejas a través de su modelo de objetos: Application > Presentations > Slides > Shapes. No hay celdas. Una diapositiva es un lienzo de formas colocadas en puntos, así que Excel prepara los números y los gráficos y PowerPoint solo los coloca. La trampa es que PowerPoint ejecuta una sola copia: CreateObject("PowerPoint.Application") te entrega el PowerPoint que el usuario ya tiene abierto, con sus presentaciones dentro. Cierra solo la presentación que creaste y llama a .Quit solo si PowerPoint no se estaba ejecutando antes de que arrancara tu macro. Pega los gráficos como imágenes, reintenta el pegado cuando el portapapeles va lento y parte de una plantilla en lugar de dibujar diseños con código.

Sub ChartToNewSlide()
    Dim ppt As Object, pres As Object, sld As Object
    Set ppt = CreateObject("PowerPoint.Application")     ' el PowerPoint en ejecucion, si lo hay
    Set pres = ppt.Presentations.Add                      ' una presentacion nueva, con ventana
    Set sld = pres.Slides.Add(1, 11)                      ' 11 = ppLayoutTitleOnly
    sld.Shapes.Title.TextFrame.TextRange.Text = "Q3 revenue"
    ActiveSheet.ChartObjects(1).Chart.CopyPicture
    sld.Shapes.PasteSpecial DataType:=2                   ' 2 = ppPasteEnhancedMetafile
End Sub

Este es el primero de una serie de tres artículos sobre cómo manejar otras apps de Office desde Excel. Aquí, PowerPoint: una presentación hecha de formas. La guía de Word trata el documento, que es una larga tira de texto. La guía de referencias trata el vínculo que le dice a VBA qué significan las palabras del otro programa, y qué pasa cuando ese vínculo falta en el PC de otra persona. Una regla recorre los tres: cada objeto pertenece a una aplicación, así que di a cuál.

Lo que aprenderás

  • El modelo mental: una presentación son diapositivas llenas de formas, medidas en puntos, sin celdas
  • Por qué la instancia única de PowerPoint hace peligroso .Quit, y cómo arrancar y terminar con seguridad
  • Cómo añadir diapositivas, escribir títulos y usar números de diseño sin referencia
  • Cómo pegar un gráfico o un rango como imagen, y por qué el pegado falla a veces
  • Cómo colocar y dimensionar una forma pegada en la diapositiva
  • Por qué una plantilla de presentación es mejor que construir diseños con código

El modelo mental: sin celdas, solo formas sobre un lienzo

Excel piensa en cuadrícula. PowerPoint no tiene cuadrícula. Su modelo de objetos es una cadena corta:

Objeto Qué es Equivalente en Excel
Application el programa PowerPoint Application
Presentations / Presentation presentaciones abiertas / una presentación Workbooks / Workbook
Slides / Slide las páginas de la presentación Worksheets / Worksheet
Shapes / Shape todo lo que hay en una diapositiva: títulos, cuadros de texto, imágenes, gráficos (sin equivalente real)

El texto vive dentro de una forma: Shape.TextFrame.TextRange.Text. La posición vive en la forma: .Left, .Top, .Width, .Height, todo en puntos (72 puntos por pulgada). La diapositiva en sí mide pres.PageSetup.SlideWidth por SlideHeight, que en una presentación estándar 16:9 son 960 por 540 puntos.

Por eso el reparto sensato del trabajo es: Excel calcula, PowerPoint coloca. Monta la tabla o el gráfico en una hoja, donde tienes fórmulas y formato, y luego lleva una imagen terminada a la diapositiva. Intentar construir tablas celda a celda dentro de PowerPoint es lento y frágil.

La trampa: PowerPoint solo ejecuta una copia

Excel y Word pueden ejecutar varias copias a la vez. PowerPoint no. Cuando tu macro llama a CreateObject("PowerPoint.Application"), Windows no arranca un PowerPoint nuevo y privado, como describe la guía de CreateObject para la mayoría de los programas. Te entrega el PowerPoint que ya se está ejecutando, el que tiene abierta la presentación a medio terminar del usuario.

De ahí salen dos cosas:

  • ppt.Quit lo cierra todo. Se cierran todas las presentaciones que el usuario tenga abiertas, y los cambios sin guardar disparan avisos para guardar, o se pierden si tu código los ha suprimido.
  • No puedes ocultarlo. ppt.Visible = False lanza un error en tiempo de ejecución que termina en Hiding the application window is not allowed (no se permite ocultar la ventana de la aplicación). Si necesitas trabajar sin que se vea, abre o añade la presentación sin ventana (WithWindow:=0) en lugar de ocultar el programa.

El patrón seguro consiste en recordar si PowerPoint ya se estaba ejecutando, cerrar solo lo que abriste y salir solo de lo que arrancaste:

Sub BuildDeck()
    Dim ppt As Object, pres As Object
    Dim wasRunning As Boolean

    On Error Resume Next
    Set ppt = GetObject(, "PowerPoint.Application")   ' ya se esta ejecutando?
    On Error GoTo 0
    wasRunning = Not ppt Is Nothing
    If Not wasRunning Then Set ppt = CreateObject("PowerPoint.Application")

    Set pres = ppt.Presentations.Add
    ' ... aqui se anaden diapositivas y contenido ...
    pres.SaveAs ThisWorkbook.Path & "\Report.pptx"
    pres.Close                                        ' cierra solo NUESTRA presentacion

    If Not wasRunning Then
        If ppt.Presentations.Count = 0 Then ppt.Quit  ' sale solo de lo que arrancamos
    End If
    Set pres = Nothing
    Set ppt = Nothing
End Sub

GetObject con el primer argumento vacío se engancha a una copia en ejecución y falla si no hay ninguna, que es justo la prueba que necesitas. Liberar las variables con Set ... = Nothing al final sigue la guía de Nothing.

Añadir diapositivas y texto sin referencia

pres.Slides.Add(Index, Layout) inserta una diapositiva en una posición con uno de los diseños integrados de PowerPoint. Sin una referencia a la biblioteca de PowerPoint, los nombres de diseño como ppLayoutTitleOnly no significan nada para el compilador de Excel, así que usas sus números. Decláralos una vez como constantes y el código sigue siendo legible:

Const ppLayoutTitle As Long = 1
Const ppLayoutTitleOnly As Long = 11
Const ppLayoutBlank As Long = 12
Const ppPasteEnhancedMetafile As Long = 2
Const ppPastePNG As Long = 6

Sub AddSlides(pres As Object)
    Dim sld As Object
    Set sld = pres.Slides.Add(pres.Slides.Count + 1, ppLayoutTitleOnly)
    sld.Shapes.Title.TextFrame.TextRange.Text = "Sales by region"

    Set sld = pres.Slides.Add(pres.Slides.Count + 1, ppLayoutBlank)
    With sld.Shapes.AddTextbox(1, 40, 40, 600, 50)    ' 1 = texto horizontal
        .TextFrame.TextRange.Text = "Notes for the board"
        .TextFrame.TextRange.Font.Size = 24
    End With
End Sub

pres.Slides.Count + 1 añade al final. Si prefieres IntelliSense y los nombres reales, marca una referencia a la biblioteca de objetos de PowerPoint; la guía de referencias lo explica, junto con lo que cuesta hacerlo cuando el archivo viaja a otros equipos.

Pegar un gráfico o un rango: como imagen, y con reintento

La forma fiable de llevar contenido de Excel a una diapositiva es como imagen. Un gráfico:

ws.ChartObjects("chtSales").Chart.CopyPicture   ' una imagen del grafico
Set shp = sld.Shapes.PasteSpecial(DataType:=ppPasteEnhancedMetafile)

Un rango, con su formato tal y como se ve en la hoja:

ws.Range("A1:E12").CopyPicture Appearance:=1, Format:=-4147   ' xlScreen, xlPicture
Set shp = sld.Shapes.PasteSpecial(DataType:=ppPasteEnhancedMetafile)

Un metarchivo mejorado se mantiene nítido cuando se redimensiona la diapositiva. ppPastePNG da una imagen de resolución fija que se ve idéntica en cualquier PC. Las dos son instantáneas: no cambian cuando cambia el libro, que es lo que suele querer un informe.

Ahora el fallo con el que se topa todo el mundo. La macro funciona nueve de cada diez veces y de repente se para en el pegado con un error que dice que el portapapeles está vacío o que contiene datos que no se pueden pegar aquí. El código no tiene nada mal. La copia todavía se está volcando al portapapeles de Windows cuando PowerPoint la pide. La solución es darle tiempo y volver a intentarlo, no sembrar un Wait fijo por todas partes:

Function PasteWithRetry(sld As Object, ByVal dataType As Long) As Object
    Dim attempt As Long
    For attempt = 1 To 5
        On Error Resume Next
        Set PasteWithRetry = sld.Shapes.PasteSpecial(DataType:=dataType)
        If Err.Number = 0 Then
            On Error GoTo 0
            Exit Function
        End If
        On Error GoTo 0
        DoEvents                                 ' deja que el portapapeles termine
        Application.Wait Now + TimeSerial(0, 0, 1)
    Next attempt
    Err.Raise vbObjectError + 513, , "Paste into PowerPoint failed after 5 tries"
End Function

La guía de DoEvents explica por qué ceder el control ayuda aquí. Copia y luego llama a PasteWithRetry, un elemento cada vez; nunca copies cinco gráficos para luego pegar cinco veces.

Colocar la forma pegada

PasteSpecial devuelve la forma nueva (como un rango de formas), así que puedes colocarla en el acto. Usa el tamaño de la diapositiva, no números fijos, para que el mismo código funcione en presentaciones 4:3 y 16:9:

Sub FitToSlide(pres As Object, shp As Object, ByVal topMargin As Single)
    Dim maxW As Single, maxH As Single
    maxW = pres.PageSetup.SlideWidth - 80
    maxH = pres.PageSetup.SlideHeight - topMargin - 40
    shp.LockAspectRatio = -1                       ' msoTrue
    shp.Width = maxW
    If shp.Height > maxH Then shp.Height = maxH    ' la proporcion mantiene el ancho a la par
    shp.Left = (pres.PageSetup.SlideWidth - shp.Width) / 2
    shp.Top = topMargin
End Sub

Con la proporción bloqueada, cambiar el ancho cambia también el alto, así que la imagen nunca se deforma. Centrarla es simplemente el ancho de la diapositiva menos el ancho de la forma, dividido entre dos.

La decisión de criterio: rellena una plantilla, no dibujes diapositivas con código

Cada píxel que colocas con VBA es un píxel que alguien te pedirá mover el mes que viene. Mi regla: el diseño de la presentación pertenece a una plantilla de PowerPoint, y la macro solo la rellena. Monta una presentación a mano con las fuentes, los colores y el logotipo bien puestos. Pon nombre a las formas que el código debe rellenar en el Panel de selección (Selection Pane, Alt+F10), por ejemplo txtTitle y picChart. Después la macro abre una copia y rellena las formas por su nombre:

Set pres = ppt.Presentations.Open(FileName:=ThisWorkbook.Path & "\Monthly.potx", _
                                  ReadOnly:=-1, Untitled:=-1)   ' una copia sin titulo
With pres.Slides(1)
    .Shapes("txtTitle").TextFrame.TextRange.Text = "Sales - " & Format(Date, "mmmm yyyy")
    .Shapes("txtTotal").TextFrame.TextRange.Text = Format(ws.Range("F2").Value, "#,##0")
End With

Cuando marketing cambia los colores de marca, edita la plantilla y el código no cambia. La misma lógica dice que pegues imágenes en lugar de gráficos vinculados: un vínculo al libro se rompe en cuanto la presentación se envía por correo, y le pide al destinatario actualizar vínculos a los que no puede llegar. Si la presentación tiene que mantenerse viva, deja los datos en Excel y vuelve a ejecutar la macro. Si solo necesitas un PDF, puede que la guía de guardar como PDF sea todo lo que te hace falta, sin PowerPoint de por medio.

Cómo ayuda ExcelMaster

La automatización de PowerPoint falla de maneras difíciles de ver en el código: un pegado que falla una de cada diez ejecuciones, una macro que cierra las demás presentaciones del usuario, un diseño que solo se ve bien en la pantalla de quien lo hizo.

ExcelMaster te deja describir la presentación que quieres, por ejemplo «una diapositiva por región con su gráfico y el total en el título». Escribe la macro con el arranque y el cierre seguros, pega con reintento, dimensiona las formas a partir del tamaño de la diapositiva y rellena tu propia plantilla en lugar de codificar un diseño a fuego.

Preguntas frecuentes

¿Cómo abro PowerPoint desde Excel VBA?

Usa CreateObject("PowerPoint.Application") y después Presentations.Add para una presentación nueva o Presentations.Open para un archivo existente. Como PowerPoint solo ejecuta una copia, comprueba antes con GetObject(, "PowerPoint.Application") si ya se estaba ejecutando, para saber si puedes cerrarlo al final.

¿Cómo copio un gráfico de Excel a PowerPoint con VBA?

Llama a Chart.CopyPicture sobre el gráfico y luego a Slide.Shapes.PasteSpecial con DataType:=2 (ppPasteEnhancedMetafile) o 6 (ppPastePNG). Pega justo después de cada copia y reintenta el pegado unas cuantas veces con DoEvents entre medias, porque a veces el portapapeles no está listo.

¿Por qué mi pegado en PowerPoint con VBA falla al azar?

La copia todavía no ha terminado de llegar al portapapeles de Windows cuando PowerPoint intenta pegarla. Reintenta el pegado en un bucle corto con DoEvents y una espera de un segundo, y pega cada elemento inmediatamente después de copiarlo.

¿Por qué mi macro cierra las demás presentaciones del usuario?

PowerPoint es un programa de instancia única, así que tu macro lo comparte con todas las presentaciones que el usuario tenga abiertas, y Application.Quit las cierra todas. Cierra solo la presentación que creó tu código, y sal de PowerPoint solo si no se estaba ejecutando cuando arrancó la macro y no queda ninguna presentación abierta.

¿Puedo ejecutar PowerPoint de forma invisible desde VBA?

No ocultando el programa: poner Visible a False lanza un error. En su lugar, añade o abre la presentación sin ventana, con WithWindow:=0, y la ventana de PowerPoint del usuario se queda como estaba.

Probado en

Probado en: Excel 365 y PowerPoint 365 (Windows 11), VBA 7.1 — última verificación el 02/10/2026.

Guías relacionadas: VBA Word · VBA References · VBA CreateObject · VBA Outlook · VBA Chart · VBA Save as PDF · VBA DoEvents · VBA Nothing