Stampare direttamente stringhe di testo da VBA

di il
6 risposte

Stampare direttamente stringhe di testo da VBA

Buongiorno a tutti.
Ho realizzato un programma gestionale che in multi-utenza e mutli-professione (per sale coworking) gestisce anagrafica, scadenzari, chat interne, magazzino con tanto di codice a barre seppur in sola lettura, e quasi tutte le forme documentali. Tutto bene sino a quando non mi è stato richiesto di poter stampare anche degli scontrini NON fiscali che devono semplicemente riportare l'elenco degli articoli che il venditore ambulante ha consegnato. Successivamente la casa madre invierà la fattura.

E' incredibile, ma da Access sembra impossibile stampare del semplice testo su una stampante termica se non con complicatissimi codici o addirittura appoggiandosi ad eseguibili esterni. In realtà un codice l'ho trovato ma sembra essere incompatibile con Access a 64bit e nonostante Windows abbia dichiarato di voler abbandonare il 32bit non trovo codici analoghi. Ho provato anche a creare il TXT e poi cercare di lanciarlo con SHELL o file EXE di appoggio, ma nulla.

Sto facendo prove con una Zebra iMZ320 portatile collegata in cavo USB, ma dovrebbe poi lavorare in Bluetooth.

E' possibile che Access abbia questa basilare limitazione?

Ringrazio anticipatamente per chi può collaborare.

