By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
435,561 Members | 3,265 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 435,561 IT Pros & Developers. It's quick & easy.

Send Raw data to a Printer using Win32 API

P: n/a
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

Feb 16 '06 #1
Share this Question
Share on Google+
13 Replies


P: n/a
"Susan Beebe" <su***********@monsanto.com> wrote in message
news:11*********************@o13g2000cwo.googlegro ups.com...
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.

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
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)
lReturn = ClosePrinter(lhPrinter)
End Sub
-----------------------------------------------------------------------------------------------
Thanks for your help.
Susan Beebe


--
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
Feb 16 '06 #2

P: n/a
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.

Feb 16 '06 #3

P: n/a
Susan Beebe wrote:
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.
--
Working without a .NET?
http://classicvb.org/
Feb 16 '06 #4

P: n/a
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.

Feb 16 '06 #5

P: n/a
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



"Susan Beebe" <su***********@monsanto.com> wrote in message
news:11*********************@o13g2000cwo.googlegro ups.com...
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

Feb 16 '06 #6

P: n/a
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!

Feb 16 '06 #7

P: n/a
su***********@monsanto.com wrote:
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>)
--
Working without a .NET?
http://classicvb.org/
Feb 16 '06 #8

P: n/a
On Thu, 16 Feb 2006 17:32:50 -0500, "JP Bless"
<jp************@hotmail.com> wrote:
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


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.
Feb 17 '06 #9

P: n/a
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

"Susan Beebe" <su***********@monsanto.com> wrote in message
news:11*********************@o13g2000cwo.googlegro ups.com...
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

Feb 17 '06 #10

P: n/a
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



"J French" <er*****@nowhere.uk> wrote in message
news:43***************@news.btopenworld.com...
On Thu, 16 Feb 2006 17:32:50 -0500, "JP Bless"
<jp************@hotmail.com> wrote:
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


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.

Feb 17 '06 #11

P: n/a
On Fri, 17 Feb 2006 08:59:21 -0500, "JP Bless"
<jp************@hotmail.com> wrote:
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
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
Feb 17 '06 #12

P: n/a
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


"J French" <er*****@nowhere.uk> wrote in message
news:43***************@news.btopenworld.com...
On Fri, 17 Feb 2006 08:59:21 -0500, "JP Bless"
<jp************@hotmail.com> wrote:
Overflows on fast computers could be "fixed" using timers (or Sleep-API
implemented with counters). When printing large quantity of labels using afast computer the computer dumps the print job so quickly and thus overwhelmthe label printer's buffer... this sometimes cause the label printer to beerratic. 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 jobtransfer 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

Feb 17 '06 #13

P: 1
Hi Guys, can any body please give me a piece of code that shows how to print the labels over printer connected with the USB PORT

Thanks
Feb 24 '06 #14

This discussion thread is closed

Replies have been disabled for this discussion.