Wątek zablokowany 2014-11-18 08:04 przez dzek69.

Wydruk epl na drukarkę zebra przy pomocy komponentu SVRawPrinter

0

Od jakiegoś czasu bezskutecznie szukałem sposobu wydruku komend w języku EPL na drukarkę Zebra 2824 podłączoną do portu USB.
Kilka dni temu trafiłem na komponent SvRawPrinter, który pozwala na wysyłanie surowych danych na drukarkę.
Zainstalowałem, przetestowałem komponent i można powiedzieć, że połowicznie sprawa jest rozwiązana.
Chodzi o to, że ów komponent pozwala zarówno na wydruk pliku SvRawPrinter1.FilePrint(const FileName:TFileName) oraz wydruk samej komendy SvRawPrinter1.Print(const s: string).
Plik tekstowy w języku epl:

.
N
q812
S2
A50,300,0,3,2,2,R,"Example 6 0123456789"
LO25,600,750,20
B50,800,0,3,3,7,200,B,"998152-001"
P1
. 

Wydruk powyższego pliku przebiega prawidłowo.

Problem pojawia się gdy chcę wydrukować kod z poziomu komendy Print
Próbowałem w ten sposób:

SvRawPrinter1.Print('.' +
                    'N' +
                    'q812' +
                    'S2' +
                    'A50,300,0,3,2,2,R,"Example 6 0123456789"' +
                    'LO25,600,750,20' +
                    'B50,800,0,3,3,7,200,B,"998152-001"' +
                    'P1' +
                    '.');

Drukarka ani drgnie.

Pomyślałem, że może chodzi o sposób zapisu więc wrzuciłem na formatkę RichEdit'a. Wkleiłem zawartość pliku i próbowałem drukować
SvRawPrinter1.Print(RichEdit1.Text) ale również nic z tego.

Komponent został napisany 2001 roku i nie ma kontaktu z autorem.
Poniżej załączam plik .pas oraz paczkę z całym komponentem

unit SvRawPrinter;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;

type
  TSvCustomRawPrinter = class(TComponent)
  private
    { Private declarations }
    FPrinterName: string;
    FJobTitle: string;
    Handle: THandle;
    function GetPrinterName: string;
    procedure SetPrinterName(const APrinterName: string);
  protected
    { Protected declarations }
    property PrinterName: string read GetPrinterName write SetPrinterName;
    property JobTitle: string read FJobTitle write FJobTitle;
  public
    { Public declarations }
    procedure Open;
    procedure Close;
    procedure Print(const S: String);
    procedure FilePrint(const FileName: TFileName);
  published
    { Published declarations }
  end;

  TSvRawPrinter = class(TSvCustomRawPrinter)
  private
    { Private declarations }
  protected
    { Protected declarations }
  public
    { Public declarations }
  published
    { Published declarations }
    property PrinterName;
    property JobTitle;
  end;


procedure Register;

implementation
uses WinSpool;
{$R *.dcr}

function TSvCustomRawPrinter.GetPrinterName: string;
begin
Result:=FPrinterName;
end;


procedure TSvCustomRawPrinter.SetPrinterName(const APrinterName: string);
var
  P: integer;
begin
FPrinterName:=APrinterName;
P:= Pos(' on ', FPrinterName);
if P > 0
then
  FPrinterName:= Copy(FPrinterName, 1, P - 1);
end;

procedure TSvCustomRawPrinter.Open;
var
  DocInfo1: TDocInfo1;
begin
if not OpenPrinter(PChar(FPrinterName), Handle, nil)
then
  case GetLastError of
  87: Exception.create('Printer name does not exist');
  else
      Exception.create('Error ' + IntToStr(GetLastError));
  end
else
  begin
  with DocInfo1 do
    begin
    pDocName:= PChar(FJobTitle);
    pOutputFile:=nil;
    pDataType:= 'RAW';
    end;
  StartDocPrinter(Handle, 1, @DocInfo1);
  StartPagePrinter(Handle);
  end;
end;

procedure TSvCustomRawPrinter.Close;
begin
EndPagePrinter(Handle);
EndDocPrinter(Handle);
ClosePrinter(Handle);
end;


procedure TSvCustomRawPrinter.Print(const S: String);
var
  N: DWord;
begin
WritePrinter(Handle, PChar(S), Length(S), N);
if DWord(Length(S)) <> N
then
  Exception.create('Error writing to printer');
end;

