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

VBA CreateObject en Excel — enlace tardío, GetObject y por qué Outlook se queda abierto

|

VBA CreateObject en Excel — enlace tardío, GetObject y por qué Outlook se queda abierto

TL;DRCreateObject("ProgID") inicia cualquier app COM por su nombre — Scripting.FileSystemObject, Outlook.Application, WScript.Shell. Como el objeto se nombra con una cadena, el compilador no puede comprobarlo: un ProgID equivocado falla en tiempo de ejecución con el error 429. CreateObject siempre inicia una instancia nueva (usa GetObject para engancharte a una que ya se ejecuta), y todo lo que inicies debes liberarlo — haz .Quit de la app y Set obj = Nothing — o dejas un proceso headless corriendo.

Sub CreateObjectDemo()
    Dim fso As Object
    Set fso = CreateObject("Scripting.FileSystemObject")   ' enlace tardio: nombrado por cadena
    Debug.Print fso.FileExists("C:\data.txt")

    Set fso = Nothing                                      ' libera lo que creaste
End Sub

CreateObject es el verbo que convierte VBA de un lenguaje de Excel en un lenguaje de automatización de Windows. Dale un ProgID — el nombre registrado de un componente COM — e inicia ese componente y te entrega un objeto que puedes manejar: lee archivos con Scripting.FileSystemObject, envía correo con Outlook.Application, ejecuta comandos con WScript.Shell. Es la herramienta más potente del lenguaje para estirarse fuera de Excel, y a cambio pide el mayor cuidado, porque el compilador está apagado para todo lo que te entrega.

Lo que aprenderás

  • El modelo mental — CreateObject es una puerta cuya llave es una cadena (un ProgID), resuelta en tiempo de ejecución
  • La decisión de verdad: enlace tardío (CreateObject) frente a enlace temprano (una referencia + New)
  • Por qué CreateObject siempre crea una instancia nueva, y cuándo usar GetObject en su lugar
  • Por qué un proceso headless de Outlook/Excel se queda corriendo, y cómo liberarlo bien
  • Qué significa el error 429 y el puñado de cosas que lo provocan
  • Cuándo preferir cada estilo — desarrolla con temprano, distribuye con tardío

El modelo mental: una puerta cuya llave es una cadena

Todo componente de Windows automatizable registra un ProgID — un nombre de texto como Scripting.Dictionary o Word.Application. CreateObject toma esa cadena, la busca en el registro de Windows en tiempo de ejecución, inicia el componente y devuelve una referencia a él:

Dim dict As Object
Set dict = CreateObject("Scripting.Dictionary")   ' busqueda en el registro por nombre -> un objeto vivo

La palabra importante es tiempo de ejecución. El objeto se nombra con una cadena, así que no se sabe nada de él mientras escribes ni cuando el proyecto compila — VBA descubre qué es dict solo cuando esa línea se ejecuta de verdad. Ese único hecho — un objeto identificado por una cadena en lugar de por un tipo declarado — es lo que significa «enlace tardío» (late binding), y gobierna cada compensación y cada trampa de abajo.

Enlace tardío frente a enlace temprano — la decisión de verdad

Hay dos formas de alcanzar un objeto COM, y elegir entre ellas es el corazón de este tema.

El enlace tardío es CreateObject con una variable Object. Sin referencia, sin tipo declarado:

Dim ol As Object
Set ol = CreateObject("Outlook.Application")   ' tardio: una cadena, un Object
Dim mail As Object
Set mail = ol.CreateItem(0)                    ' 0 = olMailItem - el nombre de la constante no esta disponible

El enlace temprano es una referencia marcada (Herramientas → Referencias → Microsoft Outlook Library) más un tipo declarado y New:

Dim ol As New Outlook.Application              ' temprano: un tipo real
Dim mail As Outlook.MailItem
Set mail = ol.CreateItem(olMailItem)           ' ahora existen constantes con nombre como olMailItem

Compilan a casi lo mismo; la diferencia es cuándo se entiende el objeto y qué obtienes a cambio:

  • Tardío (CreateObject) — portable: sin referencia que configurar, sobrevive a las diferencias de versión, se distribuye a cualquier máquina que tenga la app. Pero sin IntelliSense, las constantes con nombre (olMailItem) no existen, así que codificas a fuego sus números o declaras tu propia Const, y cada errata sale a la luz solo cuando la línea se ejecuta.
  • Temprano (New + referencia) — IntelliSense mientras escribes, el compilador pilla los miembros mal escritos, y las constantes con nombre funcionan. Pero la referencia está atada a una versión concreta de la biblioteca y puede romperse en otra máquina o en una compilación distinta de Office.

La regla práctica que sigue la mayoría de los profesionales: desarrolla con enlace temprano por el IntelliSense y las comprobaciones en compilación, y luego cambia a enlace tardío para distribuir — cambia los tipos Dim a Object, sustituye New por CreateObject, define las constantes que hayas usado, y quita la referencia. Consigues la experiencia cómoda de escritura y el entregable portable.

