AutoFit no Excel a partir do Access (VBA): guia prático com código pronto

Exportou dados do Access para o Excel e as colunas ficaram truncadas? Veja como apontar para o Workbook correto, aplicar AutoFit em colunas e linhas, ganhar desempenho e evitar armadilhas comuns do VBA ao automatizar o Excel a partir do Microsoft Access.

Índice

Contexto: por que as colunas não se autoajustam

Ao exportar dados de uma tabela no Access (por exemplo, tbl_printExcel) para o Excel via VBA, é comum que o conteúdo apareça cortado. O motivo quase sempre é uma combinação de:

  • Referência incorreta ao Excel: usar ActiveWorkbook.Name (string) em vez de manter uma variável-objeto para o Workbook e a Worksheet.
  • Ordem das operações: aplicar AutoFit antes de terminar de preencher a planilha dispara recálculos desnecessários e pode não refletir os dados finais.
  • Faixas fixas: usar Columns("A:M") limita o ajuste a 13 colunas, o que falha quando a tabela cresce.
  • Planilhas com formatação anterior: UsedRange pode estar “poluído” por estilos herdados; é preciso limpar ou calcular o intervalo usado de forma robusta.

Princípio-chave

Para um AutoFit confiável a partir do Access: capture objetos Excel explícitos (Application → Workbook → Worksheet), preencha todos os dados primeiro, e então aplique AutoFit ao UsedRange ou a um intervalo calculado dinamicamente.

Solução consolidada (passo a passo)

PassoTrecho essencial de códigoObservações / Boas práticas
Pegar o objeto corretoDim xlApp As Object, wb As Object, ws As Object On Error Resume Next Set xlApp = GetObject(, "Excel.Application") 'anexa se existir If xlApp Is Nothing Then Set xlApp = CreateObject("Excel.Application") On Error GoTo 0 Set wb = xlApp.Workbooks.Open("C:\caminho\arquivo.xlsx") Set ws = wb.Worksheets(1)Não use ActiveWorkbook.Name como se fosse objeto; mantenha variáveis-objeto para Workbook e Worksheet.
Exportar os dados'Ex.: usando CopyFromRecordset (rápido) Dim rs As DAO.Recordset Set rs = CurrentDb.OpenRecordset("SELECT * FROM tbl_printExcel", dbOpenSnapshot) 'Cabeçalhos: Dim i As Long For i = 0 To rs.Fields.Count - 1 ws.Cells(1, i + 1).Value = rs.Fields(i).Name Next 'Dados a partir da célula A2: ws.Range("A2").CopyFromRecordset rs rs.Close: Set rs = NothingEscreva tudo primeiro; evite AutoFit dentro do loop. CopyFromRecordset é bem mais rápido que célula a célula.
Autoajustar colunasws.UsedRange.Columns.AutoFitUsedRange foca no que foi realmente preenchido. Se houver formatações “fantasma”, veja a seção de diagnóstico.
(Opcional) Autoajustar linhasws.UsedRange.Rows.AutoFitÚtil quando há quebras de linha (WrapText) ou textos longos no cabeçalho.
Tornar visível e limpar objetosxlApp.Visible = True 'Feche/Quit apenas se você criou a instância 'Set ws = Nothing: Set wb = Nothing: Set xlApp = NothingLiberar recursos evita instâncias “órfãs” do Excel em segundo plano.

Código‑modelo enxuto (late binding) com tratamento de erros

Este exemplo cria (ou anexa a) uma instância do Excel, exporta a tabela tbl_printExcel, ajusta colunas e linhas, e deixa a pasta aberta ao usuário. Não requer referência ao objeto Excel no projeto do Access.

Option Explicit

'Constantes Excel (evita referência Early Binding)
Private Const xlCalculationManual As Long = -4135
Private Const xlCalculationAutomatic As Long = -4105

