¿Exportaste desde Access y en Excel las columnas quedaron estrechas o con “####”? Aquí tienes la guía definitiva para autoajustar columnas y filas correctamente desde VBA en Access (o directamente en Excel) usando AutoFit
, UsedRange
y objetos Workbook/Worksheet bien referenciados.
Resumen de la pregunta
Tras exportar datos desde Access a Excel mediante una macro, las columnas del archivo resultante quedan demasiado estrechas. Se intentó usar ColumnWidth
y AutoFit
, pero no funcionó o surtió efecto en el libro equivocado. ¿Cómo autoajustar correctamente las columnas (y, si hace falta, la altura de las filas) desde VBA en Access?
Respuesta corta / Solución mínima recomendada
El punto clave es no trabajar con ActiveWorkbook.Name
(solo devuelve el nombre del libro como texto), sino con objetos reales Workbook
y Worksheet
. Además, hay que ejecutar AutoFit
cuando los datos ya están en la hoja y sobre el libro/hoja correctos.
Solución mínima (Access controlando Excel)
' 1) Exporta/crea el archivo de Excel primero
DoCmd.RunMacro "mcr_printExcel"
' 2) Obtén/crea la instancia de Excel y abre el libro correcto
Dim xlApp As Object, wb As Object, ws As Object
Dim xPath As String
xPath = Environ("HOMEDRIVE") & Environ("HOMEPATH") & "\Documents\tbl\_excel.xlsx"
On Error Resume Next
Set xlApp = GetObject(, "Excel.Application") ' usa Excel si ya está abierto
If xlApp Is Nothing Then Set xlApp = CreateObject("Excel.Application")
On Error GoTo 0
Set wb = xlApp.Workbooks.Open(xPath)
Set ws = wb.Worksheets(1)
' 3) Autoajusta columnas y filas cuando los datos ya están en la hoja
ws.UsedRange.Columns.AutoFit
ws.UsedRange.Rows.AutoFit
' (Opcional) Mostrar Excel y activar la hoja
xlApp.Visible = True
ws.Activate
Qué corrige este enfoque
- Usa objetos (
xlApp
,wb
,ws
) en lugar deActiveWorkbook.Name
. - Se asegura de que el libro esté abierto y referencia la hoja correcta.
- Aplica
AutoFit
al rango usado (UsedRange
), que suele coincidir con la zona cargada tras la exportación.
Por qué fallaba: causas técnicas habituales
- Referencia incorrecta del libro/hoja: usar
ActiveWorkbook.Name
da solo un string, no un objeto. Llamadas comoActiveWorkbook.Name.Worksheets(1)
son inválidas o actúan sobre el libro activo, que puede no ser el exportado. - Momento inadecuado: ejecutar
AutoFit
antes de que los datos estén en la hoja no tendrá efecto (no hay “contenido” que medir). - Rango inapropiado: ajustar
Cells
de toda la hoja puede ser innecesario; usarUsedRange
es más fiable tras la carga. - Elementos que bloquean: celdas combinadas, texto con ajuste (
WrapText=True
) o columnas ocultas pueden limitar el resultado del autoajuste.
Implementación paso a paso (Access → Excel)
Si controlas Excel desde Access, sigue este patrón robusto. Incluye creación/reciclaje de la instancia de Excel, apertura del libro correcto, aplicación de AutoFit
y limpieza de objetos COM.
Opción A: trabajar con el archivo ya exportado (macro previa)
Option Compare Database
Option Explicit
Public Sub ExportarYAjustar()
Dim xlApp As Object, wb As Object, ws As Object
Dim xPath As String
Dim created As Boolean```
' 1) Exporta o asegura que el archivo existe
DoCmd.RunMacro "mcr_printExcel"
' 2) Ruta de ejemplo (ajústala a tu realidad)
xPath = Environ("HOMEDRIVE") & Environ("HOMEPATH") & "\Documents\tbl_excel.xlsx"
' 3) Crea o reutiliza Excel
On Error Resume Next
Set xlApp = GetObject(, "Excel.Application")
If xlApp Is Nothing Then
Set xlApp = CreateObject("Excel.Application")
created = True
End If
On Error GoTo 0
' 4) Abre el libro y toma la primera hoja
Set wb = xlApp.Workbooks.Open(xPath)
Set ws = wb.Worksheets(1)
' 5) Autoajusta columnas y filas sobre el rango usado
' Forzamos la evaluación de UsedRange leyendo la propiedad
Dim ur As Object
Set ur = ws.UsedRange
ur.Columns.AutoFit
ur.Rows.AutoFit
' (Opcional) Muestra Excel
xlApp.Visible = True
' 6) Guarda cambios
wb.Close SaveChanges:=True
' 7) Limpieza: si creamos Excel, lo cerramos; si ya estaba abierto, lo dejamos vivo
Set ws = Nothing
Set wb = Nothing
If created Then xlApp.Quit
Set xlApp = Nothing
```
End Sub </code></pre>
<h3>Opción B: exportar desde Access con <code>TransferSpreadsheet</code> y ajustar</h3>
<pre><code class="language-vb">Public Sub ExportarConTransferYAutoFit()
Dim xlApp As Object, wb As Object, ws As Object
Dim xPath As String
Dim created As Boolean```
xPath = Environ("USERPROFILE") & "\Documents\tbl_excel.xlsx"
' Exporta una tabla o consulta a Excel (modifica los nombres a tu caso)
DoCmd.TransferSpreadsheet _
TransferType:=acExport, _
SpreadsheetType:=acSpreadsheetTypeExcel12Xml, _
TableName:="Consulta_Para_Excel", _
FileName:=xPath, _
HasFieldNames:=True
' Excel
On Error Resume Next
Set xlApp = GetObject(, "Excel.Application")
If xlApp Is Nothing Then
Set xlApp = CreateObject("Excel.Application")
created = True
End If
On Error GoTo 0
Set wb = xlApp.Workbooks.Open(xPath)
Set ws = wb.Worksheets(1)
' AutoFit completo
Dim ur As Object
Set ur = ws.UsedRange
ur.Columns.AutoFit
ur.Rows.AutoFit
xlApp.Visible = True
wb.Close SaveChanges:=True
Set ws = Nothing
Set wb = Nothing
If created Then xlApp.Quit
Set xlApp = Nothing
```
End Sub
Variantes útiles (recetas rápidas)
- Autoajustar un conjunto fijo de columnas (más rápido si tu dataset es grande):
ws.Range("A:M").EntireColumn.AutoFit
- Autoajustar todas las columnas de la hoja (desde Excel):
Sub AutoFitTodasLasColumnas() Cells.EntireColumn.AutoFit End Sub
- Autoajustar filas específicas (altura):
ws.Rows("1:700").AutoFit
- Preservar un ancho mínimo/máximo (combinar
AutoFit
+ validación):Dim c As Object For Each c In ws.Range("A:M").Columns c.AutoFit If c.ColumnWidth < 12 Then c.ColumnWidth = 12 ' mínimo If c.ColumnWidth > 50 Then c.ColumnWidth = 50 ' máximo Next c
- Tablas (ListObjects) o Pivots:
ws.ListObjects(1).Range.Columns.AutoFit ' Para pivots, después de refrescar: ws.PivotTables(1).TableRange2.Columns.AutoFit
Buenas prácticas, rendimiento y limpieza de procesos
- Evita Select/Activate: actúa sobre objetos (
ws.Range(...)
) sin seleccionar. Es más rápido y estable. - Apaga parpadeo mientras ajustas (si controlas Excel):
' Late binding: usar valores en lugar de constantes xlApp.ScreenUpdating = False ' ... tus ajustes ... xlApp.ScreenUpdating = True
- Controla la instancia de Excel: usa
GetObject
primero y almacena un flag (created
) para cerrar Excel solo si tú lo creaste. - Libera objetos COM:
Set ws = Nothing
,Set wb = Nothing
,xlApp.Quit
según corresponda. Evita procesos “EXCEL.EXE” huérfanos. - Ajuste solo del rango con datos:
UsedRange
reduce trabajo en hojas muy grandes.
Errores frecuentes y cómo diagnosticarlos
Problema | Causa probable | Solución |
---|---|---|
AutoFit no cambia nada | Se ejecuta antes de volcar datos o sobre la hoja equivocada | Asegura apertura del libro correcto y ejecuta tras la exportación. Usa Set ws = wb.Worksheets(1) y luego ws.UsedRange.Columns.AutoFit . |
Actúa sobre el libro/hoja equivocados | Uso de ActiveWorkbook o ActiveSheet sin control | Trabaja siempre con variables objeto (wb /ws ), no con “activos”. |
Texto cortado o “####” en fechas | Columnas demasiado estrechas | Aplica Columns.AutoFit después de escribir datos. Si hay WrapText , usa también Rows.AutoFit . |
Altura de fila no cambia | WrapText=True o celdas combinadas | Usa Rows.AutoFit tras asignar WrapText . Evita celdas combinadas o ajusta manualmente. |
AutoFit se salta columnas | Columnas ocultas | Desoculta antes de ajustar: .EntireColumn.Hidden = False . |
El ajuste es demasiado lento | Hoja muy grande | Limita a un rango concreto (A:M ) o usa UsedRange . Desactiva ScreenUpdating mientras tanto. |
Plantilla reutilizable de autoajuste
Este procedimiento te permite ajustar columnas/filas con control de mínimos y máximos. Funciona con late binding.
Public Sub ExcelAutoFitSheet( _
ByVal ws As Object, _
Optional ByVal columnsSpec As String = "", _
Optional ByVal rowsSpec As String = "", _
Optional ByVal minColWidth As Double = 0, _
Optional ByVal maxColWidth As Double = 0)```
Dim rngCols As Object, rngRows As Object, c As Object
' Forzar UsedRange (actualiza el "área usada")
Dim ur As Object: Set ur = ws.UsedRange
' Determinar columnas y filas a ajustar
If columnsSpec <> "" Then
Set rngCols = ws.Range(columnsSpec).EntireColumn
Else
Set rngCols = ur.Columns
End If
If rowsSpec <> "" Then
Set rngRows = ws.Range(rowsSpec).EntireRow
Else
Set rngRows = ur.Rows
End If
' Autoajuste
rngCols.AutoFit
rngRows.AutoFit
' Aplicar límites si procede
If minColWidth > 0 Or maxColWidth > 0 Then
For Each c In rngCols.Columns
If minColWidth > 0 And c.ColumnWidth < minColWidth Then c.ColumnWidth = minColWidth
If maxColWidth > 0 And c.ColumnWidth > maxColWidth Then c.ColumnWidth = maxColWidth
Next c
End If
```
End Sub </code></pre>
<h3>Uso de la plantilla</h3>
<pre><code class="language-vb">Dim xlApp As Object, wb As Object, ws As Object
Set xlApp = CreateObject("Excel.Application")
Set wb = xlApp.Workbooks.Open("C:\Ruta\archivo.xlsx")
Set ws = wb.Worksheets("Hoja1")
Call ExcelAutoFitSheet(ws, "A\:M", "1:700", 12, 50)
wb.Close SaveChanges:=True
xlApp.Quit </code></pre>
<h2>Macro desde Excel (si prefieres hacerlo allí)</h2>
<p>Si exportas desde Access pero quieres que sea el propio libro de Excel el que se “autoajuste” al abrirse, añade esto en <em>EstaHoja</em> o en <em>EsteLibro</em>:</p>
<pre><code class="language-vb">Private Sub Workbook_Open()
Dim ws As Worksheet
For Each ws In ThisWorkbook.Worksheets
ws.UsedRange.Columns.AutoFit
ws.UsedRange.Rows.AutoFit
Next ws
End Sub
</code></pre>
<p>O solo en una hoja concreta, por ejemplo tras cambios de datos:</p>
<pre><code class="language-vb">Private Sub Worksheet_Change(ByVal Target As Range)
On Error GoTo Salir
Application.ScreenUpdating = False
Me.UsedRange.Columns.AutoFit
Me.UsedRange.Rows.AutoFit
Salir:
Application.ScreenUpdating = True
End Sub
</code></pre>
<h2>Cómo funciona realmente <code>AutoFit</code> y cuándo preferir <code>ColumnWidth</code></h2>
<ul>
<li><strong><code>AutoFit</code></strong> calcula el ancho necesario para mostrar el contenido más ancho (en cada columna) según la fuente y formato actuales. Es ideal justo después de cargar datos.</li>
<li><strong><code>ColumnWidth</code></strong> fija un valor absoluto (en “caracteres” de la fuente Normal + márgenes). Úsalo cuando quieras un ancho controlado, por ejemplo códigos o IDs.</li>
<li><strong>Orden recomendado:</strong> primero <code>AutoFit</code> y después corrige con mínimos/máximos; o directamente <code>ColumnWidth</code> si conoces exactamente el tamaño deseado.</li>
<li><strong>Texto con <code>WrapText</code>:</strong> si activas el ajuste de texto, compra también <code>Rows.AutoFit</code> para que la altura acompañe.</li>
</ul>
<h2>Depuración avanzada: “AutoFit no hace nada”</h2>
<ol>
<li><strong>Confirma que <code>wb</code> y <code>ws</code> apuntan al archivo correcto:</strong> prueba <code>Debug.Print wb.FullName, ws.Name</code>.</li>
<li><strong>Fuerza <code>UsedRange</code>:</strong> lee la propiedad antes de llamar a <code>AutoFit</code> (<code>Dim ur: Set ur = ws.UsedRange</code>).</li>
<li><strong>Evita celdas combinadas:</strong> combinaciones impiden <code>AutoFit</code> fiable. Descombina temporalmente si es crítico.</li>
<li><strong>Desoculta columnas/filas:</strong> <code>EntireColumn.Hidden = False</code> / <code>EntireRow.Hidden = False</code>.</li>
<li><strong>Elimina formatos absurdos previos:</strong> anchos fijos extremos pueden engañar el ojo. Aun así, <code>AutoFit</code> los sobrescribe.</li>
<li><strong>Comprueba interferencias de tablas/pivots:</strong> en pivots, aplica después del <code>Refresh</code>.</li>
</ol>
<h2>Checklist final (rápida)</h2>
<ul>
<li>✅ Exporta o crea el archivo de Excel primero.</li>
<li>✅ Abre el libro correcto (<code>xlApp.Workbooks.Open</code>) y apunta a la hoja exacta.</li>
<li>✅ Llama a <code>ws.UsedRange.Columns.AutoFit</code> y <code>ws.UsedRange.Rows.AutoFit</code> después de volcar los datos.</li>
<li>✅ (Opcional) Limita a rangos concretos para rendimiento (<code>A:M</code>, <code>1:700</code>).</li>
<li>✅ Limpia objetos y cierra Excel solo si tú lo creaste.</li>
</ul>
<h2>Solución manual (sin código)</h2>
<ol>
<li>Abre el archivo en Excel.</li>
<li>Selecciona las columnas a ajustar (o toda la hoja con <kbd>Ctrl</kbd>+<kbd>A</kbd>).</li>
<li>Haz doble clic en el borde derecho del encabezado de cualquier columna seleccionada, o agrega “Autofit Column Width” a la Barra de herramientas de acceso rápido y ejecútalo.</li>
</ol>
<h2>Resultado práctico reportado</h2>
<p>El problema quedó resuelto al:</p>
<ul>
<li>Abrir el archivo correcto desde Access,</li>
<li>Volcar los datos,</li>
<li>Y ejecutar:</li>
</ul>
<pre><code class="language-vb">ws.Columns("A:M").AutoFit
ws.Rows("1:700").AutoFit ' si quieres forzar un rango de filas
</code></pre>
<p>Con esto, los nombres y textos quedan en una sola línea (o con altura adecuada si hay ajuste de texto) y las columnas adoptan el ancho óptimo según el contenido.</p>
<h2>Preguntas frecuentes</h2>
<p><strong>¿Puedo usar <em>early binding</em> para tener IntelliSense y constantes de Excel?</strong><br>
Sí. En el editor de VBA (Access), ve a <em>Herramientas > Referencias</em> y marca “Microsoft Excel xx.x Object Library”. Cambia las declaraciones <code>As Object</code> por <code>As Excel.Application</code>, <code>As Excel.Workbook</code>, <code>As Excel.Worksheet</code>. El resto del patrón no cambia.</p>
<p><strong>¿<code>AutoFit</code> funciona con columnas ocultas?</strong><br>
No. Debes desocultarlas antes o aplicar el autoajuste únicamente a las visibles.</p>
<p><strong>¿Por qué <code>AutoFit</code> a veces “encoge demasiado”?</strong><br>
Si tu cabecera es corta pero hay valores largos que usan salto de línea, Excel podría priorizar el contenido visible. Ajusta <code>WrapText</code> y usa límites mínimos (<code>minColWidth</code>).</p>
<p><strong>¿Conviene usar <code>Cells.EntireColumn.AutoFit</code>?</strong><br>
Es válido, pero en hojas grandes ajusta más de lo necesario. <code>UsedRange.Columns.AutoFit</code> es mejor tras la importación.</p>
<hr>
<h2>Ejemplo completo, robusto y comentado</h2>
<pre><code class="language-vb">Public Sub ExportarAExcelConAutoFit_Robusto()
Dim xlApp As Object, wb As Object, ws As Object
Dim xPath As String, created As Boolean```
' 1) Exportar
DoCmd.RunMacro "mcr_printExcel"
xPath = Environ$("USERPROFILE") & "\Documents\tbl_excel.xlsx"
' 2) Excel: crear o reutilizar
On Error Resume Next
Set xlApp = GetObject(, "Excel.Application")
If xlApp Is Nothing Then
Set xlApp = CreateObject("Excel.Application")
created = True
End If
On Error GoTo 0
' 3) Abre libro y selecciona hoja
Set wb = xlApp.Workbooks.Open(xPath)
Set ws = wb.Worksheets(1)
' 4) Rendimiento (opcional)
xlApp.ScreenUpdating = False
' 5) Autoajustes
Dim ur As Object: Set ur = ws.UsedRange
ur.Columns.AutoFit
ur.Rows.AutoFit
' 6) Límites opcionales por tipo de dato
Dim col As Object
For Each col In ws.Range("A:A").Columns
col.AutoFit
If col.ColumnWidth < 12 Then col.ColumnWidth = 12
Next col
' 7) Mostrar y guardar
xlApp.Visible = True
xlApp.ScreenUpdating = True
wb.Close SaveChanges:=True
' 8) Limpieza
Set ws = Nothing: Set wb = Nothing
If created Then xlApp.Quit
Set xlApp = Nothing
```
End Sub
Con este patrón, eliminas la ambigüedad de “qué libro/hoja estoy ajustando”, garantizas que el contenido ya está escrito cuando se calcula el ancho y evitas procesos colgados de Excel.
Conclusión: para autoajustar columnas/filas desde Access a Excel, trabaja siempre con objetos (xlApp
, wb
, ws
), llama a AutoFit
tras volcar los datos y, cuando necesites rendimiento y control fino, limita el rango a ajustar y aplica mínimos/máximos. Con los ejemplos de esta guía podrás resolver el problema de columnas estrechas de forma fiable y reutilizable.