CreateObject crea una instancia nueva; GetObject se engancha

CreateObject siempre inicia una instancia nueva del componente. Para un ayudante sin estado como el FileSystemObject eso es justo lo correcto. Para una aplicación que el usuario quizá ya tenga abierta, es una trampa:

Set xl = CreateObject("Excel.Application")   ' inicia un SEGUNDO Excel invisible - aunque haya uno abierto

Ahora hay dos Excels, y el invisible retiene recursos que el usuario no puede ver. Cuando te refieres a el que ya se está ejecutando, usa GetObject sin ruta y con el ProgID:

Dim ol As Object
On Error Resume Next
Set ol = GetObject(, "Outlook.Application")      ' engancha a un Outlook en ejecucion, si lo hay
If ol Is Nothing Then Set ol = CreateObject("Outlook.Application")   ' si no, inicia uno
On Error GoTo 0

Este patrón de «engancha si se está ejecutando, si no arranca» es la forma correcta de automatizar una app de cara al usuario como Outlook o Excel sin generar duplicados. GetObject tiene también una segunda forma — GetObject(path) — que abre directamente el objeto de un archivo (por ejemplo un libro) sin pasar por el método Open de la aplicación. La distinción que hay que retener: CreateObject = nuevo, GetObject(, progID) = existente, GetObject(path) = un archivo como objeto.

Por qué Outlook se queda abierto: libera lo que inicias

Aquí está el fallo que todo el mundo sufre una vez. Automatizas Outlook o un segundo Excel, la macro termina, y un proceso OUTLOOK.EXE o EXCEL.EXE sigue corriendo en el Administrador de tareas sin ventana — invisible, reteniendo memoria y a veces un bloqueo de archivo. La causa: iniciaste un objeto de aplicación y nunca le dijiste que se cerrara.

Un objeto que has creado con CreateObject no desaparece cuando tu variable sale de ámbito si la app se mantiene viva por su cuenta. Debes cerrar la aplicación y liberar la referencia, idealmente en una limpieza que se ejecute incluso ante un error:

Dim ol As Object
On Error GoTo Cleanup
Set ol = CreateObject("Outlook.Application")
' ... usa ol ...

Cleanup:
    If Not ol Is Nothing Then
        ol.Quit               ' dile a la app que se cierre
        Set ol = Nothing      ' libera la referencia
    End If

Dos hábitos evitan la fuga: llama al .Quit de la app (o .Close para un libro/documento) antes de terminar, y haz Set obj = Nothing con cada objeto que creaste. Pon ambos en un manejador de errores — consulta el manejo de errores en VBA — para que una caída a mitad de macro aún limpie. Los objetos ligeros como Scripting.Dictionary o el FileSystemObject no generan un proceso y no necesitan .Quit, pero ponerlos a Nothing sigue siendo limpio.

El error con el que te toparás: 429, en tiempo de ejecución

Como el ProgID es una cadena que el compilador nunca comprueba, el fallo clásico de CreateObject aparece solo cuando la línea se ejecuta: error 429, «El componente ActiveX no puede crear el objeto». Tiene una lista corta de causas:

  • Un ProgID mal escritoCreateObject("Scripting.FileSystemObjectt"). No hay corrector ortográfico en tiempo de compilación para una cadena.
  • La aplicación no está instaladaCreateObject("Outlook.Application") en una máquina sin Outlook. El enlace tardío se distribuye a cualquier sitio, pero la app de destino debe estar realmente presente.
  • Un problema de arquitectura de bits o de registro — un componente de 32 bits en un Office de 64 bits, o un componente que nunca se registró correctamente.

Como es un error en tiempo de ejecución, protege la llamada con manejo de errores y dale al usuario un mensaje claro («Outlook no está instalado») en lugar de un 429 en crudo. Este fallo que solo aparece en ejecución es el precio del enlace tardío, y la razón por la que muchos desarrolladores escriben primero con enlace temprano: el compilador habría pillado la errata.

El veredicto honesto: la puerta a Windows, con el compilador apagado

CreateObject es el verbo más capaz para estirarse fuera de Excel — la puerta a archivos, correo, el shell, bases de datos y todas las demás apps de Office. Su poder y su peligro son la misma cosa: un objeto nombrado por una cadena, sin comprobar hasta que se ejecuta. Cuatro reglas lo mantienen seguro:

  • Es enlace tardío por cadena → un ProgID resuelto en tiempo de ejecución; una errata o una app que falta fallan con el error 429 cuando la línea se ejecuta, nunca en compilación.
  • Elige tardío o temprano a propósito → temprano (New + referencia) para el IntelliSense y las comprobaciones en compilación mientras desarrollas; tardío (CreateObject) para distribuir un archivo portable.
  • CreateObject es nuevo; GetObject es existente → usa el patrón «engancha si se está ejecutando, si no crea» para las apps de cara al usuario, y así nunca generas un duplicado invisible.
  • Libera lo que inicias → haz .Quit de la app y Set obj = Nothing, en un manejador de errores, o dejas un proceso headless reteniendo memoria y bloqueos de archivo.