procedure TSvCustomRawPrinter.FilePrint(const FileName: TFileName);
var
  FromF: File;
  NumRead: Integer;
  Buf: array[1..2048] of Char;
  SBuf: string;
begin
AssignFile(FromF, FileName);
Reset(FromF, 1);	{ Record size = 1 }
try
  Open;
  try
    BlockRead(FromF, Buf, SizeOf(Buf), NumRead);
    while (NumRead > 0 ) do
      begin
      SBuf:= Buf;
      SetLength(SBuf, NumRead);
      Print(SBuf);
      BlockRead(FromF, Buf, SizeOf(Buf), NumRead);
    end
  finally
    Close;
  end;
finally
  CloseFile(FromF);
end;
end;


procedure Register;
begin
  RegisterComponents('Sv', [TSvRawPrinter]);
end;

end.

http://www.delphipages.com/comp/svrawprinter-4217.html

1

Nigdy nie musiałem tak wysyłać danych na drukarkę, jak i nie używałem nigdy takiej drukarki. Ale może problem jest w znaku końca linii. Ponieważ pokazujesz przykładowy plik z oddzielnymi linijkami. Późnej wysyłasz go jako jeden ciąg znaków, co może powodować że nie osiągasz oczekiwanych rezultatów. Natomiast po drukowaniu z RichEdita to raz, że ma on domyślnie własnośc PlainText ustawioną na False, a wiec nie wysyłasz tego co byś chciał (zobacz co zapisze się do pliku z własności Lines). Także lepiej to robić z pod Memo, a wcześniej przypisać jego własność Text do zmiennej typu string. Dla pewności usunąc ostatnią pustą linijkę - znaku końca linii. I jeżeli to nie pomoże, to dla pewności zamienić funkcją StringReplace znaki końca lini z #13#10 na Unixowe #10. Jeśli i to nie pomoże, to nie mam więcej pomysłów, więc może ktoś inny coś tutaj jeszcze Tobie konkretnego oraz skutecznego doradzi w tym temacie.

0

po każdej komendzie musi być znak końca linii. Masz to w dokumentacji do EPLa

0

Próbuje tak ale bez skutku.

const LF = #10;
SvRawPrinter1.Print('N' +LF+ 'A50,50,0,2,1,1,N,"test"' +LF+ 'P1'+LF);

Próbowałem również LF = #10#13 ale również nic. :/

Taki zapis miałeś na myśli?

0

Może podejrzyj kod który podałeś.
FilePrint czyta plik kawałkami po 2048 bajtów i wrzuca to na drukarkę za pomocą Print więc jeżeli ci działa z plikiem o zawartości:

.
N
q812
S2
A50,300,0,3,2,2,R,"Example 6 0123456789"
LO25,600,750,20
B50,800,0,3,3,7,200,B,"998152-001"
P1
.

To nie może nie działać podane na żywca:

SvRawPrinter1.Open;
SvRawPrinter1.Print
(
  '.'#13#10+
  'N'#13#10+
  'q812'#13#10+
  'S2'#13#10+
  'A50,300,0,3,2,2,R,"Example 6 0123456789"'#13#10+
  'LO25,600,750,20'#13#10+
  'B50,800,0,3,3,7,200,B,"998152-001"'#13#10+
  'P1'#13#10+
  '.'#13#10
);
SvRawPrinter1.Close;

Można ten tekst zapisać jako stałą:

const RBuf:String=
  '.'#13#10+
  'N'#13#10+
  'q812'#13#10+
  'S2'#13#10+
  'A50,300,0,3,2,2,R,"Example 6 0123456789"'#13#10+
  'LO25,600,750,20'#13#10+
  'B50,800,0,3,3,7,200,B,"998152-001"'#13#10+
  'P1'#13#10+
  '.'#13#10
;

//Wywołać tak:
SvRawPrinter1.Open;
SvRawPrinter1.Print(RBuf);
SvRawPrinter1.Close;

Zatrzymać się debugerem na wierszu:
Print(SBuf);
Sprawdzić czy są równe <Ctrl-F7> RBuf=SBuf <Enter>
A jak nie równe to szukać różnicy.

0

Nie drukuje. Zadanie pokazuje się w kolejce wydruku ale po chwili znika.

