TL;DR —
CreateObject("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.CreateObjectsiempre inicia una instancia nueva (usaGetObjectpara engancharte a una que ya se ejecuta), y todo lo que inicies debes liberarlo — haz.Quitde la app ySet 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 —
CreateObjectes 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é
CreateObjectsiempre crea una instancia nueva, y cuándo usarGetObjecten su lugar - Por qué un proceso headless de
Outlook/Excelse 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 propiaConst, 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 escrito —
CreateObject("Scripting.FileSystemObjectt"). No hay corrector ortográfico en tiempo de compilación para una cadena. - La aplicación no está instalada —
CreateObject("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. CreateObjectes nuevo;GetObjectes 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
.Quitde la app ySet 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