6 Risposte

  • Re: Stampare direttamente stringhe di testo da VBA

    Non so cosa intendi per complessissimi... quando si fanno certe cose occorre mettere in conto la programmazione...

    Vedi questo:


    Quel codice divrebbe essere compatibile con un S.O. 64bit ma devi guardarci...
  • Re: Stampare direttamente stringhe di testo da VBA

    Ho copiato il codice da te gentilmente linkato in un modulo (togliendo le righe che mi sembravano superflue per la prova), poi ho fatto un form apposito con il solo bottone stampa che fa riferimento a un file di testo di prova, ma mi da errore su hPrn dice che è un tipo non corrispondente perché devo ancora capire come è gestito dai 3 call che lo usano, ma sembrerebbe essere sulla strada giusta.

    'INIZIO MODULO
    Option Compare Database
    Option Explicit

    Const PRINTER_ENUM_DEFAULT = &H1
    Declare PtrSafe Function OpenPrinter Lib "winspool.drv" Alias "OpenPrinterA" (ByVal pPrinterName As String, phPrinter As LongPtr, pDefault As Any) As Long
    Declare PtrSafe Function StartDocPrinter Lib "winspool.drv" Alias "StartDocPrinterA" (ByVal hPrinter As LongPtr, ByVal Level As Long, pDocInfo As DOC_INFO_1) As Long
    Declare PtrSafe Function StartPagePrinter Lib "winspool.drv" (ByVal hPrinter As LongPtr) As Long
    Declare PtrSafe Function WritePrinter Lib "winspool.drv" (ByVal hPrinter As LongPtr, pBuf As Any, ByVal cdBuf As Long, pcWritten As Long) As Long
    Declare PtrSafe Function EndPagePrinter Lib "winspool.drv" (ByVal hPrinter As LongPtr) As Long
    Declare PtrSafe Function EndDocPrinter Lib "winspool.drv" (ByVal hPrinter As LongPtr) As Long
    Declare PtrSafe Function ClosePrinter Lib "winspool.drv" (ByVal hPrinter As LongPtr) As Long

    Private Type DOC_INFO_1
    pDocName As String
    pOutputFile As String
    pDatatype As String
    End Type

    Public Sub SpoolFile(sFile As String, PrnName As String, Optional AppName As String = "Magazzino")
    Dim hPrn As Long
    Dim buffer() As Byte
    Dim hFile As Integer
    Dim Written As Long
    Dim di As DOC_INFO_1
    Dim i As Long
    Const BufSize As Long = &H4000

    'Extract filename from passed spec, and build job name.
    'Fill remainder of DOC_INFO_1 structure.
    If InStrRev(sFile, "\") Then
    di.pDocName = Mid$(sFile, InStrRev(sFile, "\") + 1)
    Else
    di.pDocName = sFile
    End If
    If Len(AppName) Then
    di.pDocName = AppName & ": " & di.pDocName
    End If
    di.pOutputFile = vbNullString
    di.pDatatype = "RAW"

    'Open printer for output to obtain handle.
    'Set it up to begin recieving raw data.
    Call OpenPrinter(PrnName, hPrn, ByVal 0&)
    Call StartDocPrinter(hPrn, 1, di)
    Call StartPagePrinter(hPrn)

    'Open file and pump it to the printer.
    hFile = FreeFile
    Open sFile For Binary Access Read As hFile

    'Read in 16K buffers and spool.
    ReDim buffer(1 To BufSize) As Byte
    For i = 1 To LOF(hFile) \ BufSize
    Get #hFile, , buffer
    Call WritePrinter(hPrn, buffer(1), BufSize, Written)
    Next i

    ' Get last chunk of file if it doesn't
    ' fit evenly into a 16K buffer.
    If LOF(hFile) Mod BufSize Then
    ReDim buffer(1 To (LOF(hFile) Mod BufSize)) As Byte
    Get #hFile, , buffer
    Call WritePrinter(hPrn, buffer(1), UBound(buffer), Written)
    End If
    Close #hFile

    ' Shut down spooling process.
    Call EndPagePrinter(hPrn)
    Call EndDocPrinter(hPrn)
    Call ClosePrinter(hPrn)
    Kill sFile
    End Sub
    'FINE MODULO

    'INIZIO FORM
    Private Sub CmdPrint_Click()
    Dim io As Integer
    io = FreeFile
    Open "Esempio.txt" For Output As io
    Print #io, "Riga di stampa1"
    Print #io, "Riga di stampa2"
    Close #io
    Call SpoolFile("Esempio.txt", "Zebra Technologies ZTC iMZ320")
    End Sub
    'FINE FORM
  • Re: Stampare direttamente stringhe di testo da VBA

    Se guardi la Call OpenPrinter restituisce un LongPtr la.dovr usi quella.variabile, e non un Long... quindi devi fare attenzione inserendo, se serve la Compilazione Condizionale oppure gestisci le variabili in modo adeguato... il copia incolla in questi casi non va bene.

    Se non hai dimestichezza sulle API, di certo questo codice non sarà una passeggiata...
  • Re: Stampare direttamente stringhe di testo da VBA

    @Alex ha scritto:


    Se guardi la Call OpenPrinter restituisce un LongPtr la.dovr usi quella.variabile, e non un Long... quindi devi fare attenzione inserendo, se serve la Compilazione Condizionale oppure gestisci le variabili in modo adeguato... il copia incolla in questi casi non va bene.

    Se non hai dimestichezza sulle API, di certo questo codice non sarà una passeggiata...
    Visto che alla fine hai ammesso che per stampare una riga con una parola su Access (e forse non solo) è parecchio complicato?!
    In realtà il codice l'avevo già un pò modificato e appena finisco altre sezioni, dove per fortuna non si deve stampare se non da normali report, provo a capirne bene la logica. Se ci riesco riposto il codice altrimenti lascerò un argomento irrisolto anche su questo forum.
  • Re: Stampare direttamente stringhe di testo da VBA

    Non ho detto che è complicato in senso assoluto... Non fare giochetti, la.complicazione è inversamente proporzionale alla dimestichezza o se vogliamo essere più chiari, alla conoscenza ed alla padronanza tecnica.
    Le API le usano in pochi con Access perché per usarle serve un livello di conoscenza più che sufficiente... altrimenti non si capisce nemmeno la differenza della dichiarazione delle variabili
  • Re: Stampare direttamente stringhe di testo da VBA

    Ho risolto senza ricorrere al codice.
    Creo un report di larghezza pari a quella del rullo (nel mio caso 76mm) e invio la stampa su un driver apposito. L'apparecchio che mi hanno dato come prova è una Zebra e Windows mi ha installato 2 driver, semplicemente puntavo a quello sbagliato perché probabilmente il secondo driver è apposito per stampe dirette e l'altro gestisce forse codici a barre e grafiche specifiche. Purtroppo su queste funzioni so veramente poco.
    Ho risolto con il codice seguente che riporto quasi integralmente essendo inserito in un contesto più complesso. Il problema residuo è che mi scorre il rullo sino all'altezza di un foglio A4 anche se l'area con dati occupa, per esempio, solo 50 mm e non ho ancora trovato modo di dargli una altezza dinamica e il driver non sembra contemplare una opzione modulo continuo anche se non so se basterebbe.

    Private Sub CmdDocPrint_Click()
    If Doc1Doc4ID = 6 Then
    'Solo se il doc è di tipo scontrino NON fiscale (ID 6) stampo con la stampante memorizzata in apposita tabella
    'Salvo stampante predefinita
    Dim PrntPC As String
    Dim PrntGOSVEM As String
    PrntPC = Application.Printer.DeviceName
    PrntGOSVEM = Nz(DLookup("Prt1Name", "TBLPrinters", "Prt1Doc4ID=6")) 'Ricerca rapida del valore nella tabella
    'con il nome esatto della stampante assegnata per ogni tipo di documento
    'Cambio con stampante dedicata
    Application.Printer = Application.Printers(PrntGOSVEM)
    'Stampo
    Call F_Doc("PRINT")
    'Risetto stampante predefinita
    Application.Printer = Application.Printers(PrntPC)
    Else
    'Per tutti gli altri tipi di doc stampo con la default
    Call F_Doc("PRINT")
    End If
    End Sub

    Private Function F_Doc(MEMAction As String, MEMMode As String)
    'MEMAction: PREVIEW, PDF, PRINT

    'condizioni e codici vari che decidono per i vari documenti se dare l'anteprima, creare il PDF o stamparlo direttamente...

    On Error GoTo Error1
    Dim MEMReportName As String
    If MEMAction = "PRINT" Then
    DoCmd.OpenReport MEMReportName, acViewReport, , "Doc1ID = '" & Doc1ID & "'", acHidden
    DoCmd.RunCommand acCmdPrint
    DoCmd.Close acReport, MEMReportName, acSaveNo
    End If

    'altro codice....

    Error1:
    If Err.Number <> 2501 Then
    MsgBox Err.Description
    Else
    DoCmd.Close acReport, MEMReportName, acSaveNo
    End If
    End Function
Devi accedere o registrarti per scrivere nel forum
6 risposte