Nie wiem jak dostać się do zmiennej sbuf. W oknie Evaluate/Modify jest dostęp tylko do Rbuff.
Bufor Rbuf ma następującą postać:
'.'#$D#$A'N'#$D#$A'q812'#$D#$A'S2'#$D#$A'A50,300,0,3,2,2,R,"Example 6 0123456789"'#$D#$A'LO25,600,750,20'#$D#$A'B50,800,0,3,3,7,200,B,"998152-001"'#$D#$A'P1'#$D#$A'.'#$D#$A
Zdziwiła mnie obecność apostrofów. Jeżeli ten string jest wysyłany do drukarki to chyba one są winne. Próbowałem przypisać do stałej string w postaci 'xxxxxxxxxxx' pomijając wewnętrzne apostrofy ale wtedy #13#10 jest również wysyłane na drukarkę.

0

Dostałem się do zmiennej SBuff przy wydruku z pliku tekstowego. Jej zawartość w momencie Print(Sbuff) jest następująca:
'മ上'#$0A0D'㡱㈱'#$0A0D'㉓'#$0A0D'㕁ⰰ〵〬㈬ㄬㄬ丬∬硅浡汰'#$2065'′'#$3130'㌲㔴㜶㤸ഢ倊റ⸊'#$14''#$18'涑疢浑疢ꡏ੬'#$D#0'뒕燛'#$18'$'#0#1#0#0#0#0#0'p'#0#$FFFF#$FFFF#$FFFF#$FFFF'泩疢'
Wydawałoby się, że to są jakieś śmieci ale

SvRawPrinter1.Print
(
'മ上'#$0A0D'㡱㈱'#$0A0D'㉓'#$0A0D'㕁ⰰ〵〬㈬ㄬㄬ丬∬硅浡汰'#$2065'′'#$3130'㌲㔴㜶㤸ഢ倊റ⸊'#$1D''#$18'涑疢浑疢㈛楁'#$D#0'뒕燛'#$18'$'#0#1#0#0#0#0#0'p'#0#$FFFF#$FFFF#$FFFF#$FFFF'泩疢'
);

powoduje prawidłowy wydruk etykiety z napisem "Example 2 0123456789" :/
Jak to interpretować? Może to sprawa kodowania?

0

Nie wiem co próbujesz zrobić ale może napiszę Ci co u mnie działa na 100%.

  1. Drukarka podłączona przez kabel USB
  2. Drukarka ta musi być zainstalowana i widoczna w panelu sterowania\drukarki jako normalna drukarka
  3. drukarka obsługuje język EPL
  4. Do drukowania używam takiego kodu
unit RawPrinter;

interface

uses SysUtils, Windows, WinSpool;

type
  TRawPrinter = class(TObject)
  private
    FIsOpen: Boolean;
    FHandle: THandle;
    FBytesWritten: DWord;
    FDocInfo: TDocInfo1;
    FPrinterName: string;
    FDocument: string;
  public
    constructor Create;
    function Open: Boolean; 
    function Close: Boolean;
    function Write(AText: string): Boolean;

    property Document: string read FDocument write FDocument; //nazwa dokumentu jaka pokaże się w zasobniku drukarki
    property PrinterName: string read FPrinterName write FPrinterName; //nazwa drukarki, na którą ma iść wydruk
end; 


implementation 

constructor TRawPrinter.Create;
begin 
  FIsOpen:=False;
  FDocument:='TestDoc';
  FPrinterName:='';
end; 

function TRawPrinter.Open: Boolean;
begin
  Result:=False;
  if not FIsOpen then
  begin
    if FPrinterName <> '' then
    begin
      if FDocument = '' then
        Document:='TestDoc';

      with FDocInfo do
      begin
        pDocName := PChar(FDocument);
        pOutputFile := nil;
        pDatatype := 'RAW';
      end;

      Result := OpenPrinter(PChar(FPrinterName), FHandle, nil);

      if Result then
        if StartDocPrinter(FHandle, 1, @FDocInfo) = 0 then
        begin
          Result := False;
          ClosePrinter(FHandle);
        end;
    end;
    FIsOpen := Result;
  end; 
end; 

function TRawPrinter.Close: Boolean;
begin
  Result := True;
  if FIsOpen then
    Result := ClosePrinter(FHandle);
  FIsOpen := False;
end; 

function TRawPrinter.Write(AText: string): Boolean;
var
  Buffer: string;
begin
  Result := False;
  Buffer := AText;

  if FIsOpen then
    Result := WritePrinter(FHandle, @Buffer[1], Length(Buffer), FBytesWritten); 
end; 

end. 

i samo drukowanie