Sub ExportarParaExcel_AutoFit()
Const ARQUIVO As String = "C:\Caminho\saida.xlsx"
```
Dim xlApp As Object, wb As Object, ws As Object
Dim created As Boolean, calcMode As Long

On Error GoTo TrateErro

'1) Excel
Set xlApp = GetOrCreateExcel(created)

'Desempenho (restaurado no final)
calcMode = xlApp.Calculation
xlApp.ScreenUpdating = False
xlApp.Calculation = xlCalculationManual
xlApp.EnableEvents = False

'2) Abra ou crie um arquivo
If Dir$(ARQUIVO) <> "" Then
    Set wb = xlApp.Workbooks.Open(ARQUIVO)
Else
    Set wb = xlApp.Workbooks.Add
    wb.SaveAs ARQUIVO
End If
Set ws = wb.Worksheets(1)

'3) Limpe destino e escreva cabeçalhos + dados
ws.Cells.Clear
Dim rs As DAO.Recordset, i As Long
Set rs = CurrentDb.OpenRecordset("SELECT * FROM tbl_printExcel", dbOpenSnapshot)
For i = 0 To rs.Fields.Count - 1
    ws.Cells(1, i + 1).Value = rs.Fields(i).Name
Next
If Not (rs.BOF And rs.EOF) Then
    ws.Range("A2").CopyFromRecordset rs
End If
rs.Close: Set rs = Nothing

'4) AutoFit após preencher TUDO
With ws.UsedRange
    .Columns.AutoFit
    .Rows.AutoFit
End With

'5) Mostrar ao usuário
xlApp.Visible = True
wb.Activate
```
LimpeTudo:
'Restaure e limpe
On Error Resume Next
xlApp.ScreenUpdating = True
xlApp.Calculation = calcMode
xlApp.EnableEvents = True
```
Set ws = Nothing
Set wb = Nothing
If created Then
    'Se criamos o Excel, fechamos ao final (se desejar manter aberto, comente as duas linhas abaixo)
    'xlApp.Quit
End If
Set xlApp = Nothing
Exit Sub
```
TrateErro:
MsgBox "Falha ao exportar: " & Err.Number & " - " & Err.Description, vbCritical
Resume LimpeTudo
End Sub

Private Function GetOrCreateExcel(ByRef created As Boolean) As Object
On Error Resume Next
Set GetOrCreateExcel = GetObject(, "Excel.Application")
If GetOrCreateExcel Is Nothing Then
Set GetOrCreateExcel = CreateObject("Excel.Application")
created = True
End If
On Error GoTo 0
End Function 

Variante: usando DoCmd.TransferSpreadsheet e depois AutoFit

Se você prefere delegar a exportação ao Access, dá para chamar TransferSpreadsheet e apenas abrir o Excel para o AutoFit:

Sub ExportarComTransferSpreadsheet()
    Const ARQUIVO As String = "C:\Caminho\saida.xlsx"
    Const PLANILHA As String = "Dados"
```
'Exporta a tabela para o Excel (cria uma planilha nova chamada "Dados")
DoCmd.TransferSpreadsheet _
    TransferType:=acExport, _
    SpreadsheetType:=acSpreadsheetTypeExcel12Xml, _
    TableName:="tbl_printExcel", _
    FileName:=ARQUIVO, _
    HasFieldNames:=True, _
    Range:=PLANILHA

'Abre para AutoFit
Dim xl As Object, wb As Object, ws As Object
Dim created As Boolean
Set xl = GetOrCreateExcel(created)
Set wb = xl.Workbooks.Open(ARQUIVO)
Set ws = wb.Worksheets(PLANILHA)

ws.UsedRange.Columns.AutoFit
ws.UsedRange.Rows.AutoFit

xl.Visible = True
wb.Activate
```
End Sub 

Diagnóstico avançado: quando UsedRange não ajuda

Se a planilha recebeu formatações antigas, UsedRange pode ser maior que os dados reais. Nestes casos, calcule o último valor com .Cells.Find e aplique AutoFit apenas no intervalo real:

Private Sub AutoFitIntervaloReal(ws As Object)
    'Constantes Excel (late binding)
    Const xlByRows As Long = 1
    Const xlByColumns As Long = 2
    Const xlPrevious As Long = 2
```
Dim lastCell As Object, lastRow As Long, lastCol As Long
On Error Resume Next
Set lastCell = ws.Cells.Find(What:="*", After:=ws.Cells(1, 1), _
                             LookIn:=-4163, LookAt:=1, SearchOrder:=xlByRows, _
                             SearchDirection:=xlPrevious, MatchCase:=False)
On Error GoTo 0

If Not lastCell Is Nothing Then
    lastRow = lastCell.Row
    Set lastCell = ws.Cells.Find(What:="*", After:=ws.Cells(1, 1), _
                                 LookIn:=-4163, LookAt:=1, SearchOrder:=xlByColumns, _
                                 SearchDirection:=xlPrevious, MatchCase:=False)
    lastCol = lastCell.Column

    ws.Range(ws.Cells(1, 1), ws.Cells(lastRow, lastCol)).Columns.AutoFit
    ws.Range(ws.Cells(1, 1), ws.Cells(lastRow, lastCol)).Rows.AutoFit
End If
```
End Sub 

Dica: se houver células mescladas, o AutoFit pode não ampliar corretamente a altura de linhas; evite mesclas em dados tabulares.

Atalho turbo: escreva tudo de uma vez (sem loop) e só então AutoFit

Para grandes volumes, evite preencher célula a célula. Três alternativas mais rápidas:

  1. CopyFromRecordset (já mostrado): ótimo custo/benefício.
  2. Matriz Variant: carregue os dados no Access (DAO/ADO), monte uma matriz bidimensional e atribua direto ao Range de destino.
  3. QueryTable/ListObject: para fontes externas, alimente uma tabela do Excel; depois, AutoFit no intervalo da tabela.

Boas práticas indispensáveis

  • Variáveis‑objeto explícitas: mantenha xlApp, wb e ws em escopo; não confie em ActiveWorkbook / ActiveSheet.
  • AutoFit no final: somente após preencher todas as células.
  • Desempenho: para planilhas grandes, desligue ScreenUpdating, EnableEvents e coloque Calculation como manual; restaure ao fim.
  • Liberação: feche Recordset, zere objetos e chame Quit apenas se você criou o Excel.
  • Resiliência: envolva pontos críticos em On Error e restaure o Excel caso haja falhas intermediárias.
  • Intervalo dinâmico: prefira UsedRange ou a função de “última célula” a faixas fixas como "A:M".
  • Formatação: para cabeçalhos longos, aplique WrapText = True antes do AutoFit de linhas.

Exemplo completo: do Access para um arquivo novo com cabeçalhos, formato e AutoFit

Sub ExportarTbl_ComFormato()
    Const ARQUIVO As String = "C:\Caminho\relatorio.xlsx"
```
Dim xlApp As Object, wb As Object, ws As Object
Dim created As Boolean
Dim rs As DAO.Recordset, i As Long

On Error GoTo TrateErro
Set xlApp = GetOrCreateExcel(created)

xlApp.ScreenUpdating = False
Set wb = xlApp.Workbooks.Add
Set ws = wb.Worksheets(1)
ws.Name = "Relatorio"

'Dados
Set rs = CurrentDb.OpenRecordset("SELECT * FROM tbl_printExcel", dbOpenSnapshot)

'Cabeçalhos
For i = 0 To rs.Fields.Count - 1
    ws.Cells(1, i + 1).Value = rs.Fields(i).Name
Next
ws.Range("A1").Resize(1, rs.Fields.Count).Font.Bold = True
ws.Range("A1").Resize(1, rs.Fields.Count).WrapText = True

'Linhas
If Not (rs.BOF And rs.EOF) Then ws.Range("A2").CopyFromRecordset rs
rs.Close: Set rs = Nothing

'AutoFit
With ws.UsedRange
    .Columns.AutoFit
    .Rows.AutoFit
    .EntireColumn.HorizontalAlignment = -4131 'xlLeft (late binding)
End With

'Congelar painel na primeira linha
ws.Rows(2).Select
xlApp.ActiveWindow.FreezePanes = True

wb.SaveAs ARQUIVO
xlApp.Visible = True
wb.Activate
```
Limpe:
On Error Resume Next
xlApp.ScreenUpdating = True
Set ws = Nothing: Set wb = Nothing
If created Then
'xlApp.Quit 'se necessário
End If
Set xlApp = Nothing
Exit Sub

