Grazie Gibra, ti riposto il codice con qualche commento. Fatto veloce perchè devo uscire.
Merto una tirata di orecchi si per come indento il codice...fa un po' pena, vedrò di migliorare.
Per quanto riguarda la stampa, purtroppo ci sono su dei nomi e non credo sia il caso di farla vedere qui, se la vuoi vedere ne scanerizzo una in pdf e te la mando in pvt.
Dimmi tu, ho provato come mi hai detto ma mi salta un sacco di righe orrizontali, dove non ho problemi e le verticali rimangono sempre sopra i testi e completamente sfasate come se la funzione pad1 non impaccasse.

Grazie

codice:
Function pad1(stringa As String, lung As Integer) As String
  pad1 = Left$(stringa & Space(lung), lung)
End Function

Function valida(dato As Variant) As String
Select Case VarType(dato)
  Case vbNull: valida = vbNullString
  Case vbInteger: valida = CStr(dato)
  Case Else: valida = dato
  End Select
End Function

Private Sub Stampa()
Screen.MousePointer = vbHourglass
Dim aColWidth(10) As Integer, aPosVLine(10) As Integer
Dim sHeader As String, bar As String, riga As String
Dim ws As Workspace, db As Database, tb As Recordset
Dim i As Integer, msup As Integer, msin As Integer, mdes As Integer, colx As Integer
Dim maxr As Integer, rec As Integer, righe As Integer, pag As Integer

bar = Chr(32)                ‘carattere spazio, per lasciare spazio alle barre verticali della griglia

For i = 0 To 10
  aColWidth(i) = CInt(Array(15, 15, 18, 16, 8, 8, 15, 8, 11, 11, 18)(i))  ‘Definisco largheza delle colonne 
     sHeader = sHeader + bar + pad1(DBGrid1.Columns(i).Caption, aColWidth(i))       ‘uso la larghezza appena impostata aColWidth(i) per costruire il  pezzo dell'intestazione delle colonne e la passo a pad1 che dovrebbe impaccare….ma !!
       aPosVLine(i) = msin + aColWidth(i) + 1 ‘corrispondente posizione di colonna per le linee verticali
       msin = aPosVLine(i)
  Next

 Set ws = DBEngine(0)                                                                     ‘proprietà del controllo Data
  Set db = ws.OpenDatabase(Data1.DatabaseName)
  Set tb = db.OpenRecordset(Data1.RecordSource)
  tb.MoveLast
  tb.MoveFirst

  Printer.Orientation = vbPRORPortrait                                              ‘proprietà della stampante
  Printer.FontName = "Courier"
  Printer.FontSize = 10
  Printer.ScaleMode = vbCharacters
  mdes = Int(Printer.ScaleWidth)
  maxr = Int(Printer.ScaleHeight) - 10
  
If maxr > tb.RecordCount Then maxr = tb.RecordCount     ‘controllo che il numero massimo di righe non sia superiore al numero di records 


  msin = (mdes - Len(sHeader)) / 2         ‘trovo il margine sinistro e (Destro) anche se non importerebbe
  colx = msin + 1
  
  For pag = 1 To tb.RecordCount Step maxr       ‘ciclo di stampa, pagina per pagina, impostando il passo sul massimo numero di righe-record stampabili
  
  Printer.CurrentY = 1
  Printer.Print Tab(colx); DBGrid1.Caption; " (pagina"; Str(pag \ maxr + 1); ")"
  Printer.Print
‘  salto le due righe di margine superiore e mi posiziono sulla terza riga, dove scrivo la Caption del controllo Data e il numero di pagina, ricavandolo con un calcolo basato sull'indice del ciclo, poi salto una riga.
  
  msup = Printer.CurrentY + 1
  
If tb.RecordCount - righe < maxr Then maxr = tb.RecordCount - righe
  Printer.CurrentY = msup + 0.04
  Printer.Print Tab(colx); sHeader
  Printer.CurrentY = Printer.CurrentY + 0.04
  Printer.Print
‘prima di stampare ogni riga posiziono la testina un po' sotto la posizione attuale per non sovrapporre righe di record a linee di griglia
  
For rec = 1 To maxr     ‘‘ciclo di stampa dei records contenibili nella pagina 
   riga = ""

For i = 0 To tb.Fields.Count - 1
  riga = riga + bar + pad1(valida(tb.Fields(i)), aColWidth(i))
Next i
‘costruisco la riga aggiungendole lo spazio bar per la fincatura verticale e il dato contenuto nel campo corrente del record corrente, dopo averlo validato con la funzione valida ed impaccato secondo la larghezza della colonna corrispondente con la funzione padl

Printer.CurrentY = Printer.CurrentY + 0.04          ‘routine di stampa
  Printer.Print Tab(colx); riga
  righe = righe + 1
  tb.MoveNext
Next rec

Printer.Line (msin, msup)-Step(Len(sHeader), 1), , B   ‘rettangolo attorno all'intestazione

For i = 1 To maxr 
Printer.Line (msin, msup + i + 1)-Step(Len(sHeader), 1), , B  ‘disegno i rettangoli attorno ad ogni riga 
Next i

For i = 0 To tb.Fields.Count – 2     ‘ qui dovrei disegnare le lineee verticali ma!
  Printer.Line (msin + aPosVLine(i), msup)-Step(0, maxr + 2)
Next i

Printer.NewPage
  Next pag
  
Printer.EndDoc

tb.Close
db.Close
Set tb = Nothing
Set db = Nothing
Set ws = Nothing
  Screen.MousePointer = vbDefault

End Sub