Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
Home
Discussion GroupsFormsForms ProgrammingQueriesModules / DAO / VBAReports / PrintingMacrosDatabase DesignSecurityConversionImporting / LinkingSQL Server / ADPMultiuser / NetworkingReplicationSetup / ConfigurationDeveloper ToolkitsActiveX ControlsNew UsersGeneral 1General 2
Access DirectoryToolsTutorialsUser Groups
Related Topics
SQL ServerOther DB ProductsMS OfficeMore Topics ...

MS Access Forum / General 1 / February 2006

Tip: Looking for answers? Try searching our database.

Send Raw data to a Printer using Win32 API

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Susan Beebe - 16 Feb 2006 18:01 GMT
I have downloaded the code described in Microsoft article Q154078.  I
am trying to send raw ZPL (zebra barcode printer) code from Microsoft
access.  It works just fine if I hard code the actual data in the
string being sent to the printer.  However, if I prompt the user for
data or if I insert data from a particular record/field in a form
Access crashes/closes on its own.

I have included the code below, if anyone has any suggestions, they
would be much appreciated.  The string being sent to the printer looks
exactly the same in the msgbox I am using to try to make sure I am
printing what I want to be printing.
------------------------------------------------------------------------------
Private Type DOCINFO
         pDocName As String
         pOutputFile As String
         pDatatype As String
End Type

     Private Declare Function ClosePrinter Lib "winspool.drv" (ByVal _
        hPrinter As Long) As Long
     Private Declare Function EndDocPrinter Lib "winspool.drv" (ByVal
_
        hPrinter As Long) As Long
     Private Declare Function EndPagePrinter Lib "winspool.drv" (ByVal
_
        hPrinter As Long) As Long
    Private Declare Function OpenPrinter Lib "winspool.drv" Alias _
        "OpenPrinterA" (ByVal pPrinterName As String, phPrinter As
Long, _
         ByVal pDefault As Long) As Long
    Private Declare Function StartDocPrinter Lib "winspool.drv" Alias
_
        "StartDocPrinterA" (ByVal hPrinter As Long, ByVal Level As
Long, _
        pDocInfo As DOCINFO) As Long
     Private Declare Function StartPagePrinter Lib "winspool.drv"