var
  RawPrn: TRawPrinter;
begin
  RawPrn := TRawPrinter.Create;
  try
    RawPrn.PrinterName := 'nazwa drukarki';
    if RawPrn.Open then
    begin
      RawPrn.Write(mmoFile.Text);
      RawPrn.Close;
    end;
  finally
    RawPrn.Free;
  end;
end;

pozwala to wydrukować np. taką etykietę

N
ZB
q456
I8,B
B19,401,0,1,2,2,39,B,"00001230000000150002450"
A102,46,0,2,2,2,N,"01.08.2013"
A129,98,0,3,2,2,N,"2.45kg"
A38,148,0,2,1,1,N,"Partia:"
A232,146,0,2,1,1,N,"0150"
A189,231,0,3,1,3,N,"KARK"
A18,306,0,1,1,1,N,"Nr kierunku:"
A19,325,0,1,1,1,N,"Operator:"
A227,326,0,1,1,1,N,"Tara:KG"
A18,350,0,1,1,2,N,"Spozyć do:20.08.2013"
P1

Po każdej linii musi być znak końca linii #13#10 jeśli chcesz to przypisać do zmiennej lub możesz to wstawić do np. memo i drukować po prostu mmoFile.Text tylko wtedy pamiętaj żeby na końcu była pusta linia

0

Również brak wydruku powyższego kodu EPL. Natomiast wrzucenie, śmieci, o których wspomniałem powoduje podanie pustej etykiety :/ . Drukarka jest sprawna, drukuje etykiety z programu Zebra Label Designer oraz powyższy kod EPL ale odczytany z pliku tekstowego.

0

w poniedziałek daj znać to Ci podeślę exe, którym testuje drukarki. Jaka to drukarka? Bo wygląda mi, że to nie jest EPL

0

dodaje załącznik z kodem i exe

Zanim cokolwiek zaczniesz działać wydrukuj ustawienia drukarki (zobacz w instrukcji jak)

0

Uruchomienie programu ZebraUSBTest.exe z katalogu EXE i kliknięcie na Test EPL powoduje wydruk prawidłowej etykiety.
Po uruchomieniu i skompilowaniu projektu z pliku dpr w kolejce wydruku pojawia się zadanie ale wydruku brak.

3

pewnie jakieś nowsze delphi :) - założę się, że problemem jest UTF. Podmień plik RawPrinter.pas na poniższy i zobacz czy pomoże

unit RawPrinter;

interface

uses SysUtils, Windows, WinSpool;

type
  TRawPrinter = class(TObject)
  private
    FIsOpen: Boolean;
    FHandle: THandle;
    FBytesWritten: DWord;
    FDocInfo: TDocInfo1;
    FPrinterName: string;
    FDocument: string;
  public

    constructor Create;
    function Open: Boolean;
    function Close: Boolean;
    function Write(AText: AnsiString): Boolean;

    property Document: string read FDocument write FDocument;
    property PrinterName: string read FPrinterName write FPrinterName;
end; 


implementation 

constructor TRawPrinter.Create;
begin 
  FIsOpen:=False;
  FDocument:='TestDoc';
  FPrinterName:='';
end; 

function TRawPrinter.Open: Boolean;
begin
  Result:=False;
  if not FIsOpen then
  begin
    if FPrinterName <> '' then
    begin
      if FDocument = '' then
        Document:='TestDoc';

      with FDocInfo do
      begin
        pDocName := PChar(FDocument);
        pOutputFile := nil;
        pDatatype := 'RAW';
      end;

      Result := OpenPrinter(PChar(FPrinterName), FHandle, nil);

      if Result then
        if StartDocPrinter(FHandle, 1, @FDocInfo) = 0 then
        begin
          Result := False;
          ClosePrinter(FHandle);
        end;
    end;
    FIsOpen := Result;
  end; 
end; 

function TRawPrinter.Close: Boolean;
begin
  Result := True;
  if FIsOpen then
    Result := ClosePrinter(FHandle);
  FIsOpen := False;
end; 

function TRawPrinter.Write(AText: AnsiString): Boolean;
var
  Buffer: AnsiString;
begin
  Result := False;
  Buffer := AText;

  if FIsOpen then
    Result := WritePrinter(FHandle, @Buffer[1], Length(Buffer), FBytesWritten); 
end; 

end.
0

Działa. Podmiana zawartości pomogła.

1 użytkowników online, w tym zalogowanych: 0, gości: 1