Todo lo anterior vivía dentro del propio modelo de objetos de Excel, donde una llamada termina antes de la línea siguiente y un error salta a voces. Shell, Environ y CreateObject se salen de esa seguridad — y CreateObject es el que más lejos llega, entregándote un objeto que el compilador nunca vio. Respeta las cuatro reglas y es una puerta, no un campo de minas.

Cómo ayuda ExcelMaster

Los bugs de CreateObject que cuestan tiempo de verdad son los invisibles: un segundo Excel headless que se queda corriendo, un proceso de Outlook que nunca cerró, un 429 en tiempo de ejecución en una máquina a la que le falta la app, una constante de enlace tardío codificada a fuego con el número equivocado. Cada uno viene de que el compilador esté apagado para los objetos nombrados por una cadena.

ExcelMaster escribe el pegamento de automatización correctamente. Describe el trabajo — «envía este rango como un correo de Outlook» o «lee un archivo de texto con el FileSystemObject» — y produce el enlace correcto (tardío, para que se distribuya a cualquier sitio), se engancha a una app en ejecución con GetObject cuando eso es lo que quieres decir, define las constantes que le faltan al enlace tardío, y limpia cada objeto que inició en un manejador de errores. Tú describes qué app manejar; él escribe el código que la maneja y no deja nada colgando.

Preguntas frecuentes

¿Cuál es la diferencia entre CreateObject y New en VBA?

New (enlace temprano) necesita una referencia marcada a la biblioteca del componente y un tipo declarado — Dim ol As New Outlook.Application — y te da IntelliSense, comprobación en tiempo de compilación y constantes con nombre. CreateObject("Outlook.Application") (enlace tardío) nombra el componente con una cadena ProgID, no necesita referencia, y funciona entre versiones y máquinas, pero no tiene IntelliSense y falla solo en tiempo de ejecución si el nombre es incorrecto. Desarrolla con New por las herramientas, distribuye con CreateObject por la portabilidad.

¿Qué es el enlace tardío frente al enlace temprano en VBA?

El enlace temprano declara un objeto como un tipo concreto (As Outlook.Application) respaldado por una entrada en Herramientas → Referencias, así que el compilador conoce el objeto y ofrece IntelliSense y constantes con nombre. El enlace tardío lo declara como Object genérico y lo crea con CreateObject("ProgID"), así que el objeto se resuelve por cadena en tiempo de ejecución sin conocimiento del compilador. El enlace temprano es mejor para escribir; el enlace tardío es mejor para distribuir porque no depende de que esté presente una referencia concreta a una biblioteca.

¿Cómo soluciono el error «El componente ActiveX no puede crear el objeto» (error 429)?

El error 429 significa que CreateObject no pudo iniciar el ProgID que pasaste. Comprueba tres cosas: que el ProgID esté bien escrito (Scripting.FileSystemObject, no una variante); que la aplicación esté realmente instalada en esa máquina (el enlace tardío se distribuye a cualquier sitio, pero la app de destino debe estar presente); y que no haya un desajuste de arquitectura de bits (un componente de 32 bits bajo un Office de 64 bits). Envuelve la llamada en manejo de errores para que los usuarios vean un mensaje claro en lugar del 429 en crudo.

¿Cómo uso CreateObject con una aplicación ya abierta?

CreateObject siempre inicia una instancia nueva, así que para una app que el usuario quizá ya tenga abierta, usa GetObject en su lugar: Set ol = GetObject(, "Outlook.Application") se engancha a un Outlook en ejecución. El patrón seguro es «engancha si se está ejecutando, si no crea»: prueba GetObject bajo On Error Resume Next, y si el objeto Is Nothing, recurre a CreateObject. Esto evita generar una segunda copia invisible de Excel, Outlook o Word.

¿Por qué Excel o Outlook se quedan abiertos después de que mi macro termina?

Porque creaste un objeto de aplicación y nunca lo liberaste. Una app automatizada mantiene su proceso vivo hasta que llamas a .Quit y pones la referencia a Nothing. Si la macro termina — o se cae — sin hacer ambas cosas, el proceso EXCEL.EXE u OUTLOOK.EXE permanece invisible en el Administrador de tareas, reteniendo memoria y a veces un bloqueo de archivo. Pon siempre obj.Quit : Set obj = Nothing en una sección de limpieza a la que llegue un manejador de errores, para que se ejecute incluso cuando algo falla.

Probado en

Probado en: Excel 365 (Windows 11), VBA 7.1 — última verificación el 30/08/2026.

Guías relacionadas: VBA Shell · VBA Environ · VBA FileSystemObject · VBA Dictionary · VBA Outlook Automation