TrateErro:
MsgBox "Erro: " & Err.Number & " - " & Err.Description, vbCritical
Resume Limpe
End Sub 

Quando usar macro interna ou atalho manual

Se o usuário final puder interagir no Excel, duas alternativas simples resolvem sem mexer no Access:

  • Macro no Excel (no próprio arquivo):
Sub AutoFitColumns()
    Cells.Select
    Cells.EntireColumn.AutoFit
    Cells.EntireRow.AutoFit
End Sub
  • Barra de Ferramentas de Acesso Rápido: adicione o comando “Autofit Column Width” para um clique ajustar a planilha aberta.

Checklist de solução de problemas

  • AutoFit não muda nada? Verifique se há conteúdo de fato nas células (fórmulas vs valores vazios). Confirme que você está chamando AutoFit na Worksheet correta (ws).
  • Linhas não aumentam de altura? Ative WrapText nos cabeçalhos ou células com quebras de linha antes do AutoFit. Evite mesclar células.
  • Colunas continuam estreitas? Remova formatação antiga (ws.Cells.ClearFormats antes de escrever) ou calcule o intervalo real com .Cells.Find (veja função acima).
  • Excel fica lento? Desligue atualização de tela e cálculo automático durante a escrita; religue ao final.
  • Excel fica “preso” em segundo plano? Só chame Quit se você criou a instância (flag created = True), e sempre libere objetos.

Comparativo rápido: late binding x early binding

CritérioLate Binding (Object)Early Binding (Excel.Application)
Dependência de referênciaNão requer referência ao ExcelRequer marcar “Microsoft Excel xx.x Object Library”
IntellisenseNãoSim (tipos e constantes)
PortabilidadeAlta entre versõesPode quebrar entre versões
DesempenhoSem diferença relevante para este casoSem diferença relevante para este caso

Resumo prático

  • Guarde objetos do Excel (nada de strings de Name).
  • Preencha a planilha toda e só então chame AutoFit.
  • Use UsedRange ou calcule o intervalo real com .Find.
  • Para desempenho, escreva em bloco (CopyFromRecordset), desligue atualização/ cálculo e restaure ao final.
  • Feche e limpe com critério, evitando instâncias órfãs do Excel.

Perguntas frequentes

“Definir ColumnWidth = 50 antes do AutoFit ajuda?”
Não é necessário. O AutoFit calcula a largura ideal com base no conteúdo. Definir uma largura fixa antes só aumenta trabalho e pode atrasar a execução.

“Por que o AutoFit às vezes reduz pouco a largura?”
Porque há estilos/formatos aplicados (como formatação de número com muitos dígitos) que influenciam o cálculo. Limpar formatos antigos antes de escrever os dados costuma resolver.

“Consigo aplicar AutoFit em todas as planilhas do arquivo?”
Sim. Basta iterar:

Dim sht As Object
For Each sht In wb.Worksheets
    sht.UsedRange.Columns.AutoFit
    sht.UsedRange.Rows.AutoFit
Next

Conclusão

Ao substituir referências ambíguas por variáveis‑objeto, escrever os dados primeiro e aplicar AutoFit ao intervalo correto, o ajuste de colunas (e linhas) passa a funcionar de forma consistente após a exportação do Access para o Excel. Os exemplos acima oferecem um caminho confiável, performático e fácil de manter — do script enxuto ao modelo completo com tratamento de erros.

Índice