MS Access Forum / General 1 / February 2006
Send Raw data to a Printer using Win32 API
|
|
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
|
|
|