Professional Documents
Culture Documents
Neste artigo veremos como devemos fazer para declarar DLL`s e comunicar com o ECF, visando automao comercial. Para isso, utilizaremos o CSharp.NET, do Visual Studio 2010. Antes falarei um pouco das vantagens de se usar uma DLL para desenvolver para aplicaes de automao comercial, mais focado nos Emissores de Cupom Fiscal, o ECF. Todo equipamento possui um quadro de comandos que so interpretados por seu sistema operacional, ou seu software bsico. Esses comandos normalmente so complicados de serem enviados e requerem um conhecimento a mais para serem usados, como por exemplo, as tabelas ASCII, onde temos comandos de Controle, Decimais, Caracteres e Hexadecimais. Mas o que a DLL tem haver com tudo isso? Simples. A DLL tem tudo haver com isso. Por qu? A DLL nada mais que uma biblioteca de comandos, onde conseguimos simplificar a execuo deles. Mas, como? Simples tambm. Vou dar um exemplo: Eu tenho empresa onde todo final do ms tenho que fechar meu caixa, mas eu preciso sempre tirar 10% do meu faturamento e pagar os impostos, e em cima desses 10% preciso pagar 5% para o banco. Ao invs de eu sempre ter que fazer as contas, no seria mais fcil eu apenas inserir o valor do meu faturamento na calculadora e ela me devolver quanto seria meus 10% e meus 5%? A DLL trabalha dessa forma. Ela recebe seu comando simplificado, interpreta e envia para o ECF execut-lo, sem que voc precise passar perto dos comandos do equipamento. Bem, depois dessa breve explicao, vamos colocar as mos a obra! Vamos iniciar nosso Visual Studio e abrir um Novo Projeto.
Em seguida, escolha a opo Windows Forms Application, coloque o nome ao seu projeto e d Ok.
Com isso criamos nosso novo projeto e estamos prontos para comear. Ficamos com essa cara ento em nosso Visual Studio.
Agora chegamos parte mais divertida: Declarar a DLL DarumaFramework.dll ;) Para isso, vamos criar um novo Class. Clique sobre seu projeto no Solution Explorer com o boto esquerdo, v em Add/New Item e adicione uma Class. Ou aperte CTRL+SHIFT+A para abrir a tela para adicionar o novo item. Ficamos ento com 1 Form1, 1 Class1 em nosso Solution Explorer. No arquivo Class1, vamos declarar as funes da DarumaFramework.dll. Pode apagar o contedo do Class1, pois vamos iniciar do zero. Adicione as seguintes usings no arquivo Class1. using System; using System.Collections.Generic; using System.Text; using System.Runtime.InteropServices; Com elas, poderemos trabalhar sem problemas com a DLL. Aps, criaremos um NameSpace, o qual darei o nome de DarumaFramework_DLL. Digitamos ento, aps a ultima using; namespace DarumaFramework_DLL; Como um namespace, precisamos abrir e fechas as chaves. namespace DarumaFramework_DLL ; { } Entre as chaves deste namespace, criaremos a classe ECF_Daruma, onde vamos declarar as funes da DLL e a chamada dela. Crie a public class ECF_Daruma e j abra as chaves. Vamos declarar apenas uma funo da DLL, para que possamos passar para o prximo passo que tambm divertido! ;) Dentro do public class ECF_Daruma, vamos colocar a seguinte informao: [DllImport("DarumaFrameWork.dll")] public static extern int rVerificarImpressoraLigada_ECF_Daruma(); Nesse comando, indicamos que o comando rVerificarImpressoraLigada_ECF_Daruma(), est
em externo, e por isso indicamos onde est, no caso est em DarumaFramework.dll Para cada mtodo, necessria a declarao dessa forma. Ficamos ento com nosso Class1 com essa cara:
Com isso, estamos pronto para chamar a DLL e executar uma primeira funo no nosso Form1! Vamos deixar a declarao de lado, e vamos trabalhar com nosso Form1, para isso abra ele. Com ele aberto, devemos inserir a using do namespace que criamos, para indicar que usaremos ele no form. Junto com as outras usings, insira: using DarumaFramework_DLL; Para facilitar o servio, certifique-se de que o namespace do Form1 esteja com o nome do namespace da nossa declarao do arquivo Class1, no caso DarumaFramework_DLL. Feito a conferncia, vamos utilizar o mtodo que inserimos agora h pouco. Entre as chaves do Public Form1 e abaixo do InitializeComponent(); , chame a classe ECF_Daruma. No caso das linguagens Microsoft, temos o IntelliSense que filtra os comandos conforme vamos digitando. Vamos usar bastante esse recurso no andar de nossos artigos. Quando digitamos o . depois de ECF_Daruma, veja que ele j identifica as funes declaradas neste class. No nosso caso, aparecer apenas o rVerificaImpressoraLigada, pois s declaramos ela no arquivo Class1. Como essa funo no tem parmetros, nosso public form1 ficar assim: public Form1() {InitializeComponent();ECF_Daruma.rVerificarImpressoraLigada_ECF_Daruma();} Feito isso, nosso programa j est chamando a DLL. Para realizarmos um teste, vamos adicionar um if em nossa funo, que j verificar se a nossa impressora est ligada ou no. Temos ento essa cara: public Form1(){InitializeComponent();if (ECF_Daruma.rVerificarImpressoraLigada_ECF_Daruma() != 1) {MessageBox.Show("IMPRESSORA DESLIGADA.VERIFIQUE CONFIGURAO", "DarumaFramework.dll");}} Feito esses passos, podemos executar nosso projeto e fazer o teste! D o Start Debugging (F5) e aguarde. Se voc tiver uma impressora conectada ao computador e configurada corretamente, nenhum aviso ir aparecer. No meu caso, estou sem o equipamento instalado, ento veremos que a mensagem de erro aparecer em minha tela.
Com certeza voc ter problemas ao fazer o debug e o VS reportar erro dizendo que no encontrou o mdulo DarumaFramework.dll, pois propositalmente no falei sobre a DLL e onde ela deve estar inserida. Temos duas opes: Primeira: Na mesma pasta da aplicao. No caso do Debug do VS, dentro da pasta \bin\Debug\ dentro da sua aplicao. Segunda: \Windows\System32\ Com a DLL em mos, a coloque na pasta de sua escolha. Eu prefiro colocar na pasta da aplicao, pois fica mais fcil de chegar at l.
Ficamos ento assim: Feito! Podemos iniciar novamente o Debug da nossa aplicao. Como disse anteriormente, a mensagem de impressora desligada iria aparecer na minha tela.
Para testarmos a aplicao caso voc tenha a impressora ligada no computador, faremos essa modificao no cdigo: public Form1() { InitializeComponent(); if (ECF_Daruma.rVerificarImpressoraLigada_ECF_Daruma() != 1) { MessageBox.Show("IMPRESSORA DESLIGADA.VERIFIQUE CONFIGURAO", "DarumaFramework.dll"); } else MessageBox.Show("IMPRESSORA LIGADA. PARABNS", "DarumaFramework.dll"); } Feita a alterao, mande rodar e vamos ver o que acontece!
Agora, se voc no quer ter o trabalho de declarar as funes uma a uma, utilize nosso class j pronto e apenas importe para sua aplicao. Espero que vocs tenham aproveitado este artigo. Dvidas? Postem! ;)
Com ele aberto, vamos declarar as funes de LeituraX e ReduoZ. Para isso, abriremos o nosso Class1, onde declaramos a DLL no artigo anterior.
Com ele aberto, vamos declarar as funes de LeituraX e ReduoZ Os mtodos com seus parmetros so:
Insira essas informaes no Class1, abaixo do ultimo mtodo que adicionamos anteriormente. Deixamos nosso VS2010 com essa cara.
Com essa parte pronta, poderemos partir para a prxima etapa! Vamos at o Form1, e vamos criar um Menu para inserir 2 botes. Adicione um MenuStrip e criei um menu Relatrios com 2 sub-menus Leitura X e Reduo Z, como mostra a imagem abaixo.
O sistema j est pronto para efetuar a impresso dos dois documentos. Com isso, estamos pronto para realizar os testes! D o F5 e vamos ver o que acontece! Bom, pessoal. Com isso j aprendemos a declarar a DLL e tambm a fazer a LeituraX e ReduoZ, que so os dois principais relatrios do ECF. At a prxima! ;)
Tendo os mtodos, consigo declara-los no nosso Class1. Ficamos ento com nosso arquivo Class1 assim:
Com o Class1 pronto, vamos ao Form1. Crie no MenuToolStrip um menu Cupom Fiscal, e dentro sub-menus Abrir, Vender, Totalizar, Pagar, Fechar.
Com o menu criado, vamos colocar as funes para cada menu. Lembrando novamente que devemos ter o manual da DLL com todos seus comandos e parmetros. Menu Abrir
o");
Parmetros(alquota, quantidade, preo ,tipodesconto, valor desconto, codproduto, unidade, descrio) Menu Totalizar
ECF_Daruma.iCFTotalizarCupom_ECF_Daruma("D%", "0,00");
Breve esclarecimento: Por enquanto no estamos tratando retorno dos mtodos. Esse ser outro artigo que teremos, tratando apenas o retorno dos mtodos. Por isso, no ser mostrado nenhum erro no momento da execuo dos comandos. D F5 no projeto para iniciar o Debug. Se tudo estiver devidamente configurado, a impressora vai bipar. Faa esse procedimento, clicando: Abrir / Vender / Totalizar / Pagar / Fechar. Sua impressora vai imprimir o cupom. Agora, faa os testes e mude os parmetros para ver como fica! At a prxima! ;)
//Tratamento Erro e AViso [DllImport("DarumaFrameWork.dll")] public static extern int rStatusUltimoCmdInt_ECF_Daruma(ref int pi Erro, ref intpiAviso); [DllImport("DarumaFrameWork.dll")] public static extern int eInterpretarErro_ECF_Daruma(int iErro, St ringBuilderpszDescErro); [DllImport("DarumaFrameWork.dll")] public static extern int eInterpretarAviso_ECF_Daruma(int iAviso, Stri ngBuilderpszDescAviso);
Com isso pronto, criaremos um GroupBox em nossa Janela ECF, e vamos inserir 10 Labels. 5 deles levaro o ttulo, e os outros 5 recebero os retornos. Nomeei as cinco que recebero o retorno de: label_retornometodo label_coderro label_stringerro label_codaviso label_stringaviso Os labels que recebem o nome ficaram com o nome padro (Label1, Label2...). Os asteriscos coloridos so os labels que citei acima, na ordem. Ento, a Janela ECF ficou desta forma:
Feito esses pequenos ajustes, vamos ao cdigo. Vamos criar uma funo que realizar todo o tratamento de retorno. Podemos fazer o tratamento mtodo a mtodo, e isso no deixar seu programa lento. Optei por fazer dessa forma por ser mais rpido e prtico. Ao invs de falar linha a linha, copiei e colei o tratamento de retorno com todas as linhas comentadas.
//funo tratamento de erro e aviso // TratamentoRetorno o nome da funo. Voc pode trocar se preferir. // int RetornoFuncao recebe o retorno do mtodo ( 1, -1, -6 , -12) private void TratamentoRetorno(int RetornoFuncao) { int iErro=0; //declara iErro int iAviso = 0; //declara iAviso //monta a string eErro com tamanho 300 StringBuilder eErro = new StringBuilder(300); //monta a string eAviso com tamanho 300 StringBuilder eAviso = new StringBuilder(300); label_coderro.Text = ""; //Limpa o Label label_codaviso.Text = ""; //Limpa o Label label_stringerro.Text = ""; //Limpa o Label label_stringaviso.Text = ""; //Limpa o Label //Mostra o retorno do mtodo label_retornometodo.Text = RetornoFuncao.ToString(); //trata os status de erro e aviso do ultimo comando ECF_Daruma.rStatusUltimoCmdInt_ECF_Daruma(ref iErro, ref iAvis //Parte que interpreta os valores das variaveis da funco acima. ECF_Daruma.eInterpretarErro_ECF_Daruma(iErro, eErro); //interpreta o iErro inteiro e mostra como eErro string ECF_Daruma.eInterpretarAviso_ECF_Daruma(iAviso, eAviso); //interpreta o iAviso inteiro e mostra como eAviso string //mostra nos labels os retornos label_coderro.Text = iErro.ToString();//Mostra codigo erro no label
o);
no label no label
label_codaviso.Text = iAviso.ToString(); //mostra codigo aviso label_stringerro.Text = eErro.ToString(); //mostra string erro
Com o cdigo acima, nossa funo tratar qualquer retorno do mtodo. Isso no interessante. Por qu? Pense comigo: se o mtodo retorna 1 sempre que executado com sucesso, eu no preciso tratar os retornos quando o meu retorno for igual a 1, certo? No h sentido em tratar algo que no contm erros. Por isso, vamos colocar uma condio if , para executar os mtodos apenas quando minha varivel intRetornoFuncao, for diferente de [1]. Colocaremos o if abaixo do incio da nossa funo.
private void TratamentoRetorno(int RetornoFuncao) { if (RetornoFuncao != 1) {
. . .
label_stringaviso.Text = eAviso.ToString(); //mostra string aviso no label } }
Pronto! Estrutura de tratamento de retorno criada com sucesso! Agora hora de aplicar isso em nossas funes j criadas. At agora ns criamos as seguintes funes:
ECF_Daruma.iLeituraX_ECF_Daruma() ECF_Daruma.iReducaoZ_ECF_Daruma("", "") ECF_Daruma.iCFAbrir_ECF_Daruma("11111111111", "Rafael", "VisualStudio") ECF_Daruma.iCFVender_ECF_Daruma("F1", "1,000", "01,40", "D%", "0,00", "123 456", "UN", "COCA COLA 2LT") ECF_Daruma.iCFTotalizarCupom_ECF_Daruma("D%", "0,00") ECF_Daruma.iCFEfetuarPagamento_ECF_Daruma("Dinheiro", "5,00", "Volte Sempre") ECF_Daruma.iCFEncerrar_ECF_Daruma("0", "Aplicativo Teste")
Para que tratemos os retornos das funes acima, devemos inserir o nome da nossa funo de tratamento de retorno antes delas. Ficar algo desse tipo:
TratamentoRetorno(ECF_Daruma.iLeituraX_ECF_Daruma()); TratamentoRetorno(ECF_Daruma.iReducaoZ_ECF_Daruma("", "")); TratamentoRetorno(ECF_Daruma.iCFAbrir_ECF_Daruma("11111111111", "Rafael"," VisualStudio"));
TratamentoRetorno(ECF_Daruma.iCFVender_ECF_Daruma("F1", "1,000", "01,40", "D%","0,00", "123456", "UN", "COCA COLA 2LT")); TratamentoRetorno(ECF_Daruma.iCFTotalizarCupom_ECF_Daruma("D %", "0,00")); TratamentoRetorno(ECF_Daruma.iCFEfetuarPagamento_ECF_Daruma("Dinheiro", "5 ,00","Volte Sempre")); TratamentoRetorno(ECF_Daruma.iCFEncerrar_ECF_Daruma("0", "Aplicativo Teste"));
Prontinho! Nossos mtodos j so tratados para qualquer erro ou aviso! Faremos um teste! Compile seu sistema e mande abrir um cupom fiscal. Depois de aberto, execute novamente o comando de abrir o cupom. Veja o que acontece com os labels! Agora, pessoal, vamos fazer alguns ajustes. Em nosso prximo artigo, falaremos do arquivo XML. O que ele afinal? Para que serve? Basicamente ele um arquivo de configurao. o local onde a DLL armazena informaes para seu correto funcionamento, tais como porta serial que a impressora est instalada, velocidade de trabalho. Existe uma chave dentro desse arquivo que modifica tambm o nosso tratamento de retorno. Falarei brevemente dela, pois algum pode ter um problema com o tratamento de retorno com o condicional if . Neste XML existe uma chave chamada <RetornarAvisoErro>0</RetornarAvisoErro>. Com ela DESABILITADA ( 0 ), a dll sempre retornar [1] no mtodo. Nesse caso, nem sempre o retorno [1] significa que ocorreu tudo certo. Vou dar um exemplo: Eu mandei abrir um cupom, a impressora imprimiu. Eu mandei novamente o comando de abertura do cupom e o que acontece? O retorno do mtodo [1]. A voc vem e diz: Mas a t errado, no pode ser assim! Depende. O mtodo ser executado no est ligado a ter sido impresso ou no. O mtodo foi executado, contudo o ECF emitiu um erro. Se tirarmos o if e deixamos a funo tratando TODOS retornos, vamos ter o seguinte cenrio. Abri o cupom. Mandei abrir novamente Retorno do mtodo [1] Com Sucesso Funo de tratamento acionada. Interpretao de erro e aviso acionada. Retorno da funo eInterpretarErro = 78 String do Erro: CF Aberto Visualmente temos o seguinte:
Agora, se essa chave est habilitada (1), o tratamento dispensvel quando RetornoFuno = [1]. Dvidas sobre o XML? No deixe de ler nosso prximo artigo! Espero que vocs tenham entendido. Qualquer dvida, postem ou entre em contato conosco!
Essas duas indicam os locais onde sero salvos os arquivos que a DLL consegue extrair do ECF, como os relatrios do PAF-ECF. Chave <ECF> No falarei de todas as chaves, apenas as mais importantes. <ArredondarTruncar> </ArredondarTruncar> Essa chave indica a DLL com qual modo ela deve trabalhar na venda do item. A para Arredondamento e T para Truncamento. <Auditoria></Auditoria> Auditoria o LOG que armazena os dados enviados e recebidos pela impressora. muito utilizado no Suporte ao Desenvolvedor da Daruma, por conter muitas informaes importantes na realizao dos comandos. habilitado com 1 e desabilitado com 0. <ReducaoZAutomatica></ReducaoZAutomatica> Efetua a reduo Z de forma automtica sempre que ficar pendente. Com ela ativada [1], a DLL verifica assim que aberto seu sistema, se no dia anterior foi tirada a ReduoZ. Se no, imprime. Se foi, no executa nada. <RetornarAvisoErro></RetornarAvisoErro> Essa chave de extrema importncia para nosso artigo 4 Tratamento de Retorno. Com ela ativada [1], os mtodos retornam -12 em caso de erro ou aviso. Com ela desativada [0], os mtodos retornam que foram realizados com sucesso, mesmo se esbarraram com um cupom fiscal aberto, reduo z pendente. <PortaSerial> </PortaSerial> a porta com a qual a DLL ir tentar comunicao. Ela sempre vai enxergar essa porta e tentar estabelecer comunicao com ela. Ex: COM1, COM2. <Velocidade></Velocidade> a velocidade que a impressora e a porta COMx esto configuradas. Ela deve ser igual s outras para que a comunicao seja estabelecida com sucesso. Ex: 9600, 115200 No HELP da DarumaFramework, existe uma parte que fala chave a chave. Esse HELP encontra-se no sitehttp://www.desenvolvedoresdaruma.com.br/, ou no blog em Links Importantes. Alterando via Software Utilizaremos apenas 1 mtodo para fazer alteraes em todas as chaves. , apenas um mesmo, no precisa se assustar. Essa outra inovao da DarumaFramework. Declaremos as funes:
//Mtodos de Registro [DllImport("DarumaFrameWork.dll")]//Altera valor do XML public static extern int regAlteraValorChave_DarumaFramework(strin g pszProduto,string pszChave, string pszValor); [DllImport("DarumaFrameWork.dll")]//Consulta Valor da chave do XML public static extern int regRetornaValorChave_DarumaFramework(stri ng sProduto, stringsChave, [MarshalAs(UnmanagedType.VBByRefStr)] ref string szRetorno);
Pessoal, uma dica: Tentem comentar e separar os trechos das declaraes. Fica mais fcil de encontrar posteriormente. Esses mtodos tm como parmetros trs strings. A primeira indica o produto, a segunda a chave, e a terceira o valor a ser inserido. O primeiro mtodo altera as chaves. O segundo retorna o valor delas.
Para alterar as chaves, vamos criar um GroupBox, um boto, 3 labels e trs textbox para brincar um pouco. Para visualizar, criaremos outro GroupBox com 6 labels, onde 3 sero atualizados assim que alterarmos as chaves e os valores. Toda minha ao ser comandada pelo boto AlterarXml, que acionar o mtodo de alterao e consulta, e mostrar a alterao que e fiz ao lado. Para facilitar o entendimento, segue a tela das alteraes que fiz.
<!--[if !vml]--><!--[endif]--> Feito isso, vou alterar os nomes dos textbox e labels, para organizar. Alterar XML TextBox do Produto. Nomeei como tbx_produto TextBox da Chave. Nomeei como tbx_chave TextBox do Valor. Nomeei como tbx_valor Valores XML Label que recebe produto nomeei label_retproduto Label que recebe Chave nomeei como label_retchave Label que recebe Valor nomeei como label_retvalor Feito essa pequena alterao, vamos a execuo da funo. Usarei o mtodo regAlteraValorChave_DarumaFramework para alterar o valor do XML e o mtodo regRetornaValorChave_DarumaFramework para consultar o XML. Vamos criar um evento para nosso boto de alterao, o bt_alterarxml.
private void bt_alterarxml_Click(object sender, EventArgs e) //Com ando de Alterar XML { }
Primeiramente terei de criar as strings para os parmetros dos mtodos. Criei ento:
string str_produto = tbx_produto.Text; string str_chave = tbx_chave.Text; string str_valor = tbx_valor.Text;
Aproveitei para j atribuir os valores das variveis aos valores recebidos pelos textbox. Feito isso, nosso evento est praticamente pronto. Falta apenas inserir a funo:
TratamentoRetorno(ECF_Daruma.regAlteraValorChave_DarumaFramework(str_produ to,str_chave, str_valor));
No se esquea de inserir sua funo de tratamento de retorno. Apenas com isso o arquivo XML j alterado. Mas e para consultar os registros, como fao? Vamos para a segunda parte! Aproveitando o mesmo evento, vou criar uma nova string chamada str_valor_, para receber o valor que eu alterei na chave. Aproveitarei as outras duas variveis str_produto e str_chave para consultar as mesmas logo depois que eu alterar os valores, troquei a que recebe o valor para no ter confuso e acharem que eu apenas mantive os valores. Como a varivel que recebe o valor por referencia, ento chamamos a funo
ECF_Daruma.regRetornaValorChave_DarumaFramework(str_produto, str_chave, ref str_valor_);//Comando de Consultar XML
Note que utilizei 2 variaveis iguals, apenas a str_valor_ que diferente. Isso far que eu visualize a chave que eu acabei de alterar. Como o C# pede que defina o tamanho de variveis por referencia, criei a seguinte linha para atribuir um tamanho a varivel str_valor_
string str_valor_ = new string(' ', 30);
Finalizando, para mostrar nos labels os retornos, igualei o label respectivo a sua varivel.
label_retproduto.Text = str_produto; label_retchave.Text = str_chave; label_retvalor.Text = str_valor_;
Com isso, podemos executar nosso programa e testar! Vamos alterar uma chave que aprendemos hoje aqui: a Auditoria. Vamos deixa-la com valor 1.
Preencha os campos com o Produto, Chave e Valor, respectivamente. Em seguida, clique em Alterar.
Conseguimos ver que o XML foi alterado graas a nossa visualizao instantnea. Tambm conseguimos ver que a funo retornou 1, com sucesso, sem erro e sem aviso.
Os parmetros so idnticos. Duas strings que recebem o valor e uma mensagem, bem simples. No nosso Form, criei um item em nosso menustrip chamado Op. No Fiscal, com Sangria e Suprimento.
Feito essa insero, vamos adicionar os eventos aos menus. Boto Sangria:
gs e) { TratamentoRetorno(ECF_Daruma.iSangria_ECF_Daruma("50,00","Retirada para Banco")); } private void sangriaToolStripMenuItem_Click(object sender, EventAr
No mtodo de Sangria, estou retirando R$50,00 do meu caixa com uma mensagem de Retirada para Banco. E tambm j chamei nossa funo de tratamento. Boto Suprimento:
private void suprimentoToolStripMenuItem_Click(object sender, Even tArgs e) { TratamentoRetorno(ECF_Daruma.iSuprimento_ECF_Daruma("100,00","Abasteciment o Caixa")); }
No mtodo de Suprimento, adicionei um valor de R$100,00 para abastecer o caixa. Pronto, j est tudo pronto! Pedi um Start Debugging para o VS e mandei executar o mtodo de Sangria.
Mtodo realizado com sucesso! possvel cadastrar esses operadores no fiscais, um para conta de luz, outra para telefone por exemplo. Bom, ficamos por aqui! At a prxima!