Autoajustar columnas en Excel desde VBA/Access: guía completa (AutoFit y ColumnWidth)

¿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.

Índice

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 de ActiveWorkbook.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 como ActiveWorkbook.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; usar UsedRange 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

ProblemaCausa probableSolución
AutoFit no cambia nadaSe ejecuta antes de volcar datos o sobre la hoja equivocadaAsegura 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 equivocadosUso de ActiveWorkbook o ActiveSheet sin controlTrabaja siempre con variables objeto (wb/ws), no con “activos”.
Texto cortado o “####” en fechasColumnas demasiado estrechasAplica Columns.AutoFit después de escribir datos. Si hay WrapText, usa también Rows.AutoFit.
Altura de fila no cambiaWrapText=True o celdas combinadasUsa Rows.AutoFit tras asignar WrapText. Evita celdas combinadas o ajusta manualmente.
AutoFit se salta columnasColumnas ocultasDesoculta antes de ajustar: .EntireColumn.Hidden = False.
El ajuste es demasiado lentoHoja muy grandeLimita 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 &gt; 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 &lt; 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.

Índice