Introducción
Recorrer automáticamente todos los archivos de una carpeta es una de las tareas más habituales en la automatización con Excel VBA. Este tipo de macro resulta útil cuando una empresa recibe decenas o cientos de libros con una estructura similar y necesita abrirlos, leer determinados datos, consolidar información, comprobar su contenido, cambiar formatos o generar un informe conjunto.
Aunque la idea parece sencilla, una solución fiable debe resolver varios problemas prácticos: comprobar que la carpeta existe, verificar que el usuario dispone de permisos, decidir qué extensiones se procesarán, evitar archivos temporales creados por Excel y controlar los posibles errores al abrir libros dañados, protegidos o bloqueados por otro usuario.
En este artículo se desarrolla una estructura de macro reutilizable para recorrer archivos de una carpeta de forma controlada. El objetivo no es limitarse a mostrar un bucle básico, sino explicar cómo convertirlo en una solución adecuada para el trabajo real de un profesional, una microempresa o una pyme.
Índice
Qué significa recorrer los archivos de una carpeta con una macro
Recorrer una carpeta significa obtener, uno por uno, los nombres o las rutas de los archivos que contiene y ejecutar una operación sobre cada elemento encontrado. En VBA, este proceso suele realizarse mediante un bucle que continúa hasta que ya no quedan más archivos por revisar.
La macro puede limitarse a inventariar los documentos o puede abrir cada libro y trabajar con su contenido. Por ejemplo, podría acceder a una hoja determinada, leer una celda, copiar una tabla, comprobar una fecha o incorporar información a un libro maestro.
El patrón general del proceso es el siguiente:
- Obtener o solicitar al usuario la ruta de la carpeta.
- Comprobar que la ruta existe y es accesible.
- Localizar el primer archivo que cumpla los criterios establecidos.
- Descartar archivos temporales, ocultos o no válidos.
- Abrir el archivo cuando sea necesario.
- Ejecutar el tratamiento programado.
- Cerrar el archivo de forma controlada.
- Continuar con el siguiente archivo.
- Registrar los resultados y posibles incidencias.
Esta estructura puede integrarse posteriormente en una solución más amplia, como una macro para consolidar datos y preparar un informe final o un sistema para generar informes por cliente desde una plantilla de Excel.
Casos de uso habituales
Una macro que recorre archivos puede utilizarse en numerosos procesos administrativos, técnicos y comerciales. Algunos ejemplos habituales son los siguientes:
- Consolidar hojas de ventas mensuales enviadas por distintas delegaciones.
- Leer facturas o listados almacenados en varios libros.
- Extraer datos de partes de trabajo.
- Revisar si todos los archivos contienen una hoja obligatoria.
- Comprobar que determinadas celdas están cumplimentadas.
- Actualizar tablas, fórmulas o gráficos en varios libros.
- Cambiar nombres de hojas o formatos de celda.
- Generar un inventario de archivos con nombre, extensión, tamaño y fecha.
- Exportar varios informes de Excel a PDF.
- Separar o reorganizar información por clientes, proyectos o departamentos.
La principal ventaja es que el usuario deja de abrir manualmente cada archivo. Esto reduce tiempo, evita operaciones repetitivas y disminuye el riesgo de omitir documentos o copiar datos en una posición incorrecta.
Requisitos previos antes de crear la macro
Antes de escribir el código conviene definir con precisión qué debe hacer la automatización. Una macro que simplemente enumera archivos no necesita las mismas comprobaciones que otra que abre cien libros, modifica información y guarda los cambios.
Estructura de los archivos
Debe comprobarse si todos los documentos tienen una estructura homogénea. Es importante saber:
- Si las hojas tienen los mismos nombres.
- Si las columnas aparecen siempre en el mismo orden.
- Si los encabezados se encuentran en la misma fila.
- Si existen libros antiguos con un formato diferente.
- Si algunos archivos pueden estar vacíos.
- Si las hojas o libros están protegidos.
Tipos de archivo admitidos
También hay que decidir qué extensiones formarán parte del proceso. Una carpeta puede contener libros de Excel, archivos PDF, documentos de texto, imágenes y subcarpetas. La macro debe indicar expresamente qué elementos quiere procesar.
Entre las extensiones más habituales de Excel se encuentran:
.xlsx: libro de Excel sin macros..xlsm: libro habilitado para macros..xlsb: libro binario de Excel..xls: formato antiguo de Excel..csv: archivo de texto con datos separados por delimitadores.
Acción que se realizará
Debe especificarse si la macro solo leerá los libros o también los modificará. Esta decisión afecta al modo de apertura, al cierre de cada archivo y a la necesidad de realizar copias de seguridad.
Cuando el proceso todavía se realiza manualmente, puede ser útil analizar primero qué tareas de Excel deberían automatizarse y cuáles conviene mantener bajo supervisión humana.
Cómo seleccionar la carpeta que se va a procesar
La ruta puede escribirse directamente en el código, almacenarse en una celda de configuración o seleccionarse mediante una ventana de exploración. Para una herramienta que utilizarán distintos usuarios, normalmente resulta más práctico mostrar un selector de carpetas.
Función para seleccionar una carpeta
Private Function SeleccionarCarpeta() As String
```
Dim selector As FileDialog
Set selector = Application.FileDialog(msoFileDialogFolderPicker)
With selector
.Title = "Seleccione la carpeta que desea procesar"
.AllowMultiSelect = False
If .Show = -1 Then
SeleccionarCarpeta = .SelectedItems(1)
Else
SeleccionarCarpeta = vbNullString
End If
End With
Set selector = Nothing
```
End Function
La función devuelve la ruta elegida. Si el usuario cancela la ventana, devuelve una cadena vacía. La macro principal debe comprobar esta situación antes de continuar.
Ruta fija almacenada en una celda
Otra posibilidad consiste en guardar la carpeta en una hoja de configuración:
rutaCarpeta = ThisWorkbook.Worksheets("Configuracion").Range("B2").Value
Esta alternativa es útil cuando la carpeta cambia ocasionalmente y se quiere evitar modificar el código VBA. Sin embargo, conviene validar siempre el valor de la celda antes de comenzar.
Métodos disponibles en VBA para recorrer archivos
VBA permite recorrer archivos principalmente mediante la función Dir o mediante FileSystemObject. Ambos métodos son válidos, pero tienen características diferentes.
Función Dir
Dir forma parte de VBA y no requiere activar referencias adicionales. Es rápida y suficiente para muchos procesos sencillos.
Su funcionamiento básico consiste en solicitar el primer archivo que cumpla un patrón y llamar después repetidamente a Dir() sin argumentos para obtener los siguientes.
nombreArchivo = Dir(rutaCarpeta & "\*.xlsx")
Do While nombreArchivo <> vbNullString
Debug.Print nombreArchivo
nombreArchivo = Dir()
Loop
FileSystemObject
FileSystemObject ofrece objetos específicos para carpetas y archivos. Facilita el acceso a propiedades como el tamaño, la fecha de modificación o el tipo de archivo, y resulta cómodo cuando se quieren recorrer subcarpetas.
Dim sistemaArchivos As Object
Dim carpeta As Object
Dim archivo As Object
Set sistemaArchivos = CreateObject("Scripting.FileSystemObject")
Set carpeta = sistemaArchivos.GetFolder(rutaCarpeta)
For Each archivo In carpeta.Files
Debug.Print archivo.Name
Next archivo
Qué método conviene utilizar
Para una macro sencilla que busque archivos por extensión, Dir suele ser suficiente. Cuando se necesitan propiedades adicionales, una estructura orientada a objetos o un recorrido recursivo por subcarpetas, FileSystemObject puede resultar más claro.
Macro completa para recorrer todos los archivos de una carpeta
El siguiente ejemplo utiliza Dir, permite seleccionar una carpeta, procesa varios formatos de Excel, descarta archivos temporales y evita abrir el propio libro que contiene la macro.
Option Explicit
Public Sub RecorrerArchivosDeCarpeta()
Dim rutaCarpeta As String
Dim nombreArchivo As String
Dim rutaCompleta As String
Dim libroOrigen As Workbook
Dim numeroProcesados As Long
Dim numeroErrores As Long
On Error GoTo GestionErrorGeneral
rutaCarpeta = SeleccionarCarpeta()
If Len(rutaCarpeta) = 0 Then
MsgBox "No se ha seleccionado ninguna carpeta.", vbInformation
Exit Sub
End If
If Dir(rutaCarpeta, vbDirectory) = vbNullString Then
MsgBox "La carpeta seleccionada no existe o no está disponible.", vbExclamation
Exit Sub
End If
If Right$(rutaCarpeta, 1) <> "\" Then
rutaCarpeta = rutaCarpeta & "\"
End If
Application.ScreenUpdating = False
Application.EnableEvents = False
Application.DisplayAlerts = False
Application.StatusBar = "Buscando archivos..."
nombreArchivo = Dir(rutaCarpeta & "*.*")
Do While nombreArchivo <> vbNullString
rutaCompleta = rutaCarpeta & nombreArchivo
If EsArchivoProcesable(nombreArchivo) Then
If StrComp(rutaCompleta, ThisWorkbook.FullName, vbTextCompare) <> 0 Then
Application.StatusBar = _
"Procesando: " & nombreArchivo
Set libroOrigen = Nothing
On Error Resume Next
Set libroOrigen = Workbooks.Open( _
Filename:=rutaCompleta, _
UpdateLinks:=0, _
ReadOnly:=True, _
AddToMru:=False, _
Notify:=False)
On Error GoTo GestionErrorArchivo
If Not libroOrigen Is Nothing Then
ProcesarLibro libroOrigen, nombreArchivo
libroOrigen.Close SaveChanges:=False
Set libroOrigen = Nothing
numeroProcesados = numeroProcesados + 1
Else
numeroErrores = numeroErrores + 1
End If
End If
End If
SiguienteArchivo:
On Error GoTo GestionErrorGeneral
nombreArchivo = Dir()
Loop
SalidaControlada:
On Error Resume Next
If Not libroOrigen Is Nothing Then
libroOrigen.Close SaveChanges:=False
Set libroOrigen = Nothing
End If
Application.StatusBar = False
Application.DisplayAlerts = True
Application.EnableEvents = True
Application.ScreenUpdating = True
On Error GoTo 0
MsgBox _
"Proceso finalizado." & vbCrLf & vbCrLf & _
"Archivos procesados: " & numeroProcesados & vbCrLf & _
"Archivos con error: " & numeroErrores, _
vbInformation
Exit Sub
GestionErrorArchivo:
numeroErrores = numeroErrores + 1
RegistrarIncidencia _
nombreArchivo, _
Err.Number, _
Err.Description
Err.Clear
Resume SiguienteArchivo
GestionErrorGeneral:
MsgBox _
"No ha sido posible completar el proceso." & vbCrLf & _
"Error " & Err.Number & ": " & Err.Description, _
vbCritical
Resume SalidaControlada
End Sub
Private Function SeleccionarCarpeta() As String
Dim selector As FileDialog
Set selector = Application.FileDialog(msoFileDialogFolderPicker)
With selector
.Title = "Seleccione la carpeta que desea procesar"
.AllowMultiSelect = False
If .Show = -1 Then
SeleccionarCarpeta = .SelectedItems(1)
Else
SeleccionarCarpeta = vbNullString
End If
End With
Set selector = Nothing
End Function
Private Function EsArchivoProcesable( _
ByVal nombreArchivo As String) As Boolean
Dim extension As String
Dim posicionPunto As Long
EsArchivoProcesable = False
If Len(nombreArchivo) = 0 Then Exit Function
If Left$(nombreArchivo, 2) = "~$" Then Exit Function
If Left$(nombreArchivo, 1) = "." Then Exit Function
posicionPunto = InStrRev(nombreArchivo, ".")
If posicionPunto = 0 Then Exit Function
extension = LCase$(Mid$(nombreArchivo, posicionPunto + 1))
Select Case extension
Case "xlsx", "xlsm", "xlsb", "xls"
EsArchivoProcesable = True
End Select
End Function
Private Sub ProcesarLibro( _
ByVal libroOrigen As Workbook, _
ByVal nombreArchivo As String)
Dim hojaOrigen As Worksheet
Dim hojaDestino As Worksheet
Dim siguienteFila As Long
Set hojaDestino = ThisWorkbook.Worksheets("Resultado")
If ExisteHoja(libroOrigen, "Datos") Then
Set hojaOrigen = libroOrigen.Worksheets("Datos")
siguienteFila = _
hojaDestino.Cells(hojaDestino.Rows.Count, "A").End(xlUp).Row + 1
hojaDestino.Cells(siguienteFila, "A").Value = nombreArchivo
hojaDestino.Cells(siguienteFila, "B").Value = hojaOrigen.Range("B2").Value
hojaDestino.Cells(siguienteFila, "C").Value = hojaOrigen.Range("B3").Value
hojaDestino.Cells(siguienteFila, "D").Value = hojaOrigen.Range("B4").Value
Else
RegistrarIncidencia _
nombreArchivo, _
0, _
"El libro no contiene la hoja Datos."
End If
End Sub
Private Function ExisteHoja( _
ByVal libro As Workbook, _
ByVal nombreHoja As String) As Boolean
Dim hoja As Worksheet
ExisteHoja = False
For Each hoja In libro.Worksheets
If StrComp(hoja.Name, nombreHoja, vbTextCompare) = 0 Then
ExisteHoja = True
Exit Function
End If
Next hoja
End Function
Private Sub RegistrarIncidencia( _
ByVal nombreArchivo As String, _
ByVal numeroError As Long, _
ByVal descripcionError As String)
Dim hojaLog As Worksheet
Dim siguienteFila As Long
Set hojaLog = ThisWorkbook.Worksheets("Registro")
siguienteFila = _
hojaLog.Cells(hojaLog.Rows.Count, "A").End(xlUp).Row + 1
hojaLog.Cells(siguienteFila, "A").Value = Now
hojaLog.Cells(siguienteFila, "B").Value = nombreArchivo
hojaLog.Cells(siguienteFila, "C").Value = numeroError
hojaLog.Cells(siguienteFila, "D").Value = descripcionError
End Sub
El ejemplo presupone que el libro de la macro contiene dos hojas llamadas Resultado y Registro. También presupone que los libros de origen deberían incluir una hoja llamada Datos.
La parte incluida en el procedimiento ProcesarLibro es solo un ejemplo. Debe sustituirse por las operaciones concretas de cada proyecto.
Explicación detallada del código
Option Explicit
La instrucción Option Explicit obliga a declarar las variables antes de utilizarlas. Esto evita errores provocados por nombres mal escritos y mejora la fiabilidad de la macro.
Selección y validación de la carpeta
La función SeleccionarCarpeta muestra una ventana para que el usuario elija el directorio. Después, la macro comprueba que la ruta no esté vacía y que el directorio exista.
También se añade una barra invertida al final cuando sea necesaria. Sin esta normalización, la concatenación de la carpeta y el nombre del archivo podría generar una ruta incorrecta.
Búsqueda inicial
La instrucción siguiente inicia la búsqueda:
nombreArchivo = Dir(rutaCarpeta & "*.*")
El patrón *.* permite examinar todos los nombres. Posteriormente, la función EsArchivoProcesable decide cuáles deben abrirse.
Bucle principal
El bucle continúa mientras Dir devuelva un nombre:
Do While nombreArchivo <> vbNullString
' Tratamiento del archivo
nombreArchivo = Dir()
Loop
La llamada posterior a Dir() no debe incluir argumentos. Su función es devolver el siguiente archivo correspondiente a la búsqueda iniciada previamente.
Exclusión del propio libro
Si el archivo que contiene la macro está guardado dentro de la carpeta procesada, conviene impedir que intente abrirse a sí mismo:
If StrComp(rutaCompleta, ThisWorkbook.FullName, vbTextCompare) <> 0 Then
ThisWorkbook representa el libro donde está guardado el código, mientras que ActiveWorkbook representa el libro activo en ese momento. Confundir ambos objetos puede provocar que la macro escriba datos en un archivo equivocado.
Apertura en modo de solo lectura
El parámetro ReadOnly:=True reduce el riesgo de modificar accidentalmente los documentos de origen. También resulta conveniente desactivar la actualización de vínculos mediante UpdateLinks:=0.
Procedimiento independiente para procesar cada libro
Separar el tratamiento en un procedimiento denominado ProcesarLibro mejora la claridad y facilita las ampliaciones. La macro principal se ocupa del recorrido y el procedimiento secundario contiene la lógica de negocio.
Esta división es especialmente importante cuando el procesamiento incluye múltiples comprobaciones, transformaciones de datos o generación de informes.
Cómo evitar los archivos temporales que abre Excel
Cuando un libro está abierto, Excel suele crear en la misma carpeta un archivo temporal cuyo nombre comienza por ~$. Por ejemplo, al abrir Ventas.xlsx puede aparecer temporalmente un archivo llamado ~$Ventas.xlsx.
Este archivo sirve para gestionar información relacionada con el bloqueo y la edición del documento. No debe tratarse como un libro normal.
La comprobación más habitual es la siguiente:
If Left$(nombreArchivo, 2) <> "~$" Then
' El archivo puede continuar en el proceso
End If
En el ejemplo completo, esta validación se encuentra dentro de la función EsArchivoProcesable:
If Left$(nombreArchivo, 2) = "~$" Then Exit Function
Excluir los archivos temporales evita errores de apertura, mensajes inesperados y registros duplicados. También conviene descartar nombres que comiencen por punto cuando la carpeta pueda contener archivos ocultos generados por otros sistemas.
Cómo filtrar los tipos de archivo que se van a procesar
No todos los archivos de una carpeta deben abrirse con Excel. La macro debe identificar la extensión y admitir únicamente los formatos previstos.
Procesar una sola extensión
Cuando solo se quieren recorrer archivos .xlsx, puede aplicarse el filtro directamente en Dir:
nombreArchivo = Dir(rutaCarpeta & "*.xlsx")
Procesar varias extensiones
Si se quieren admitir varios formatos, resulta más flexible recorrer los nombres y evaluarlos mediante una función:
Select Case extension
Case "xlsx", "xlsm", "xlsb", "xls"
EsArchivoProcesable = True
End Select
Precauciones con archivos CSV
Los archivos CSV pueden abrirse desde Excel, pero requieren un tratamiento específico. La interpretación de separadores, fechas, decimales, codificación de caracteres y ceros iniciales puede variar según la configuración regional.
Cuando los datos contienen códigos como 000123, Excel podría convertirlos automáticamente en números y eliminar los ceros iniciales. Para procesos críticos, puede ser preferible importar el archivo mediante QueryTables, Power Query o una lectura controlada como texto.
Archivos con extensiones engañosas
La extensión ayuda a filtrar, pero no garantiza que el archivo sea válido. Un documento puede estar dañado, haber sido renombrado incorrectamente o no ser realmente un libro de Excel. Por este motivo, la apertura debe quedar protegida mediante control de errores.
Cómo abrir y procesar cada libro
Una vez identificado un archivo válido, la macro puede abrirlo y ejecutar la operación prevista. La apertura debería utilizar argumentos explícitos para evitar comportamientos inesperados.
Set libroOrigen = Workbooks.Open( _
Filename:=rutaCompleta, _
UpdateLinks:=0, _
ReadOnly:=True, _
AddToMru:=False, _
Notify:=False)
UpdateLinks
El valor 0 evita actualizar vínculos externos durante la apertura. Esto reduce esperas, avisos y riesgos cuando los libros hacen referencia a archivos que ya no existen o no están disponibles.
ReadOnly
La apertura en modo de solo lectura protege los documentos originales. Si la macro debe modificar y guardar cada libro, este parámetro tendrá que cambiarse, pero será recomendable trabajar previamente con una copia de seguridad.
AddToMru
El valor False impide que cada libro abierto por la macro se incorpore a la lista de documentos recientes de Excel.
Cierre del archivo
Después del tratamiento, el libro debe cerrarse expresamente:
libroOrigen.Close SaveChanges:=False
Si la macro solo lee datos, SaveChanges:=False es la opción más segura. Cuando se guardan cambios, conviene determinar con claridad si se sobrescribe el archivo, se crea una copia o se genera una nueva versión.
No utilizar Select ni Activate cuando no sea necesario
Una macro robusta debe trabajar directamente con variables de objeto:
valor = libroOrigen.Worksheets("Datos").Range("B2").Value
Es preferible evitar una secuencia como esta:
libroOrigen.Activate
Worksheets("Datos").Select
Range("B2").Select
valor = Selection.Value
El acceso directo es más rápido, más legible y menos dependiente de la ventana o la hoja que estén activas.
Permisos sobre el directorio
Que una carpeta sea visible en el Explorador de archivos no significa necesariamente que la macro pueda realizar todas las operaciones previstas. Los permisos pueden afectar a la lectura, apertura, modificación, creación o eliminación de documentos.
Permiso de lectura
Para inventariar o abrir documentos, el usuario necesita al menos acceso de lectura. Si no dispone de él, la función Dir podría no devolver archivos o la apertura podría generar un error.
Permiso de escritura
Si la macro debe guardar cambios, renombrar archivos, crear informes o escribir un registro dentro de la misma carpeta, también será necesario disponer de permiso de escritura.
Carpetas de red
En unidades de red pueden intervenir permisos del servidor, credenciales, desconexiones temporales, rutas compartidas y bloqueos establecidos por otros usuarios.
Una ruta con letra de unidad, como Z:\Informes\, puede funcionar en un ordenador y no existir en otro. En entornos compartidos suele ser más estable utilizar una ruta UNC:
\\Servidor\RecursoCompartido\Informes\
OneDrive, SharePoint y carpetas sincronizadas
Los archivos almacenados en servicios sincronizados pueden aparecer en el Explorador sin estar descargados físicamente. La macro podría provocar su descarga o fallar si el recurso no está disponible sin conexión.
También pueden producirse conflictos de sincronización cuando la macro modifica muchos libros en poco tiempo. En estos casos, conviene probar el proceso con una copia local antes de utilizar la carpeta definitiva.
Carpetas protegidas del sistema
No es recomendable utilizar como directorio de trabajo ubicaciones protegidas de Windows, carpetas de instalación o directorios para los que el usuario necesite privilegios administrativos.
Prueba práctica de escritura
Cuando la macro necesita guardar resultados en una carpeta, puede realizarse una prueba creando y eliminando un archivo temporal controlado. Esta comprobación permite detectar la falta de permisos antes de procesar todos los documentos.
Control de errores durante el recorrido
En una carpeta real es habitual encontrar algún archivo problemático. La macro no debería detener todo el proceso porque un único documento esté dañado, protegido o bloqueado.
Errores posibles
- El archivo está siendo utilizado por otro usuario.
- El libro está protegido por contraseña.
- El documento está dañado.
- La extensión no coincide con el contenido real.
- Falta una hoja obligatoria.
- La estructura de columnas es diferente.
- Existen vínculos externos no disponibles.
- La ruta supera limitaciones del sistema.
- La conexión con la unidad de red se interrumpe.
- El usuario pierde acceso a la carpeta durante el proceso.
Continuar con el siguiente archivo
El código debe distinguir entre un error general, que impide continuar, y un error asociado a un archivo concreto. En este último caso, lo habitual es registrar la incidencia y pasar al documento siguiente.
Restaurar siempre la configuración de Excel
Si la macro desactiva eventos, avisos o actualización de pantalla, debe restaurarlos incluso cuando se produce un error:
Application.StatusBar = False
Application.DisplayAlerts = True
Application.EnableEvents = True
Application.ScreenUpdating = True
Dejar EnableEvents desactivado puede provocar que otras macros de eventos dejen de ejecutarse. Por eso es importante disponer de una salida controlada.
Evitar On Error Resume Next de forma indiscriminada
On Error Resume Next puede ser útil para una operación muy concreta, pero no debería permanecer activo durante todo el procedimiento. De lo contrario, la macro podría ignorar fallos importantes y continuar con datos incompletos.
Cómo recorrer también las subcarpetas
La función Dir puede utilizarse para recorrer carpetas, pero una solución recursiva suele resultar más clara con FileSystemObject. El siguiente ejemplo visita una carpeta y todas las que contiene.
Option Explicit
Public Sub RecorrerCarpetaYSubcarpetas()
Dim rutaInicial As String
Dim sistemaArchivos As Object
rutaInicial = SeleccionarCarpeta()
If Len(rutaInicial) = 0 Then Exit Sub
Set sistemaArchivos = CreateObject("Scripting.FileSystemObject")
RecorrerCarpetaRecursiva _
sistemaArchivos.GetFolder(rutaInicial), _
sistemaArchivos
Set sistemaArchivos = Nothing
MsgBox "Recorrido finalizado.", vbInformation
End Sub
Private Sub RecorrerCarpetaRecursiva( _
ByVal carpetaActual As Object, _
ByVal sistemaArchivos As Object)
Dim archivo As Object
Dim subcarpeta As Object
Dim extension As String
For Each archivo In carpetaActual.Files
If Left$(archivo.Name, 2) <> "~$" Then
extension = LCase$(sistemaArchivos.GetExtensionName(archivo.Name))
Select Case extension
Case "xlsx", "xlsm", "xlsb", "xls"
Debug.Print archivo.Path
End Select
End If
Next archivo
For Each subcarpeta In carpetaActual.SubFolders
RecorrerCarpetaRecursiva subcarpeta, sistemaArchivos
Next subcarpeta
End Sub
La recursividad debe utilizarse con precaución. Si la carpeta inicial contiene miles de archivos o una estructura muy profunda, el proceso puede tardar bastante tiempo.
También conviene definir si existen subcarpetas que deben excluirse, como directorios de copias de seguridad, históricos, documentos rechazados o resultados generados por la propia macro.
Mejoras de rendimiento para procesar muchos archivos
Cuando se recorren pocos documentos, las diferencias de rendimiento apenas se perciben. Sin embargo, al trabajar con cientos o miles de libros, cada apertura, cálculo y escritura puede aumentar notablemente el tiempo total.
Desactivar temporalmente funciones de Excel
Puede resultar útil desactivar la actualización de pantalla, los eventos y los avisos:
Application.ScreenUpdating = False
Application.EnableEvents = False
Application.DisplayAlerts = False
Controlar el modo de cálculo
Si los libros contienen muchas fórmulas, puede considerarse el cálculo manual durante el proceso:
Dim modoCalculoAnterior As XlCalculation
modoCalculoAnterior = Application.Calculation
Application.Calculation = xlCalculationManual
' Proceso
Application.Calculation = modoCalculoAnterior
Debe restaurarse siempre el modo anterior al finalizar, incluso cuando se produzca un error.
Leer rangos completos en matrices
Copiar celda por celda es lento. Cuando se necesita procesar una tabla, suele ser mejor cargar el rango en una matriz:
Dim datos As Variant
datos = hojaOrigen.Range("A2:F1000").Value
Después, la información puede analizarse en memoria y escribirse en bloques.
Evitar abrir archivos innecesarios
Antes de abrir un documento, pueden evaluarse su extensión, nombre, fecha o tamaño. Si el nombre indica que ya fue procesado o pertenece a un periodo fuera del análisis, puede descartarse previamente.
Mostrar el progreso
La propiedad Application.StatusBar permite informar al usuario del archivo actual:
Application.StatusBar = "Procesando: " & nombreArchivo
Para procesos largos, también puede mostrarse el número de archivo, el total estimado y el porcentaje completado.
No guardar repetidamente el libro maestro
Guardar el libro de resultados después de cada archivo reduce el riesgo de pérdida de información, pero puede ralentizar mucho el proceso. Una solución intermedia consiste en guardar cada cierto número de documentos o al terminar cada bloque.
Registro de resultados e incidencias
Una macro empresarial no debería limitarse a mostrar un mensaje final. Es recomendable crear una hoja de registro que permita saber qué documentos se trataron y cuáles quedaron pendientes.
Datos que conviene registrar
- Fecha y hora del procesamiento.
- Nombre del archivo.
- Ruta completa.
- Extensión.
- Estado del proceso.
- Número de registros importados.
- Descripción del error.
- Tiempo empleado.
- Usuario que ejecutó la macro.
Evitar procesamientos duplicados
El registro también puede utilizarse para comprobar si un archivo ya fue tratado. No obstante, basarse únicamente en el nombre puede ser insuficiente, porque un documento podría haberse sustituido por otra versión con el mismo nombre.
Para un control más riguroso pueden compararse:
- Nombre completo.
- Ruta.
- Tamaño.
- Fecha de última modificación.
- Una huella o identificador calculado externamente.
Separar resultados y errores
En procesos amplios puede ser conveniente utilizar una hoja para los datos consolidados y otra para las incidencias. Esto facilita la revisión y evita mezclar información operativa con mensajes técnicos.
Errores habituales al crear este tipo de macro
Procesar el archivo temporal de Excel
No excluir los nombres que comienzan por ~$ provoca intentos de apertura innecesarios y errores evitables.
Intentar abrir el libro que contiene la macro
Si el libro maestro se encuentra dentro de la carpeta, debe excluirse comparando su ruta con ThisWorkbook.FullName.
Suponer que todas las hojas existen
Una referencia directa a una hoja inexistente detendrá la ejecución. Conviene comprobar primero que el libro contiene la estructura esperada.
Usar ActiveWorkbook sin control
El libro activo cambia cuando se abren documentos. Por ello, es más seguro guardar cada referencia en variables como libroOrigen y utilizar ThisWorkbook para el libro de la macro.
No cerrar libros cuando ocurre un error
Si el código salta directamente al gestor de errores, un archivo puede quedar abierto. La salida controlada debe comprobar si existe un objeto de libro pendiente y cerrarlo.
Desactivar eventos y no restaurarlos
Un fallo durante la ejecución puede dejar Excel con eventos, cálculo o actualización de pantalla desactivados. Todas estas propiedades deben restaurarse en una sección final común.
Guardar cambios sin copia de seguridad
Modificar automáticamente cientos de libros sin una copia previa puede ocasionar una pérdida difícil de revertir. Las primeras pruebas deben realizarse siempre sobre archivos duplicados.
No controlar vínculos externos
La apertura de libros con vínculos puede mostrar avisos, ralentizar el proceso o actualizar datos que no deberían cambiar. El parámetro UpdateLinks:=0 ayuda a evitarlo.
Mezclar el recorrido con toda la lógica de negocio
Incluir cientos de líneas dentro del mismo bucle dificulta el mantenimiento. Es preferible separar la selección de carpeta, validación, apertura, procesamiento, registro y cierre en procedimientos específicos.
Cuándo conviene encargar un desarrollo a medida
Una macro básica puede ser suficiente cuando todos los archivos son homogéneos y el tratamiento consiste en leer unas pocas celdas. Sin embargo, el proyecto se complica cuando existen múltiples formatos, hojas opcionales, libros protegidos, rutas de red, reglas de validación o grandes volúmenes de información.
Un desarrollo a medida puede resultar recomendable cuando:
- Los archivos proceden de distintos clientes o departamentos.
- Existen varias versiones de la plantilla.
- Los datos deben normalizarse antes de consolidarlos.
- Es necesario generar un registro detallado y recuperable.
- La macro debe reanudar el proceso después de una interrupción.
- Los libros contienen vínculos, fórmulas, tablas o gráficos complejos.
- Se necesita mantener la confidencialidad entre departamentos.
- La solución será utilizada por varios empleados.
- Un error podría afectar a facturación, contabilidad o información contractual.
En estos casos no basta con que el código funcione durante una prueba. Debe ser mantenible, comprensible, controlable y capaz de gestionar las excepciones reales del proceso.
También conviene documentar correctamente las entradas, salidas, tiempos máximos y reglas de negocio. Para preparar el encargo puede consultarse el artículo sobre qué información necesita un programador para crear una macro Excel.
Conclusión
Crear una macro para recorrer todos los archivos de una carpeta es relativamente sencillo, pero convertirla en una herramienta fiable requiere algo más que un bucle con la función Dir. La solución debe comprobar la carpeta, filtrar extensiones, ignorar archivos temporales, excluir el libro de la macro, abrir documentos de forma segura y continuar cuando aparece un archivo problemático.
También es importante distinguir entre leer y modificar documentos, controlar los permisos de la carpeta, evitar actualizaciones de vínculos y registrar los resultados. Estas medidas reducen el riesgo de pérdida de información y permiten saber exactamente qué ocurrió durante la ejecución.
La mejor estructura consiste en separar el recorrido de archivos de la lógica específica del proceso. De este modo, la misma base puede reutilizarse para consolidar datos, validar libros, actualizar informes, generar documentos independientes o automatizar otras tareas repetitivas de Excel.
Preguntas frecuentes
¿Qué función de VBA permite recorrer los archivos de una carpeta?
La función Dir permite obtener archivos que coinciden con un patrón. Se llama una primera vez con la ruta y después se utiliza Dir() sin argumentos para recuperar los siguientes archivos.
¿Cómo se evita procesar los archivos temporales de Excel?
Los archivos temporales de Excel suelen comenzar por ~$. La macro debe comprobar los dos primeros caracteres del nombre y excluir esos documentos antes de intentar abrirlos.
¿Puede la macro recorrer archivos XLSX, XLSM y XLSB?
Sí. Puede obtener la extensión de cada archivo y admitir varios formatos mediante una estructura Select Case. También puede incluir el formato antiguo .xls cuando sea necesario.
¿Es necesario abrir cada libro para leer sus datos?
En la mayoría de las macros VBA convencionales, sí. No obstante, existen alternativas como ADO, Power Query o conexiones externas que pueden leer determinados datos sin abrir visualmente cada libro.
¿Cómo se evita que la macro abra su propio libro?
Debe compararse la ruta completa del archivo encontrado con ThisWorkbook.FullName. Si ambas rutas coinciden, el archivo debe excluirse.
¿Qué ocurre si un libro está protegido por contraseña?
La apertura puede mostrar una solicitud de contraseña o producir un error. La macro debe registrar la incidencia y continuar con el siguiente archivo, salvo que se haya diseñado expresamente para gestionar contraseñas autorizadas.
¿Se pueden recorrer también las subcarpetas?
Sí. Puede utilizarse un procedimiento recursivo con FileSystemObject para visitar la carpeta inicial y todas sus subcarpetas.
¿La macro necesita permisos especiales?
Necesita permiso de lectura para localizar y abrir los archivos. Si además debe guardar cambios, crear informes, mover documentos o escribir registros en la carpeta, también necesitará permiso de escritura.
¿Conviene abrir los archivos en modo de solo lectura?
Sí, cuando la macro únicamente consulta o copia información. El modo de solo lectura reduce el riesgo de modificar accidentalmente los documentos originales.
¿Qué debe hacerse antes de probar una macro que modifica muchos archivos?
Debe crearse una copia de seguridad completa y realizar las primeras pruebas en una carpeta duplicada. No es recomendable ejecutar directamente una macro nueva sobre los únicos archivos disponibles.