(ByVal _
        hPrinter As Long) As Long
     Private Declare Function WritePrinter Lib "winspool.drv" (ByVal _
        hPrinter As Long, pBuf As Any, ByVal cdBuf As Long, _
        pcWritten As Long) As Long

    Private Sub Command1_Click()
         Dim lhPrinter As Long
         Dim lReturn As Long
         Dim lpcWritten As Long
         Dim lDoc As Long

         Dim sWrittenData, sBatchID As String
         Dim strLine1, strLine2, strLine3 As String
         Dim MyDocInfo As DOCINFO
         lReturn = OpenPrinter("\\Server1\zebra_4mp", lhPrinter, 0)
         If lReturn = 0 Then
             MsgBox "The Printer Name you typed wasn't recognized."
             Exit Sub
         End If
       sBatchID = InputBox("Enter the batchID for which labels will be
printed", "BatchID", 1)
         MyDocInfo.pDocName = "AAAAAA"
         MyDocInfo.pOutputFile = vbNullString
         MyDocInfo.pDatatype = vbNullString
         lDoc = StartDocPrinter(lhPrinter, 1, MyDocInfo)
         Call StartPagePrinter(lhPrinter)
         strLine1 = "^XA^CFD~SD30^FS"    'indicates start of label,
and sets darkness to 30
'        strLine2 = strLine1 &
"^BY2,3,10^A0N,30,36^BCN,50,Y,N,N,N^FO20,40^FD" & "40600005" & "^FS"
'This works, 40600005 is hardcoded as batchID
       strLine2 = strLine1 &
"^BY2,3,10^A0N,30,36^BCN,50,Y,N,N,N^FO20,40^FD" & sBatchID & "^FS"
   'This crashes access, data received from user input above
       strLine3 = strLine2 & "^PQ5^XZ" '^PQ5 would print 5 copies of
the label

       MsgBox "string3 to be written is " & strLine3  ' shows what the
string looks like
       sWrittenData = strLine3 & vbFormFeed
       MsgBox "Length of string to printer is " & Len(sWrittenData)
'tells me how long the string is
       MsgBox "string to be written is " & sWrittenData  'shows what
the string looks like that will actually be printed

         lReturn = WritePrinter(lhPrinter, ByVal sWrittenData,
Len(sWrittenData), lpcWritten)
         lReturn = EndPagePrinter(lhPrinter)
         lReturn = EndDocPrinter(lhPrinter)
         lReturn = ClosePrinter(lhPrinter)
     End Sub
-----------------------------------------------------------------------------------------------
Thanks for your help.
Susan Beebe
Ken Halter - 16 Feb 2006 18:14 GMT
>I have downloaded the code described in Microsoft article Q154078.  I
> am trying to send raw ZPL (zebra barcode printer) code from Microsoft
[quoted text clipped - 16 lines]
>        MsgBox "string to be written is " & sWrittenData  'shows what
> the string looks like that will actually be printed

I've never done any VBA in Access.... and no guarantees, but, here's a
"quick and easy" thing to try anyway... send that API a byte array that's
been stripped of all Unicode related info (iow, just the string as it shows
on the screen)

  Dim b() As Byte
  b = StrConv(sWrittenData, vbFromUnicode)

  lReturn = WritePrinter(lhPrinter, b, UBound(b) + 1, lpcWritten)

>          lReturn = EndPagePrinter(lhPrinter)
>          lReturn = EndDocPrinter(lhPrinter)
[quoted text clipped - 3 lines]
> Thanks for your help.
> Susan Beebe

Signature

Ken Halter - MS-MVP-VB - Please keep all discussions in the groups..
DLL Hell problems? Try ComGuard - http://www.vbsight.com/ComGuard.htm
Freeware 4 color Gradient Frame? http://www.vbsight.com/GradFrameCTL.htm 

Susan Beebe - 16 Feb 2006 19:32 GMT
Tried this.  Nothing comes out of the printer with this.  Also, had to
change the Declare for the WritePrinter, the pBuf from As Any to as
Variant, or I got a type mismatch.  Good suggestion though!  Thanks.
Karl E. Peterson - 16 Feb 2006 20:20 GMT
> Tried this.  Nothing comes out of the printer with this.  Also, had to
> change the Declare for the WritePrinter, the pBuf from As Any to as
> Variant, or I got a type mismatch.  Good suggestion though!  Thanks.

Change pBuf back to As Any, and send b(0) rather than b.

b(0) sends a pointer to the first element of the byte array.

b sends a pointer to the Variant descriptor.
Signature

Working without a .NET?
http://classicvb.org/

susan.m.beebe@monsanto.com - 16 Feb 2006 22:34 GMT
Karl Peterson wrote:
>Change pBuf back to As Any, and send b(0) rather than b.

Great!  Worked like a champ!  Thanks very much!  Just curious, the As
Any .. what does that really mean?  As any data type?

But thanks again to you as well as Ken for heading me down the right
path!
Karl E. Peterson - 16 Feb 2006 22:45 GMT
> Karl Peterson wrote:
>> Change pBuf back to As Any, and send b(0) rather than b.
>
> Great!  Worked like a champ!  Thanks very much!  Just curious, the As
> Any .. what does that really mean?  As any data type?

Pretty much, yeah.  Strings are funky, though.  If you send any other
datatype with As Any, it sends a pointer to the data.  With Strings, you get
a pointer to the string descriptor.  (Same with Variant, I think?  I'd
pretty much *never* pass a Variant to an API, so I really don't know. <g>)
Signature

Working without a .NET?
http://classicvb.org/

Alex - 16 Feb 2006 20:50 GMT
Why not save to a text file and queue that to the printer as a job?
IIRC, Zebra has a text-only driver that you can install that allows you
to spool directly to the printer.

I did a project like this and had good success using access and
Labelview.  Easylabel 32 is easy to work with also.  With these
solutions, you still get your WYSIWYG editor for your format.

Good Luck!

Alex.
JP Bless - 16 Feb 2006 22:32 GMT
Why not print straight to port...
I have been been printing labels on Zebra printers for years by printing
straight to port and have never had problems.

Sub PrintLabel
Dim ItemName, ItemNum, ClassID
ItemName = "Expresso"
ItemNum = 142222
ClassID = "Coffee"
   Open "Com1:" for output as #1
Print #1, ItemName & " " & ItemNum & " " & ClassID
Close #1

End Sub

If you are printing to a network printer then you will need to print to the
network printer share name and by the way share name must not exceed 8
characters. So if sharename is ZebraX attached to computer Cherry

Open "\\Cherry\ZebraX" for output as #1

> I have downloaded the code described in Microsoft article Q154078.  I
> am trying to send raw ZPL (zebra barcode printer) code from Microsoft
[quoted text clipped - 85 lines]
>       End Sub
> --------------------------------------------------------------------------
---------------------
> Thanks for your help.
> Susan Beebe
J French - 17 Feb 2006 10:16 GMT
>Why not print straight to port...
>I have been been printing labels on Zebra printers for years by printing
[quoted text clipped - 8 lines]
>Print #1, ItemName & " " & ItemNum & " " & ClassID
>Close #1

Interesting, I suppose you set up the Baud etc elsewhere

Do you not get buffer overflow problems ?

When I implemented printing to a Zebra, I used the APIs, but on some
fast machines I got buffer overflows (in the Zebra)

I put it down to the USB <---> RS232 converter not raising the CTS
line fast enough.
JP Bless - 17 Feb 2006 13:59 GMT
Overflows on fast computers could be "fixed" using timers (or Sleep-API
implemented with counters). When printing large quantity of labels using a
fast computer the computer dumps the print job so quickly and thus overwhelm
the label printer's buffer... this sometimes cause the label printer to be
erratic. I notice that most Zebra desktop barcode printer models could
handle 12 or less label in a quick dump but would report errors or print
jumbled barcodes if more. So what I do is use timer to pace large print job
transfer to the barcode printer. So, no I never have overflow problems

Baudrate is handled internally in my code... See below code
The code below prints 2"x2" label using most desktop Zebra Label Printer.
The Baudrate here uses windows defaults...

Sub PrintLabel(sCompany, dResalePrice, sItemNum, sDescr)
   Dim sPrint
   Dim Crlf
Open "Com1:" For Output As #1  'Substitute right com port
      Crlf = Chr(13) & Chr(10)
       Print #1, Crlf & "N"
       Print #1, "Q1015,24"
       Print #1, "q816"
       Print #1, "S2"
       Print #1, "D8"
       Print #1, "ZT"
                 Print #1, "A240,100,0,2,1,1,N," & Chr(34) & sDescr &
Chr(34) 'Item Description
                 Print #1, "B220,120,0,1,3,1,45,B," & Chr(34) & sItemNum &
Chr(34) 'Print Human readable barcode
                 Print #1, "A400,180,0,3,2,1,N," & Chr(34) & dResalePrice &
Chr(34) 'Print bold retail price
                 Print #1, "A220,40,0,3,1,1,N," & Chr(34) & sCompany &
Chr(34) 'Print Business name in bold
        Close #1
End Sub

> >Why not print straight to port...
> >I have been been printing labels on Zebra printers for years by printing
[quoted text clipped - 18 lines]
> I put it down to the USB <---> RS232 converter not raising the CTS
> line fast enough.
J French - 17 Feb 2006 17:22 GMT
>Overflows on fast computers could be "fixed" using timers (or Sleep-API
>implemented with counters). When printing large quantity of labels using a
[quoted text clipped - 4 lines]
>jumbled barcodes if more. So what I do is use timer to pace large print job
>transfer to the barcode printer. So, no I never have overflow problems

Yes, I resorted to timeGetTime and sent an average of 3 chars per tick

>Baudrate is handled internally in my code... See below code
>The code below prints 2"x2" label using most desktop Zebra Label Printer.
>The Baudrate here uses windows defaults...

Very interesting, I shall ponder on that
JP Bless - 17 Feb 2006 19:44 GMT
Code should have been
Sub PrintLabel(sCompany, dResalePrice, sItemNum, sDescr)
   Dim sPrint
   Dim Crlf
Open "Com1:" For Output As #1  'Substitute right com port
      Crlf = Chr(13) & Chr(10)
       Print #1, Crlf & "N"
       Print #1, "Q1015,24"
       Print #1, "q816"
       Print #1, "S2"
       Print #1, "D8"
       Print #1, "ZT"
     Print #1, "A240,100,0,2,1,1,N," & Chr(34) & sDescr & Chr(34)
     Print #1, "B220,120,0,1,3,1,45,B," & Chr(34) & sItemNum & Chr(34)
     Print #1, "A400,180,0,3,2,1,N," & Chr(34) & dResalePrice & Chr(34)
     Print #1, "A220,40,0,3,1,1,N," & Chr(34) & sCompany & Chr(34)
     Print #1, "P1"
   Close #1
End Sub

> >Overflows on fast computers could be "fixed" using timers (or Sleep-API
> >implemented with counters). When printing large quantity of labels using a
[quoted text clipped - 12 lines]
>
> Very interesting, I shall ponder on that
Eric - 17 Feb 2006 13:43 GMT
Just an FYI:

If you don't want to use the API, there are a couple other ways to send data
to the printer.

1.  If it's connected via the parallel port, add a 'generic / text only'
printer and then just send

dim yourzpl as string
yourzpl = ...
printer.print yourzpl
printer.enddoc

If you don't to make the zebra the 'default' printer, you'll have to set the
printer in your code... not hard to do

If the printer is networked, just make sure the driver is the g /to

Be careful on windows 2000, SP3.  The g/t driver strips the first character
of the data  ( so you need to update the dll (there are other solutions, but
I wouldn't recommend))

2.  If the printer is attached rs232, use the winsock control

3.  Print directly to the port (as suggested by someone else)

I think the above ways are easier; Ironically, if you move to dot net your
solution will be very similar to the one you've implemented for the api
call.  That's a little tougher to figure out... If you come across it,
search 'how to send raw data to a printer with vb.net' and you'll get the
full code

>I have downloaded the code described in Microsoft article Q154078.  I
> am trying to send raw ZPL (zebra barcode printer) code from Microsoft
[quoted text clipped - 87 lines]
> Thanks for your help.
> Susan Beebe
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.