Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Impresión (https://www.clubdelphi.com/foros/forumdisplay.php?f=4)
-   -   Impresora Zebra GC420 con EPL (https://www.clubdelphi.com/foros/showthread.php?t=86347)

hgiacobone 23-07-2014 22:08:13

Impresora Zebra GC420 con EPL
 
Saludos colegas,
Tengo que lograr generar una etiqueta con codigos de barras en una impresora Zebra GC420, pero no tengo suerte con las pruebas.
Entiendo que hubo varios foros tratando temas similares, pero en ninguno hay una solución factible.

Primero, este dispositivo se comunica por puerto USB, que es como el viejo Serial, pero tiene asignación dinamica por parte del SO (USB001, USB002,...) con lo cual es dificil determinar en donde está ubicada la impresora. Por ahora, yo trato de ubicarla mediante el "nombre" del dispositivo, haciendo un llamado a la funcion Printer de la unit Printers, ago asi:
Código Delphi [-]
unit MiPrograma;

interface

uses
..., Printers,...
//
//
procedure TForm1.IniciandoModulo();  
begin
  //Esto es para listar las impresoras disponibles, incluso la impresora USB
  ComboBox1.Items.Clear;
  ComboBox1.Items.AddStrings(Printer.Printers);
{...}
end;

Segundo problema, es que a mi me pasan un archivo TXT con toda la instruccion EPL necesaria. Aqui un ejemplo del txt :
Código:

I8,A,001


Q508,024
q863
rN
S3
D7
ZT
JF
OD
R25,0
f100
N
B200,189,0,E30,4,8,130,B,"3836556465461"
A99,31,0,4,6,6,N,"Esto es un ejemplo"
P1

Puede que este archivo sea incorrecto, porque en otros foros he visto que las secuencias deben comenzar con el prefijo "^" que aqui está ausente, pero, el driver de la impresora (Dispositivo de impresion->Propiedades) permite cargar y enviar un fichero externo y al cargar ese fichero lo imprime bien. Lo que desconozco es si antes lo pre-procesa de alguna forma.

La rutina de impresión se basa en una rutina ya conocida para enviar comandos RAW (muy utilizado con impresoras para POS) y es la siguiente:
Código Delphi [-]
procedure TForm1.Imprimir();
var
  fTextFile, fPrnFile:TextFile;
  sPRN, s, s1: string;   
begin
 
  //Con este OpenDialog recupero el archivo TXT que necesito imprimir
  TRY
    s:= GetCurrentDir;
    ChDir(s);
    OpenDialog1.InitialDir:= s;
  EXCEPT
    try
      s:= ExtractFilePath(paramStr(0));
      ChDir(s);
      OpenDialog1.InitialDir:= s;
    except
        s:= PathInicial; //DataMod
        ChDir(s);
        OpenDialog1.InitialDir:= s;
    end;
  END;

  if OpenDialog1.Execute then
  begin
      try

        sPRN:= Trim(ComboBox1.Text); //Aqui se toma la impresora Zebra por USB

        AssignFile(fTextFile, OpenDialog1.FileName );
        Reset(fTextFile);
              try
                While Not Eof(fTextFile) Do
                begin
                  ReadLn(fTextFile, s);
                  WriteRawDataToPrinter(sPRN, s);  //PRUEBA 1: con esto pretendo enviar instrucciones linea a linea y no funciona
                  s1:= s1 + s;
                end;

              //  WriteRawDataToPrinter(sPRN, s1); //PRUEBA 2: con esto pretendo enviarlo todo junto y tampoco funciona

              except
                on E:Exception do MessageDlg(E.Message, mtWarning, [mbOk],0);
              end;
      finally
        CloseFile(fTextFile);
      end;
  end;
end;

//----------------------------------------------

{--la siguiente funcion se encuentra en otra unit pero es indistinto---}
function WriteRawDataToPrinter(PrinterName: String; Str: String): Boolean;
var
  PrinterHandle: THandle;
  DocInfo: TDocInfo1;
  i: Integer;
  B: Byte;
  Retorna: DWORD;
begin
  Result:= FALSE;
  if OpenPrinter(PChar(PrinterName), PrinterHandle, nil)
  then try
      FillChar(DocInfo,Sizeof(DocInfo),#0);
      with DocInfo do
      begin
        pDocName:= PChar('Etiqueta...');
        pOutputFile:= nil;
        pDataType:= 'RAW';
      end;
      if StartDocPrinter(PrinterHandle, 1, @DocInfo) <> 0 then
      try
        if StartPagePrinter(PrinterHandle) then
        try
          while Length(Str) > 0 do
          begin
            if Copy(Str, 1, 1) = '\' then
            begin
              if Uppercase(Copy(Str, 2, 1)) = 'X' then
                Str[2]:= '$';
              if not TryStrToInt(Copy(Str, 2, 3),i) then
                Exit;
              B:= Byte(i);
              Delete(Str, 1, 3);
            end else B:= Byte(Str[1]);
            Delete(Str,1,1);
            WritePrinter(PrinterHandle, @B, 1, Retorna);
          end;
          Result:= TRUE;
        finally
          EndPagePrinter(PrinterHandle);
        end;
      finally
        EndDocPrinter(PrinterHandle);
      end;
  finally
    ClosePrinter(PrinterHandle);
  end;
end;

La cosa es que con esto la impresora ni se inmuta...:mad:
Alguna sugerencia al formato del archivo; a la forma de enviar la secuencia y/o al código en general?

orodriguezca 23-07-2014 22:31:34

Que versión de Delphi utilizas?, en cualquier versión posterior a Delphi 2009 se recomienda la utilización de variables AnsiString en lugar de string cuando se envia/recibe información a otros dispositivos.

juanelo 23-07-2014 22:35:44

1 Archivos Adjunto(s)
Te envio una unidad que utilizo sin problema, se basa en mandar a imprimir a la "cola de impresion" de la impresora que se seleccione, sin importar si es USB, LPT, etc.
Actualemente me sirve entre otras cosas para un sistema de etiquetado con Zebra y Datamax.
Te anexo la unidad y un ejemplo de uso.

juanelo 23-07-2014 22:46:50

1 Archivos Adjunto(s)
Esta otra unidad tambien la uso, y es la que actualmente tengo, la anterior por error te la mande, esta es la actualizada.
Basicamente su uso es asi:

Código Delphi [-]

procedure Enviar_Etiqueta(s : string);
var
        xPrn: TRawPrint;
        i : integer;
begin
        xPrn := TRawPrint.Create;
        xPrn.DeviceName:= "IMPRESORA"; 
       xPrn.JobName = "ETIQUETA";
// nombre de la impresora. Lo puedes encontrar correctamente en la 
// variable printer. Pulsa f1 buscando printer para mas informacion.
// el URaw no es mas que una simplificacion del uso de printer para texto

         if xPrn.OpenDevice = False then
        raise exception.Create('Error en impresora.');

        xPrn.WriteString(s);
        

        xPrn.CloseDevice;
        xPrn.Free;
end;

hgiacobone 23-07-2014 23:08:07

Juanelo muchas gracias... pero como se utiliza esto? hay que instalarlo?

juanelo 24-07-2014 00:16:21

Si, instalas la unidad y luego le haces referencia con USES

hgiacobone 29-07-2014 20:09:21

Cita:

Empezado por juanelo (Mensaje 479313)
Si, instalas la unidad y luego le haces referencia con USES

Disculpame pero soy medio lerdo con esto....
Que hago?
Pongo el .PAS en el mismo directorio con el resto de los archivos fuente y lo agrego al proyecto ?

hgiacobone 29-07-2014 21:50:32

Nop... sigue sin funcionar.
1-Primero instale el componente.
2-Luego lo puse en el Form junto a un TOpenDialog.
3-Esto me permite abrir (y guardar en una variable TextFile) el archivo de texto que tiene la etiqueta. El formato es script EPL:
Código:

I8,A,001
Q508,024
q863
rN
S3
D7
ZT
JF
OD
R25,0
f100
N
B200,189,0,E30,4,8,130,B,"3836556465461"
A99,31,0,4,6,6,N,"Esto es un ejemplo"
P1

4-Leo y recojo cada linea y las envio a la impresora (mediante el componente):
Código Delphi [-]
procedure Enviar_Etiqueta(s : string);
begin
        with  RawPrint1 do 
        begin 
            DeviceName:= "IMPRESORA";  // nombre de la impresora que se obtiene de la variable Printer.-
            JobName = "ETIQUETA";
            Try
                if OpenDevice = False then
                  raise exception.Create('Error en impresora.')
                  else begin 
                      AssignFile(fTextFile, OpenDialog1.FileName );
                      Reset(fTextFile);
                      try
                        While Not Eof(fTextFile) do
                        begin
                           ReadLn(fTextFile, s);                
                           RawPrint1.WriteString(s);  //enviar comando
                        end;
                      finally
                          CloseFile(fTextFile);
                      end;
                  end;
            Finally
               CloseDevice;
            End;
        end;
end;

No imprime nada...nada...nada...:confused:

juanelo 29-07-2014 21:55:56

Preguntas:
¿se abre correctamente el dispositivo (impresora)?
¿La impresora a la que madas está correctamente instalada ?
¿si es interfaz usb, está correctamente asignado el puerto en la impresora (lista de impresoras)?

hgiacobone 29-07-2014 22:25:25

Cita:

Empezado por juanelo (Mensaje 479501)
Preguntas:
¿se abre correctamente el dispositivo (impresora)?
¿La impresora a la que madas está correctamente instalada ?
¿si es interfaz usb, está correctamente asignado el puerto en la impresora (lista de impresoras)?

Si a todo... ;-)
De hecho, desde el mismo driver de la impresora (Propiedad de la Impresora en entornos Windows), tiene una solapa "Herramientas" con la opción "Enviar fichero", desde el cual cargo y subo el mismo archivo script y lo imprime al instante.

Con esto concluyo que tanto la impresora como el archivo script son correctos.

He visto que otros colegas mandan todos los comandos concatenados e una sola llamada, cosa que tambien he probado, al estilo:
Código Delphi [-]
Procedure Imprimir_Etiqueta;
var
  L,Q1,A,A1,B,C,D,E:String ;
begin
        with  RawPrint1 do 
        begin 
            DeviceName:= "IMPRESORA";  // nombre de la impresora que se obtiene de la variable Printer.-
            JobName = "ETIQUETA";
            Try
              L:=chr(13)+Chr(10);
              Q1:='q500'+L;
              A1:='A220,10,0,1,1,1,N,"ESTO ES UN TEXTO"+L ;
              B:='B220,30,0,E30,2,20,100,B,'+'"ABC1234"'+L ;
              C:='A440,50,0,3,1,1,N,"Leyenda"'+L;
              D:='A440,70,0,3,1,1,N,'+'"'+FormatFloat('0.00', Precio.Value)+'"'+L;
              E:='A210,20,1,1,1,1,N,'+'"'+DateToStr(date)+'"'+L;

                RawPrint1.WriteString(L+'N'+L+'O'+L+'S2'+L+'D7'+L+'ZT'+L+'Q250,10'+Q1+A+A1+B+C+D+E+'P1');
           
            Finally
               CloseDevice;
            End;
        end;
End ;

juanelo 29-07-2014 22:55:28

Ok, te comento que yo mando todo el archivo de una sola vez.
Uso TStringList, con su metodo LoadFromFile. Usas luego la propiedad TStringList.Text para pasar todo el contenido de una sola vez. Te lo digo de pura memoria, no tengo el codigo a la mano.
Saludos

hgiacobone 04-08-2014 05:14:18

Finalizado / Solucionado
 
Bien amigos, al fin y al cabo lo hemos logrado solucionar entre todos, sobre todo con el "tip" final que indicó el amigo Juanelo respecto a que él lo hace mediante un TSringList...
De aquí que surgió entonces la pregunta: ¿Y que tiene de distinto enviar un TStringList que no tenga una linea obtenida de un archivo de texto?
En apariencia nada, pero sí tiene algo distinto... y al parecer es el "retorno de carro/fin de línea" que el comando ReadLn(fTextFile, s); parece quitar.

Tambien el hecho de que que de esa forma, Juanelo enviaba el script completo, en vez de enviarlo línea a línea. Asi que la primera aproximación fue cargar el archivo externo en un TMemo y enviarlo con el componente de Juanelo directamente al dispositivo, de la forma:
Código Delphi [-]
(...)
  try
    memo1.Lines.Clear;
    memo1.Lines.LoadFromFile(OpenDialog1.FileName);
    with RawPrint1 do
    begin
      DeviceName:= sPRN;
      JobName:= 'Desde componente Raw';
      Try
       if OpenDevice = False then
        raise exception.Create('Error en impresora.')
        else WriteString(memo1.Lines.Text);
      Finally
       CloseDevice;
      End;
    end;
  except
  on E:Exception do MessageDlg(E.Message, mtWarning, [mbOk],0);
  end; 
(...)
Esto funcionó a la perfección.
Después de algunas pruebas más, apareció la solución final que es un procedimiento/función que prescinde de la utilización del componente que tan gentilmente nos ofreció Juanelo, ya que básicamente hace lo mismo y es así:
Código Delphi [-]
{-------------------------------------------------------------------------------
  Nombre:  WriteRawStringToPrinter
  Creado el:  22/07/2014
  Obs:    Envia una instrucion RAW a una impresora
-------------------------------------------------------------------------------}
function Write_RAW_StringToPrinter(Comando, PrinterName :string): Boolean;
var
   PrinterHandle: THandle;
   N: DWORD;
   DocInfo1: TDocInfo1;
begin
  Result:= FALSE;
  if not OpenPrinter(PChar(PrinterName), PrinterHandle, nil) then
  begin
    ShowMessage('Error de impresora: ' + IntToStr(GetLastError));
    Exit;
  end
  else Try
      with DocInfo1 do
      begin
        pDocName := pChar('Imprimiendo etiqueta');
        pOutputFile:= pChar(#0);
        pDataType := pChar('RAW');
      end;

      if StartDocPrinter(PrinterHandle, 1, @DocInfo1) <> 0 then
      begin
          try
            if StartPagePrinter(PrinterHandle) then
            begin
              try
                Result:=( WritePrinter(PrinterHandle,pChar(comando),Length(comando), N)  );
                if not Result then ShowMessage('Error de impresora: ' + IntToStr(GetLastError));
              finally
                EndPagePrinter(PrinterHandle);
              end;
            end;
          finally
            EndDocPrinter(PrinterHandle);
          end;
      end;
  finally
    ClosePrinter(PrinterHandle);
  end;
end;

Como alternativa, para aquellos que como yo, gustan de llevar mayor control sobre cada instrucción, puede generarse la instrucción concatendado cadenas con los comandos EPL apropiados, de esta manera:
Código Delphi [-]
Function Imprimir_Etiqueta(A,B,C,D,E:string): boolean;
var
  sPRN, L, cadena, fin: string;
begin
    sPRN:= "IMPRESORA";  // nombre de la impresora que se obtiene de la variable Printer.-
    L:=Chr(13)+chr(10);
    cadena:= 'I8,A,001'+L;         //charset
    cadena:= cadena + 'Q360,024' +L;   //ancho en Dots (10mm=80Dots...1mm=8dots)
    cadena:= cadena + 'q480' +L;       //alto en Dots
    cadena:= cadena + 'rN' +L;      //disable double buffer
    cadena:= cadena + 'S3' +L;
    cadena:= cadena + 'D7' +L;
    cadena:= cadena + 'ZT' +L; //from Top
    cadena:= cadena + 'OD' +L; //Direct thermal //Od=Transfer ribbon
    {  cadena:= cadena + 'R191,0' +L;  //punto de referencia para datos centrados (si se utiliza, sobreescribe lo indicado por comando "q") }
    cadena:= cadena + 'f100' +L;   //cut position between labels
    cadena:= cadena + 'N' +L;     //clear image buffer

{Ejemplo donde se recibe datos como:
    A:='A52,49,0,4,1,1,N,"Impresión directa..."' +L;
    B:='B46,170,0,E30,4,8,70,B,"3836556465461"' +L;
    C:='A90,50,0,3,1,1,N,"Aquí hay una leyenda..."' +L;
    D:='A90,70,0,3,1,1,N,'+'"Precio: '+FormatFloat('0.00', 10.25)+'"' +L;
    E:='A50,20,1,1,1,1,N,'+'"Fecha: '+DateToStr(date)+'"' +L;
}
    
    fin:= 'P1'+L;
    cadena:= cadena +A+B+C+D+E + fin;

    Result:= Write_RAW_StringToPrinter(cadena, sPRN);
End;

Tip final: algo muy importante, es que la dimensión de la etiqueta debe estar muy bien configurada en el driver de la impresora y luego hay que lanzar un comando de auto-calibración para que ajuste bien la separación entre etiquetas (cut position), ya que estas impresoras realizan todo su trabajo en base a estos datos.
Esto es todo amigos...! :D
YAKO

juanelo 04-08-2014 05:34:18

Excelente!, que bueno que solcuionaste tu problema.
Con respecto a tu funcion, es basicamente lo que hace la unidad.
Me parece genial tu implementacion.^\||/

IVAND 11-10-2018 20:21:16

Estimado hgiacobone

Creas un archivo txt que contiene los comandos para mandar a imprimir , pero como reemplazas los campos fijos , imagino que utilizas la misma plantilla para imprimir varios productos diferentes ?

Gracias por tu aclaracion , aunque paresca tonta la pregunta o no se si me explico bien

newtron 13-10-2018 11:31:00

Cita:

Empezado por IVAND (Mensaje 528946)
Estimado hgiacobone

Creas un archivo txt que contiene los comandos para mandar a imprimir , pero como reemplazas los campos fijos , imagino que utilizas la misma plantilla para imprimir varios productos diferentes ?

Gracias por tu aclaracion , aunque paresca tonta la pregunta o no se si me explico bien


Lo que tienes que hacer es crear un .txt por cada etiqueta distinta que quieras imprimir con sus textos particulares de descripción, precios, etc. e ir enviandolas a la impresora.


Saludos

manelb 17-10-2018 22:37:12

Pues yo no lo consigo
 
Aprovechando que habéis “reabierto” este tema, he intentado el sistema de impresión propuesto pero no he podido hacer funcionar ninguno de los ejemplos presentados en el hilo.
Con algunos de los ejemplos consigo que por el administrador de impresión de mi Zebra aparezcan i desaparezcan rápidamente los trabajos que mando a imprimir, pero la impresora no se inmuta.
He seguido el consejo de Newtron y he creado una plantilla de mi etiqueta con el programa ZebraDesigner creando un fichero de texto que se imprime perfectamente si lo envío directamente desde la impresora, pero no me funciona si lo hago con cualquiera de los ejemplos de este hilo.

Podría tener algo que ver mi versión de Delphi 10.2CE?
Lo digo por el tema del Unicode.
Con que versión de Delphi lo estáis utilizando vosotros?

Saludos

newtron 18-10-2018 10:35:05

Cita:

Empezado por manelb (Mensaje 529048)
Aprovechando que habéis “reabierto” este tema, he intentado el sistema de impresión propuesto pero no he podido hacer funcionar ninguno de los ejemplos presentados en el hilo.
Con algunos de los ejemplos consigo que por el administrador de impresión de mi Zebra aparezcan i desaparezcan rápidamente los trabajos que mando a imprimir, pero la impresora no se inmuta.
He seguido el consejo de Newtron y he creado una plantilla de mi etiqueta con el programa ZebraDesigner creando un fichero de texto que se imprime perfectamente si lo envío directamente desde la impresora, pero no me funciona si lo hago con cualquiera de los ejemplos de este hilo.

Podría tener algo que ver mi versión de Delphi 10.2CE?
Lo digo por el tema del Unicode.
Con que versión de Delphi lo estáis utilizando vosotros?

Saludos


Yo uso Delphi 2007 no sé si será ese el problema, te paso algún trozo de código por si te sirve de ayuda:


Código Delphi [-]
var
  DocInfo1: TDocInfo1;
  Handle:   THandle;
  N:        DWORD;
  Linea:    String;
....


Código Delphi [-]
    with DocInfo1 do begin
      pDocName    := PChar('Etiqueta ' + fsTablaPosicionamiento + '.');
      pOutputFile := nil;
      pDataType   := 'RAW';
    end;

    for g:=1 to fiCopias do begin
    //
      StartDocPrinter(Handle, 1, @DocInfo1);

      StartPagePrinter(Handle);

      for f:=0 to fslLineaImpreso.Count-1 do begin
        Linea := fslLineaImpreso[f] + #10 + #13;
        WritePrinter(Handle, PChar(Utf8Encode(AnsiString(Linea))), Length(Linea), N);
      end;

      EndPagePrinter(Handle);

      EndDocPrinter(Handle);
    //
    end; // for g:=1 to fiCopias do begin

    ClosePrinter(Handle);


Saludos

manelb 22-10-2018 09:31:18

Gracias Newtron...

parece que con esta sentencia lo he solucionado
Código Delphi [-]
    WritePrinter(Handle, PChar(Utf8Encode(AnsiString(Linea))), Length(Linea), N);

Saludos todos...

IVAND 24-10-2018 03:08:42

Estimados amigos , uso delphi 2009 y el codigo que utilizo para la impresion de documento a una zebra epl no funciona

cabe decir que esta funcionando pefectamente desde el sistema de zebra la impresion he tomado notas de lo que dice el companero pero nada no imprime nada, desde fastreport imprime sin problemas

de antemano gracias por su tiempo

Envio el proyecto a ver si su tiempo lo permite y revise el código , seguro es algo pequenio , cabe destacar también que en delphi 6 utilizo el mismo codigo y funciona

manelb 24-10-2018 09:18:52

1 Archivos Adjunto(s)
Hola IVAND, y saludos a todos.

A mi tu código tampoco me funciona.

Lo que yo estoy utilizando es el componente del amigo Juanelo pero cambiando esta sentencia
Código Delphi [-]
if not WritePrinter(hPrinter, PChar(Text), Length(Text), WrittenChars) then begin

por esta otra
Código Delphi [-]
if not WritePrinter(hPrinter, PChar(Utf8Encode(AnsiString(Text))),Length(Text), WrittenChars) then begin

en la función

Código Delphi [-]
function TRawPrint.WriteString(Text: String): Boolean;

Este cambio lo he realizado a instancias de los comentarios realizados por Newtron donde adjuntaba un ejemplo.
También comentar que el texto que yo imprimo lo cargo desde un fichero de texto y que este fichero que cargo está creado directamente con el programa ZebraDesigner.

Adjunto uno de estos ficheros por si te sirve de ayuda, al menos, para comparar su formato con o que tu envías.

Saludos


La franja horaria es GMT +2. Ahora son las 11:59:05.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi