A impressão de etiquetas com código de barras é um componente crítico em diversos setores, especialmente na logística e no gerenciamento de estoque. Para desenvolvedores que trabalham com o ERP Protheus, dominar a programação de impressoras térmicas em ADVPL é uma habilidade essencial. Este guia abrangente explorará as nuances da geração e impressão de etiquetas com código de barras usando ADVPL, uma linguagem robusta utilizada no ecossistema Protheus.

Fundamentos da Programação de Impressoras Térmicas em ADVPL

A programação de impressoras térmicas em ADVPL envolve o uso de funções especializadas que permitem a criação de layouts complexos de etiquetas. Estas funções são projetadas para trabalhar com várias linguagens de impressão térmica, incluindo:

  • ZPL (Zebra Programming Language)
  • EPL (Eltron Programming Language)
  • DPL (Datamax Programming Language)
  • IPL (Intermec Programming Language)

Uma das principais vantagens do ADVPL neste contexto é a abstração que oferece. Os desenvolvedores não precisam dominar as linguagens específicas de cada fabricante, pois o ADVPL fornece uma interface unificada para diferentes modelos de impressoras.

O que veremos:

  • Configuração Inicial e Preparação
  • Criando Layouts de Etiquetas
  • Trabalhando com Códigos de Barras Avançados
  • Otimização para Diferentes Fabricantes de Impressoras
  • Melhores Práticas e Otimização de Performance
  • Funções ADVPL para Etiquetas Térmicas

    (MSCBPrinter, MSCBClosePrinter, MSCBBegin, MSCBEnd, MSCBSay, MSCBSayBar, MSCBBox, MSCBLineH, MSCBLineV, MSCBLoadGraf, MSCBGraphic, MSCBWrite, MSCBInfoEti)

  • Conclusão
  • Configuração Inicial e Preparação

    Antes de mergulhar na programação, é crucial configurar corretamente a impressora. A função MSCBPrinter é fundamental neste processo:

    Sintaxe Advpl

    //Exemplo de função MSCBPRINTER
    MSCBPRINTER(cModelPrt, cPorta, nDensidade, nTamanho, lSrv, nPorta, cServer, cEnv, nMemoria, cFila, lDrvWin, cPathSpool)

    Esta função permite especificar:

  • Modelo da impressora
  • Porta de comunicação
  • Densidade de impressão
  • Tamanho da etiqueta
  • Configurações de servidor e ambiente
  • É importante notar que a configuração correta destes parâmetros é essencial para garantir a qualidade e precisão da impressão.

    Parâmetros Descrição
    [cModelPrt] String com o modelo de impressora:
    Fabricante Impressoras
    Datamax ALLEGRO, ALLEGRO 2, PRODIGY, DMX, DESTINY, URANO, DATAMAX, OS 214, OS 314, PRESTIGE, ARGOX
    Eltron ELTRON, TLP 2722, TLP 2742, TLP 2844, TLP 3742, C4-8
    Intermec INTERMEC, 3400-8, 3400-16, 3600-8, 4440-16, 7421C-8
    Zebra S300, S400, S500-6, S500-8, Z105S-6, Z105S-8, Z160S-6, Z160S-8, Z140XI, S600, Z4M, Z90XI, Z170XI, ZEBRA
    [cPorta] String com a porta
    [nDensidade] Número com a densidade referente a quantidade de pixel por mm. Este parâmetro só deve ser informado quando o parâmetro cModelPrt não for informado, pois cModelPrt o atualizará automaticamente. A utilização deste parâmetro deverá ser usada quando não souber o modelo da impressora, a aplicação entenderá que se trata de uma impressora Zebra. O tamanho da etiqueta será necessário quando a mesma não for contínua.
    [nTamanho] Tamanho da etiqueta em Milímetros. Lembrando que este tamanho só deve ser passado se a etiqueta for contínua.
    [lSrv] Se .t. imprime no server, .f. no client. O seu valor padrão é .f.
    [nPorta] Número da porta de outro server
    [cServer] Endereço IP de outro server
    [cEnv] Environment do outro server
    [nMemoria] Número com bloco de memória da impressora térmica. Caso seja enviada muita informação para a impressora, a fim que esta venha imprimir (sobrecarregando a memória), pode ocorrer perda de dados. Por outro lado, se for informado blocos muito pequenos de memória, implicará na diminuição da performance da impressora. Sendo assim, o programador deverá fazer uma avaliação para ver o que melhor se adequa a sua situação.
    [cFila] Diretório onde será gravada as filas
    [lDrvWin] Indica se será utilizado os drivers do Windows para impressão
    [cPathSpool] Caminho do diretório onde serão geradas as filas de impressão


    Criando Layouts de Etiquetas

    O processo de criação de uma etiqueta geralmente segue uma estrutura definida:

    1. Iniciar a etiqueta com MSCBBegin
    2. Adicionar elementos como texto, linhas, caixas, código de barras e imagens. Ou até mesmo um bloco com código da linguagem nativa da impressora
    3. Finalizar a etiqueta com MSCBEnd

    Vamos explorar um exemplo mais avançado:

    Sintaxe Advpl MSCBBEGIN e MSCBEND

    MSCBBEGIN(1, 6) // Inicia a etiqueta
       MSCBBOX(02, 01, 76, 34, 1) // Cria uma caixa
       MSCBSAY(10, 06, "PRODUTO:", "N", "A", "012,008")
       MSCBSAY(10, 12, cDescProd, "N", "A", "012,008")
       MSCBSAY(10, 18, "LOTE:", "N", "A", "012,008")
       MSCBSAY(10, 24, cLote, "N", "A", "012,008")
       MSCBSAYBAR(23, 30, cCodigo, "N", "C", 8.36, .F., .T., .F., , 2, 1) // Imprime o código de barras
    MSCBEND() // Finaliza a etiqueta

    Este exemplo demonstra como criar uma etiqueta mais complexa, incluindo múltiplos campos de texto e um código de barras.



    Trabalhando com Códigos de Barras Avançados

    A função MSCBSayBar é o coração da impressão de códigos de barras em ADVPL. Ela suporta uma ampla variedade de simbologias, incluindo:

    1. Code 128
    2. EAN-13
    3. QR Code
    4. Data Matrix

    Aqui está um exemplo avançado usando o GS1-128, um padrão amplamente utilizado na indústria:

    Sintaxe Advpl MSCBSAYBAR

    aConteudo := {;
          {"01", "07893316010411"                             } ,;// GTIN
          {"10", "0000970100" + MSCB128B() + "1" + MSCB128C() } ,;// Lote
          {"37", "0004"                                       } ,;// Quantidade
          {"21", "000494"                                     } } // Número de Série
    
    MSCBSAYBAR(08, 10, aConteudo, "N", "MB07", 10, .F., .T., .F., "C", 2, 1, .F.)

    Este código cria um código de barras GS1-128 que incorpora múltiplas informações em um único código, uma prática comum em logística avançada e rastreamento de produtos.



    Otimização para Diferentes Fabricantes de Impressoras

    Embora o ADVPL abstraia muitas diferenças entre fabricantes, é crucial entender algumas particularidades:

    • Zebra (ZPL): O ponto de origem está no canto superior esquerdo.
    • Datamax (DPL): O ponto de origem está no canto inferior esquerdo.
    • Intermec (IPL): Similar ao Zebra, mas com algumas diferenças no sistema de coordenadas.

    Conhecer essas nuances é fundamental para criar layouts precisos e resolver problemas específicos de cada fabricante.



    Melhores Práticas e Otimização de Performance

    Embora o ADVPL abstraia muitas diferenças entre fabricantes, é crucial entender algumas particularidades:

    01.
    Utilização de Variáveis

    A função `MSCBVar` permite criar variáveis para elementos que mudam frequentemente, melhorando significativamente a eficiência da impressão.

    02.
    Gerenciamento de Memória

    Use o parâmetro `nMemoria` em `MSCBPrinter` para otimizar o uso de memória da impressora, especialmente importante em ambientes de alto volume, e se drive windows estiver desabilitado (caso contrário será o windows que administrará a memória).

    03.
    Testes Extensivos

    Devido às variações entre modelos de impressoras, é crucial testar seu código em diversas configurações e cenários.

    04.
    Documentação Detalhada

    Mantenha uma documentação clara e abrangente, especialmente ao lidar com layouts complexos de etiquetas ou integrações avançadas.

    Conhecer essas nuances é fundamental para criar layouts precisos e resolver problemas específicos de cada fabricante.


    Funções ADVPL para Etiquetas Térmicas

    Segue abaixo funções ADVPL para etiquetas térmicas:

    1. MSCBPrinter (Configuração da Impressora)

    Objetivo:

    Permite realizar as configurções da impressora, as quais permitirão ao programador determinar as caracteristicas de impressão, definidas pelos parâmetros abaixo.

    Sintaxe:

    MSCBPRINTER(cModelPrt, cPorta, nDensidade, nTamanho, lSrv, nPorta, cServer, cEnv, nMemoria, cFila, lDrvWin, cPathSpool)


    Já vimos anteriormente os detalhes dos parâmetros da função MSCBPrinter, clique aqui para mais detalhes.

    MSCBPrinter (Configuração da Impressora)

    User Function ConfigImpressora()
       Local cModelo := "ZEBRA"
       Local cPorta  := "LPT1"
       Local nDensidade := 203 // DPI
       Local nTamanho := 100 // mm
    
       MSCBPRINTER(cModelo, cPorta, nDensidade, nTamanho, .F.)
       
       // Outras configurações...
       
       MSCBCHKSTATUS(.T.) // Ativa verificação de status
    Return

    2. MSCBClosePrinter (Finaliza a conexão com a impressora)

    Objetivo:

    Finaliza a conexão com a impressora.

    Sintaxe:

    MSCBClosePrinter()

    Exemplo usando o padrão de programação Zebra (família ZPL):

    MSCBClosePrinter (Finaliza a conexão com a impressora)

    User Function FinalizaConexao()
    Local cPorta := "COM1:9600,N,8,1"
    Local nx     := 0
    
    MSCBPRINTER("S500-8", cPorta, , 40, .F.)
    
       For nx:=1 to 3
          MSCBBEGIN(1, 6)
    
          MSCBSAY(10, 06, "CODIGO", "N", "A", "015,008")
          MSCBSAY(33, 09, Strzero(nX, 10), "N", "0", "032,035")
          MSCBSAY(05, 17, "IMPRESSORA ZEBRA S500-8", "N", "0", "020,030")
    
          MSCBEND()
       Next nx
    
    MSCBCLOSEPRINTER() // Finaliza Conexao
    
    Return

    3. MSCBBegin (Início da Etiqueta)

    Objetivo:

    Inicializa a montagem da imagem para cada etiqueta.

    Sintaxe:

    MSCBBEGIN(nxQtde,nVeloc,nTamanho,lSalva)

     

    Parâmetros Descrição
    [nQtde] Quantidade de cópias
    [nVeloc] Velocidade (1,2,3,4,5,6) polegadas por segundo
    [nTamanho] Tamanho da etiqueta em Milímetros.
    [lSalva] Variável utilizada somente para definição de form´s. O valor default da variável é .f.

    Exemplo:

    MSCBBegin (Início da Etiqueta)

    User Function IniciaEtiqueta()
       Local nCopias := 1
       Local nVelocidade := 3 // Velocidade de impressão
    
       MSCBBEGIN(nCopias, nVelocidade)
       
       // Conteúdo da etiqueta será adicionado aqui...
    Return

    4. MSCBEnd

    Objetivo:

    Finaliza a montagem da imagem, que foi inicializada por um “MSCBBegin( )”.

    Sintaxe:

    MSCBEND()

    Exemplo:

    MSCBEnd (Finalizar Etiqueta)

    User Function FinalizaEtiqueta()
       MSCBEND()
    Return

    5. MSCBSay (Imprimir Texto)

    Objetivo:

    Imprime uma string.

    Sintaxe:

    MSCBSAY(nXmm, nYmm, cTexto, cRotacao, cFonte, cTam, lReverso, lSerial, cIncr, lZerosL, lNoAlltrim)

    Parâmetro Descrição
    nXmm Posição X em Milímetros
    nYmm Posição Y em Milímetros
    cTexto String a ser impresso ou itens especificando uma variável “@”.(Ex: “@2”).

    Obs: quando for especificado uma variável, o seu conteúdo deverá ser apenas o caractere “@” seguido de um número, “@1” ou “@2” e assim por diante. Vide item 15.

     

    cRotação String com o tipo de Rotação (N,R,I,B):

    Instrução Descrição
    N Normal
    R Cima para baixo
    I Invertido
    B Baixo para cima
    cFonte String com os tipos de Fonte:

    Padrão Tipos
    Zebra (A,B,C,D,E,F,G,H,0) 0(zero)- fonte escalar
    Datamax (0,1,2,3,4,5,6,7,8,9) 9 – fonte escalar
    Eltron (0,1,2,3,4,5)
    Intermec (0,1,7,20,21,22,27)
    cTam String com o tamanho da Fonte
    *[lReverso] Imprime em reverso quando tiver sobre um box preto
    [lSerial] Serializa o código
    [cIncr] Incrementa quando for serial positivo ou negativo
    *[lZerosL] Coloca zeros a esquerda no numero serial
    [lNoAlltrim] Permite brancos a esquerda e direita

     

    Exemplo usando o padrão de programação Zebra (família ZPL):

    MSCBSay (Imprimir Texto)

    User Function ImprimeTexto()
       Local cTexto := "Produto: Widget XYZ"
       Local nX := 10, nY := 15
       Local cRotacao := "N" // Normal
       Local cFonte := "A"
       Local cTamanho := "020,010"
    
       MSCBSAY(nX, nY, cTexto, cRotacao, cFonte, cTamanho)
    Return

    6. MSCBSayBar (Imprimir Código de Barras)

    Objetivo:

    Imprime código de barras.

    Sintaxe:

    MSCBSAYBAR(nXmm, nYmm, cConteudo, cRotacao, cTypePrt, nAltura, lDigVer, lLinha, lLinBaixo, cSubSetIni, nLargura, nRelacao, lCompacta, lSerial, cIncr, lZerosL)

    Parâmetro Descrição
    nXmm Posição X em Milímetros
    nYmm Posição Y em Milímetros
    cConteudo String a ser impressa especificando uma variável “@” ou array somente quando o parâmetro cTypePrt for igual á MB07.

    Definição do Array:
    cConteudo :={{“01″,”07893316010411”},;

    {“10”,”0000970100″+MSCB128B()+”1″+MSCB128C()},;

    {“37″,”0004”},;

    {“21″,”000494”}}

    • A possição 1 do array (ex: “01”) informa o AI utilizadado (que será visto no item 3.6.1. “Utilização do código de barras 128”).
    • Já a possição 2 do array (ex: “07893316010411”) é o conteúdo do AI.

     

    cRotação String com o tipo de Rotação:

    Instrução Descrição
    N Normal
    R Cima para baixo
    I Invertido
    B Baixo para cima
    cTypePrt String com o Modelo de Código de Barras:

    Instrução Modelo de Código de Barras
    MB01 Interleaved 2 of 5
    MB02 Code 39
    MB03 EAN 8
    MB04 EAN 13
    MB05 UPC A
    MB06 UPC E
    MB07 CODE 128

    Obs: Caso o leitor queira utilizar o modelo do padrão de programação da impressora, o mesmo deverá consultar documentação do fabricante.

     

    [nAltura] Altura do código de Barras em Milímetros
    *[ lDigver] Imprime dígito de verificação
    [lLinha] Imprime a linha de código
    *[lLinBaixo] Imprime a linha de código acima das barras
    [cSubSetIni] Utilizado no code128
    [nLargura] Largura da barra mais fina em pontos default 3
    [nRelacao] Relação entre as barras finas e grossas em pontos default 2
    [lCompacta] Parâmetro fora de uso.
    [lSerial] Serializa o código
    [cIncr] Incrementa quando for serial positivo ou negativo
    [lZerosL] Coloca Zeros a esquerda do conteúdo. Este parâmetro só é valido quando lSerial estiver ativado (.t.).

     

    Exemplo usando o padrão de programação Zebra (família ZPL):

    MSCBSayBar (Imprimir Código de Barras)

    User Function ImprimeCodigoBarras()
       Local cConteudo := "7891234567890"
       Local nX := 20, nY := 30
       Local cTipo := "EAN13"
       Local nAltura := 15
       Local lDigVerif := .T.
       Local lLinha := .T.
    
       MSCBSAYBAR(nX, nY, cConteudo, "N", cTipo, nAltura, lDigVerif, lLinha)
    Return

    7. MSCBBox (Desenhar Caixa)

    Objetivo:

    Imprime um box.

    Sintaxe:

    MSCBBOX(nX1mm, nY1mm, nX2mm, nY2mm, nExpessura, cCor)

    Parâmetro Descrição
    nX1mm Posição X1 em Milímetros
    nY1mm Posição Y1 em Milímetros
    nX2mm Posição X2 em Milímetros
    nY2mm Posição Y2 em Milímetros
    [nEspessura] Numero com a espessura em pixel
    *[cCor] String com a Cor Branca ou Preta (“W” ou “B”)

     

    Exemplo:

    MSCBBox (Desenhar Caixa)

    User Function DesenhaCaixa()
       Local nX1 := 5, nY1 := 5
       Local nX2 := 95, nY2 := 45
       Local nEspessura := 1
    
       MSCBBOX(nX1, nY1, nX2, nY2, nEspessura)
    Return

    8. MSCBLineH (Imprime Linha Horizontal)

    Objetivo:

    Imprime uma linha horizontal.

    Sintaxe:

    MSCBLineH(nX1mm, nY1mm, nX2mm, nExpessura, cCor)

    Parâmetro Descrição
    nX1mm Posição X1 em Milímetros
    nY1mm Posição Y1 em Milímetros
    nX2mm Posição X2 em Milímetros
    [nEspessura] Numero com a espessura em pixel
    *[cCor] String com a Cor Branca ou Preta (“W” ou “B”)

    Exemplo:

    MSCBLineH (Imprime Linha Horizontais)

    User Function LinhaHorizontal()
       // Linha Horizontal
       MSCBLINEH(10, 20, 90, 2)
    Return

    9. MSCBLineV (Imprime Linha Vertical)

    Objetivo:

    Imprime uma linha vertical.

    Sintaxe:

    MSCBLineV(nX1mm, nY1mm, nY2mm, nExpessura, cCor)

    Parâmetro Descrição
    nX1mm Posição X1 em Milímetros
    nY1mm Posição Y1 em Milímetros
    nY2mm Posição X2 em Milímetros
    [nEspessura] Numero com a espessura em pixel
    *[cCor] String com a Cor Branca ou Preta (“W” ou “B”)

    Exemplo:

    MSCBLineV (Imprime Linha Vertical)

    User Function LinhaVertical()   
       // Linha Vertical
       MSCBLINEV(50, 10, 40, 2)
    Return

    10. MSCBLoadGraf (Carrega Imagem na Memória da Impressora)

    Objetivo:

    Carrega uma imagem para memória da impressora.

    Sintaxe:

    MSCBLOADGRF(cImagem)

    Parâmetro Descrição
    cImagem Nome do arquivo que será carregado, inclusive o path + nome completo + extensão

    Observações:

  • Para o padrão Zebra, o arquivo do gráfico (cImagem) tem que ser do tipo GRF, gerado através de um PCX ou TIF no software fornecido pelo fabricante da zebra.
  • Para o padrão Intermec, o arquivo do gráfico (cImagem) tem que ser do tipo UDC, gerado através de um BMP ou TIF (não compactado) no software fornecido pelo fabricante da intermec.
  • Para o padrão Datamax, o arquivo do gráfico pode ser do tipo BMP, PCX, não sendo necessário ser convertido.
  • Para o padrão Eltron, o arquivo do gráfico tem que ser do tipo PCX, não sendo necessário ser convertido.

  • Exemplo do código usando o padrão de programação ZPL:

    MSCBLoadGraf (Carrega Imagem na Memória da Impressora)

    User Function ImprimeImagem()
       Local cNomeImagem := "LOGO"
       Local nX := 5, nY := 5
    
       MSCBLOADGRF("LOGO.GRF") // Carrega a imagem
       MSCBGRAFIC(nX, nY, cNomeImagem)
    Return

    11. MSCBGraphic (Imprimir Imagem)

    Objetivo:

    Imprime gráfico que está armazenado na memória da impressora.

    Sintaxe:

    MSCBGRAFIC(nXmm, nYmm, cArquivo, lReverso)

    Parâmetro Descrição
    NXmm Posição X em Milímetros
    NYmm Posição Y em Milímetros
    cArquivo Nome do gráfico que foi carregado na memória da impressora (não colocar a extensão do arquivo)
    *[lReverso] Imprime em reverso quando tiver sobre um box preto

    Exemplo usando o padrão de programação ZPL:

    MSCBGrafic (Imprimir Imagem)

    User Function ImprimeImagem()
       Local cNomeImagem := "LOGO"
       Local nX := 5, nY := 5
    
       MSCBLOADGRF("LOGO.GRF") // Carrega a imagem
       MSCBGRAFIC(nX, nY, cNomeImagem)
    Return

    12. MSCBWrite (Comando Direto para Impressora)

    Objetivo:

    Permite enviar para impressora uma linha de programação nativa.

    Sintaxe:

    MSCBWrite(cConteudo)

    Parâmetro Descrição
    cConteudo Linha de programação nativa da impressora.

    Exemplo usando o padrão de programação Zebra (família ZPL):

    MSCBWrite (Comando Direto para Impressora)

    User Function ComandoDireto()
       // Exemplo para Zebra (ZPL)
       MSCBWRITE("^XA^FO50,50^A0N,30,30^FDHello World^FS^XZ")
    Return

    Atenção: o MSCBWrite é muito poderoso em conjunto com ferramentas como o ZebraDesigner e BarTender, que são ferramentas de desenho e geração de etiquetas de código de barras, além do Labelary(Em outro blog irei detalhar como o Labelary poderá ser útil pre-visualização das etiquetas no dia a dia).


    13. MSCBInfoEti (Informações da Etiqueta)

    Objetivo:

    Grava informações para gerenciamento do MSCBSpool.

    Sintaxe:

    MSCBInfoEti(cDescr,cFiltro)

    Parâmetro Descrição
    cDescr Descrição que gerará informação no MSCBSpool para identificar a etiqueta.
    cFiltro É utilizado para realizar filtros no MSCBSpool. Vide documentação MSCBSpool.

    Exemplo:

    MSCBInfoEti (Informações da Etiqueta)

    User Function InfoEtiqueta()
       Local cDescricao := "Etiqueta de Produto"
       Local cFiltro := "PROD001"
    
       MSCBInfoEti(cDescricao, cFiltro)
    Return



    Exemplo Completo Integrando Várias Funções:

    User Function ImprimirEtiquetaCompleta()
       Local cCodProd := "PROD001"
       Local cDescProd := "Widget XYZ"
       Local cCodBarras := "7891234567890"
    
       // Configurar impressora
       MSCBPRINTER("ZEBRA", "LPT1", 203, 100, .F.)
    
       // Iniciar etiqueta
       MSCBBEGIN(1, 3)
    
       // Desenhar caixa
       MSCBBOX(5, 5, 95, 45, 1)
    
       // Imprimir textos
       MSCBSAY(10, 10, "Código: " + cCodProd, "N", "A", "012,008")
       MSCBSAY(10, 20, "Descrição: " + cDescProd, "N", "A", "012,008")
    
       // Imprimir código de barras
       MSCBSAYBAR(20, 30, cCodBarras, "N", "EAN13", 15, .T., .T.)
    
       // Imprimir logo
       MSCBLOADGRF("LOGO.GRF")
       MSCBGRAFIC(70, 5, "LOGO")
    
       // Finalizar e imprimir etiqueta
       MSCBEND()
    
       // Fechar conexão com a impressora
       MSCBCloseprinter()
    Return

    Este conjunto de exemplos demonstra como utilizar as principais funções ADVPL para impressão de etiquetas térmicas. Cada função desempenha um papel específico na criação de uma etiqueta completa, desde a configuração da impressora até a impressão final e fechamento da conexão.

    Para empresas que buscam implementar soluções avançadas de etiquetagem ou otimizar seus processos existentes, contar com uma DO THINK especializada pode ser extremamente benéfico. Especialistas podem ajudar a personalizar essas funções para atender às necessidades específicas do negócio, garantindo eficiência e precisão na geração de etiquetas.