quinta-feira, 18 de junho de 2009

ENVIANDO E-MAIL VIA VB.NET

Abaixo, segue um pequeno código que envia e-mails via VB.NET
para uma conta no gmail.

As contas de e-mail abaixo são fictícias. Você deve alterá-las para contas reais.


O código abaixo foi colocado dentro de um timer programado para ser executado a cada cinco minutos (suas propriedades são timer4.Interval = 300000; timer4.Enabled = True).

Quando o tempo de cinco minutos é atingido, o código é então disparado.



Private Sub Timer4_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer4.Tick

If ExisteConexaoInternet() = True Then



'------------ MANDANDO E-MAILS PELO GMAIL
Dim NumeroFigura As String = "C:\temp\winnt" + "imagem1.jpg"
Const destino As String = "teresaflorindo@hotmail.com"
Const Body As String = "Teste de e-mail. Dê uma olhada!!"
Dim respostaEnvioLabel As String


Dim remetenteEmail As String = "leoflorindo@gmail.com" '; //O e-mail do remetente

Dim mail As MailMessage = New MailMessage()

mail.To.Add(destino)

mail.From = New MailAddress(remetenteEmail, "Teresa Florindo", System.Text.Encoding.UTF8)

mail.Subject = "Assunto: Imagens do computador em uso"

mail.SubjectEncoding = System.Text.Encoding.UTF8

mail.Body = Body

mail.BodyEncoding = System.Text.Encoding.UTF8

mail.IsBodyHtml = True

mail.Priority = MailPriority.High

mail.Attachments.Add(New Attachment(NumeroFigura))

Dim client As SmtpClient = New SmtpClient() '//Adicionando as credenciais do seu e-mail e senha:

client.Credentials = New System.Net.NetworkCredential(remetenteEmail, "jeovaedeus")
client.Port = 25
client.Host = "smtp.gmail.com" '; //Definindo o provedor que irá disparar o e-mail


client.EnableSsl = True '; //Gmail trabalha com Server Secured Layer

Try

client.Send(mail)
respostaEnvioLabel = "Envio do E-mail com sucesso"
'MsgBox(respostaEnvioLabel)

Catch ex As Exception


respostaEnvioLabel = "Ocorreu um erro ao enviar:" + ex.Message
'MsgBox(respostaEnvioLabel)


End Try
'-------------------- FIM DO CÓDIGO PARA O GMAIL------------------------------


End If

End Sub

Aqui está somente descrito o envio de um e-mail simples via internet. A porta de acesso é a 25. O servirdor smtp.gmail.com é informado como host.


Verifique que uma simples imagem está sendo enviada em anexo com a mensagem.

Para usar este exemplo, você deve criar uma conta no gmail para uso.



A função ExisteConexaoInternet() verifica se o computador está no caso logado a internet. Se estiver, é possível passar o e-mail sem que o usuário tenha qualquer conhecimento disso.

O código da função está descrito abaixo:

Private Function ExisteConexaoInternet() As Boolean

'Define uma URL válida para consultar

Dim url As New System.Uri("http://www.globo.com/")



'Monta a requisição HTTP

Dim req As System.Net.WebRequest

req = System.Net.WebRequest.Create(url)



'Tenta fazer a requisição

Try

Dim resp As System.Net.WebResponse

resp = req.GetResponse()

resp.Close()

req = Nothing



'Tudo certo... Temos conexão com a Internet

Return True

Catch ex As Exception

'Não deu... Conexão não dispon¡vel

req = Nothing

Return False

End Try

End Function

A função simplesmente verifica se é possível acessar com sucesso um site na internet (no caso o site da Globo). Se for possível, então há a possibilidade de se enviar e-mail via internet e o código de envio de e-mail é liberado.

sexta-feira, 12 de junho de 2009

NF-E: COLETANDO DADOS DO ARQUIVO DE SITUAÇÃO


Em alguns momentos, seja por erro no retorno do web service, seja por algo que impossibilite o acesso, os arquivos -proc-rec.xml para uma nfe enviada normalmente ao servido da sefaz poderão ser perdidos. Ao consultar o site da sefaz você constatará que a mesma já se encontra autorizada para uso, mas não possui ainda o arquivo -pro-rec.xml com número do protocolo informado no site.

Para alguns aplicativos de ERP isso pode significar um problema se de maneira normal estes aplicativos aguardam a recepção do arquivo -pro-rec.xml para validar no banco de dados da empresa a numeração do protocolo de autorização de uso e o status da nf-e no site da Sefaz.

Se o seu ERP move os arquivos de num-lot.xml, -rec.xml e -pro-rec.xml para uma outra pasta quando os mesmos são detectados e um deles não retorna - como o -pro-rec.xml - o trabalho do seu ERP estará comprometido. Você terá que criar um arquivo de pedido de situação da nf-e que enviou à Sefaz e atualizar os dados do protocolo de uso, hora de recepção e status da nf-e na mão... trabalho inglório!!!




Nessa caso, será preciso obter de um outro modo o número do protocolo de autorização da nf-e. Para obter os dados novamente, pode gerar um arquivo de pedido de status e deixar o retorno na mesma pasta onde deveria estar o arquivo -pro-rec.xml não recebido e dessa forma forçar seu ERP a ler o arquivo -sit.XML para resolver por si mesmo essa situação.


Um pedido de situação da nf-e enviado a Sefaz está listado abaixo. O arquivo é pequeno e bem simples de ser gerado:

<?xml version="1.0" encoding="UTF-8"?>
<conssitnfe xsi="http://www.w3.org/2001/XMLSchema-instance" xsd="http://www.w3.org/2001/XMLSchema" versao="1.07" xmlns="http://www.portalfiscal.inf.br/nfe">
<tpamb>1</tpamb>
<xserv>CONSULTA</xserv>
<chnfe
>13090604672291000115550110000000380000000494</chnfe>
</consSitNFe>

O nome do arquivo de pedido de situação é nfe-sit.xml.

Exemplo: 13090604672291000115550110000000380000000494-ped-sit.xml

O arquivo de retorno gerado por um pedido de situação traz em conjunto em seu interior o próprio número da nf-e, o número do protocolo de uso e o status da nf-e no site da sefaz:

< ?xml version="1.0" encoding="UTF-8"?>
<retConsSitNFe versao="1.07" xmlns="http://www.portalfiscal.inf.br/nfe"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.portalfiscal.inf.br/nfe retConsSitNFe_v1.07.xsd">

<infProt>Id="ID113090003033468">
<tpamb>1</tpamb>
<verAplic>1</verAplic>
<cStat>100</cStat>
<xMotivo>Autorizado o uso da NF-e</xMotivo
<cUF>13</cUF>
<chNFe>13090604672291000115550110000000400000000514</chNFe>
<dhRecbto>2009-06-12T08:50:58</dhRecbto>
<nProt>113090003033468</nProt>
<digVal>roFtqwdm/MZJQEmiXms/u3hwEe4=</digVal>
</infProt>


Para coletar a informação do número de protocolo para ser usado na impressão da DANFE, um simples IF a mais precisa ser acrescentado ao código de impressão da DANFE.

Você pode checar antes da impressão da DANFE se há a existência de um arquivo de pedidido de situação ou o arquivo pro-rec.xml de retorno do recibo.

Eis um código em VB.NET para isso:


Dim NomeArquivoRecibo As String

NomeArquivoRecibo = "F:\SisWin\IAM\NFE\RETORNO\PROCESSADOS\" + IdNfe + "-pro-rec.xml"

'Danfe Normal. Pega os dados dos recibos e do protocolo de uso
If TipodeEmissao = "1" Then


'Verifica se já houve retorno do arquivo selecionado
If IO.File.Exists(NomeArquivoRecibo) = False Then

Dim NomeArquivoRecibo5 As String

'Algo errado com o retorno do recibo. Procurar pelo arquivo de situação
'da NF-e. Necessário para os erros de falta de dados do arquivo -pro-rec.xml

'Ler dados do arquivo de retorno de situação, caso o status do
'recibo de retorno esteja diferente de 104

NomeArquivoRecibo5 = "F:\SisWin\NFE\RETORNO\PROCESSADOS" + IdNfe + "-sit.xml"
'Abrir o arquivo de retorno situação de status
Dim reader_5 As XmlTextReader = New XmlTextReader(NomeArquivoRecibo5)

If IO.File.Exists(NomeArquivoRecibo5) = False Then

MsgBox("Impressão da DANFE Cancelada!!! Sem Recibo de Retorno! Envie a NF-e primeiro a SEFAZ!!", MsgBoxStyle.Critical, "DANFE Coplast")
Exit Sub

Else

Do While (reader_5.Read())


Select Case reader_5.NodeType
Case XmlNodeType.Element

If reader_5.Name = "nProt" Then
LProtocolo2 = reader_5.ReadString

If LProtocolo2 <> "" Then
myRow2.NumProtocolo = LProtocolo2
End If

End If

End Select

Loop
reader_5.Close()


End If

(...)


Esse pequeno trecho fará a leitura do dado do Protocolo diretamente do arquivo -sit.xml gerado.

O trecho também pode ser utilizado para gravar o registro de protocolo no banco de dados a fim de evitar problemas quando não se consegue obter o -pro-rec.xml de modo correto no retorno do site da Sefaz.




Sorte a todos!

segunda-feira, 25 de maio de 2009

MANTENDO A MENTE ABERTA PARA O APRENDIZADO


Já foi-se o tempo em que os programadores possuíam suas linguagens
preferidas para trabalho em empresas.

Nos tempos modernos de nossos dias é crucial e necessário ter o domínio de mais de uma linguagem de programação e manter sempre a mente aberta para novos aprendizados.

Foi reunindo os melhores desenvolvedores em VB, ASP e C# que a Microsoft desenvolveu a plataforma .NET. Interligar em uma mesma ferramenta de desevolvimento várias linguagens promove o conhecimento e gera o crescimento entre os desenvolvedores, expandindo seus horizontes para outras áreas como internet e trabalhos em modo cliente servidor.

Aprender deve estar no âmago de todo o bom desenvolvedor de software e deve possibilitar saltos de tecnologia. Por mais que seja bem cômodo ocupar uma vaga em uma empresa que usa somente a mesma linguagem de programação e que faça com que se acomode é importante participar de treinamentos e realizar cursos para se manter inteirado das novas soluções corporativas existentes no mercado. Além de ser algo inteligente investir em si mesmo, você pode estar preparado para mudanças em novas áreas, como a NF-e e seus requisitos para a RFB.

Entender isso é saber que as milhares de linha que você gastará em VB 6 e Delphi para desenvolver a solução são quase nada em comparação no VB.Net. Para isso as linguagens de programação evoluem: permitir que novas soluções e maior interatividade sejam ganhas e tornar as áreas de TI melhor equipadas não somente com um bom hardware, mas com o que de melhor há no mercado no momento.

É cômodo para algumas empresas não desenvolver de VB 6 para VB.NET por motivos de investimentos altos em tecnologia. Mas grandes empresas vêem nesse caminho um ramo natural para a evolução e ganhos de mercado. Se as áreas de TI se tornam cômodas com o que desenvolvem não aproveitam as novas tecnologias e, com o tempo, caem na armadilha de desenvolver grandes códigos para soluções que são fáceis de realizar em novas linguagens de programação.

Não é constragedor verificar que se pensa em desenvolver e se fazer atualizações na área de segurança - como alterar o Linux do firewall - mas não se pensa em atualizar as aplicações internas de Visual Basic 6 para Vb.Net aprimorando com isso todo o ganho possível que se terá com o uso da nova linguagem e de suas companheiras??

Quem se envolve em TI deve estar pronto para aprender o novo e para ser confrotado com o novo. Manter a mente aberta e renovar seus conhecimentos é se fazer apto em vários oportundades que surgirem no mercado.

Saber somente o Visual Basic 6 e o Delphi já não atendem tanto quem necessita criar soluções para uma Nf-e até setembro de 2009.

E se nas próximas atualizações se fizer necessário o uso de tecnologias mais atuais somente disponíves na plataforma .NET??

Evoluir é preciso.

Trabalhe nesse sentido.

segunda-feira, 18 de maio de 2009

MANUAL 3.0 - CÓDIGO DE BARRAS PARA A CONTINGÊNCIA EM VB.NET

O novo manual de integração para a NF-e 3.0 traz vários novos ajustes a realizar na composição da DANFE e deverá entrar em vigor a partir de 31/08/2009.

Uma das novas alterações diz respeito a impressão da DANFE no modo de contigência que, com esse novo manual, pedirá a emissão de um código de barras próprio para os dados da DANFE em contigência.

Esse novo código de barras deverá ser impresso abaixo do código de
barras da nf-e
, conforme mostrado na figura abaixo:




O campo responsável pela emissão desse código de barras será a tag TpEmis dentro do XML da Nf-e. Se o campo TpEmis for diferente de 1 indicará a emissão de uma DANFE em modo de Contingência.

O campo DADOS DA NF-e contêm a composição da chave em código de barras. Ao passar a leitora sobre o segundo código de barras, o resultado de valor esperado deverá ser o que está contido dentro do campo DADOS da NF-e. Quando a DANFE foi emitida em modo normal, o nome desse campo deverá ser PROTOCOLO DE AUTORIZAÇÃO DE USO e deverá conter o referido protocolo de autorização da Nf-e.


A composição do campo DADOS DA NF-e pode ser vista no código VB.Net abaixo:

'Compõe a chave para o código de barras da Danfe em Contigência, se for necessário
DiadaEmissao = Mid(myRow2.dEmi, 1, 2)
TipodeEmissao = myRow2.tpEmis
CodigoUF = DigitoUF(myRow2.destUF)
DadosdaNfe = Trim(CodigoUF + TipodeEmissao + myRow2.destCNPJ + ValorvNF + "2" + "2" + DiadaEmissao)
DigitoDadosNfe = Calculo_DV11(DadosdaNfe)

'Inserção do dígito verificador do módulo 11 para a Nf-e
DadosdaNfe = DadosdaNfe + Trim(DigitoDadosNfe)



A função Calculo_DV11 retorna o cálculo em módulo 11 para o digito verificador dos dados da NF-e e é apresentada abaixo:

Function Calculo_DV11(ByVal strNumero As String) As String

'declara As variáveis
Dim intContador As Integer
Dim intNumero As Integer
Dim intTotalNumero As Integer
Dim intMultiplicador As Integer
Dim intResto As Integer
Dim ValorDigito As Integer

' se nao for um valor numerico sai da função
If Not IsNumeric(strNumero) Then
Calculo_DV11 = ""
Exit Function
End If

'inicia o multiplicador
intMultiplicador = 2

'pega cada caracter do numero a partir da direita
For intContador = Len(strNumero) To 1 Step -1

'extrai o caracter e multiplica pelo multiplicador
intNumero = Val(Mid(strNumero, intContador, 1)) * intMultiplicador

intMultiplicador = intMultiplicador + 1

' se o resultado for maior que nove soma os algarismos do resultado
If intMultiplicador > 9 Then
intMultiplicador = 2
End If

'soma o resultado para totalização
intTotalNumero = intTotalNumero + intNumero

Next

'calcula o resto da divisao do total por 11
intResto = intTotalNumero Mod 11

ValorDigito = 11 - intResto
'verifica as exceções ( 0 -> DV=0 1 -> DV=0 e retorna o DV
Select Case ValorDigito
Case 0
Calculo_DV11 = "0"
Case 1
Calculo_DV11 = "0"
Case Else
Calculo_DV11 = Str(ValorDigito)
End Select

End Function


Após a chave ser composta, a geração do código de barras poderá então ser realizada, com um código simples de chamada para a geração do código de barras:


'Nf-e em contingência / Gerar código de Barras dos dadosdaNFE
If TipodeEmissao <> "1" Then

'Cria o código de barras para a Danfe em Contingência, se houver
'Pôr o código de barras em oculto, se não houver o que gerar
myRow2.DadosNfe = DadosdaNfe
Dim Barcode2 As New BarcodeLib.Barcode(DadosdaNfe, BarcodeLib.TYPE.CODE128C)
PictureBox3.Image = Barcode2.Encode(BarcodeLib.TYPE.CODE128C, DadosdaNfe, 300, 150)
Barcode2.SaveImage("C:\NF-E\Barras\BARRAS2.JPG", BarcodeLib.SaveTypes.JPG)

Dim fs As New FileStream("C:\NF-E\Barras\BARRAS2.JPG", FileMode.Open)
Dim br As New BinaryReader(fs)
myRow2.Imagem2 = br.ReadBytes(br.BaseStream.Length)

br.Close()
fs.Close()

br = Nothing
fs = Nothing

Else
myRow2.Imagem2 = Nothing

End If


O campo Imagem2 deverá ser criado para receber o código de Barras da DANFE impressa em contigência.


Sorte a todos!!



sexta-feira, 15 de maio de 2009

NF-e: Criando um validador para a NF-e em VB.NET


Vamos criar um pequeno aplicativo de validação da Nf-e, executável
em uma chamada por parâmetro. Para executar esse aplicativo, simplesmente
você deverá clicar no botão Iniciar no Windows e selecionar a opção Executar
no menu, informando o seguinte comando:

C:\ValidarNfe.exe C:\NF-E\13090404672291000115550040000000270000000730-nfe.xml

Veja o o exemplo na figura abaixo:





1) Inicie um novo projeto no Vb.NET.

2) Defina nas referências do projeto (Menu Projects - ValidarNfe Properties - aba References) os seguintes namespaces:

System
System.Data
System.Deployment
System.Drawing
System.Security
System.Web.Services
System.Windows.Forms
System.Xml

3) Inclua no formulário uma timer, uma label, um listbox e um botão.


A tela deve ficar como o mostrado abaixo:



4) Defina a propriedade interval do timer em 1000, e dê dois cliques sobre ele. Informe o seguinte código para o Timer:

Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
Me.Show()
End Sub



5) Dentro do código do formulário (form1.vb), no início do mesmo, inclua as seguintes referências:

Imports System.Collections.Generic
Imports System.Text
Imports System.Xml
Imports System.Xml.Schema
Imports System.IO
Imports System.Windows.Forms
Imports System.Security.Cryptography.Xml
Imports System.Security.Cryptography.X509Certificates


6) No evento Load do formulário, acrescente este código:

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

Dim Valor As String

Me.Show()
If Command() <> "" Then
Valor = Command()
ValidaNfe(Valor)

Me.Focus()
Me.Show()
Me.WindowState = FormWindowState.Normal

End If

End Sub


7) O código do botão Fechar deve ser o que segue abaixo:

Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
End
End Sub

8) A função ValidaNfe é a que segue abaixo:

Private Sub ValidaNfe(ByVal NfeAler As String)

Try

'Abrir agora o arquivo XML criado e inserir o Protocolo encontrado!!
Dim arquivo2 As String = NfeAler
Dim xDoc As New XmlDocument : xDoc.Load(arquivo2)
Dim Tamanho As String
Dim Nfe As String


Nfe = arquivo2
Tamanho = Replace(Nfe, "C:\", "")
Tamanho = Replace(Tamanho, "F:\SisWin\NFE\BACKUP\200905\", "")
Tamanho = Replace(Tamanho, "F:\SisWin\NFE\BACKUP", "")
Tamanho = Replace(Tamanho, "F:\SisWin\NFE\AENVIAR", "")
Tamanho = Replace(Tamanho, "F:\SisWin\NFE\AENVIAR", "")
Tamanho = Replace(Tamanho, "\", "")
Tamanho = Replace(Tamanho, "\NF-E", "")
Tamanho = Replace(Tamanho, "NF-E", "")
Tamanho = Replace(Tamanho, "SisWin", "")
Tamanho = Replace(Tamanho, "SisWin", "")

'Fazer uma cópia d arquivo XML para gerar a assinatura
Dim CaminhoArquivo As String = "C:\NF-E\XML\" + Tamanho

'Salva o Arquivo
xDoc.Save(CaminhoArquivo)

'Selecionar certificado
SelecionarCertificado()

'Assinar o XML
Dim OAd As New AssinaturaDigitalClass()
Dim pDadosNfe As String
Dim vStringNfe As String
'Dim msgResultado As String


OAd.Assinar(CaminhoArquivo, "infNFe", oCertificado)

If OAd.vResultado = 0 Then 'Assinado corretamente

pDadosNfe = OAd.vXMLStringAssinado
vStringNfe = pDadosNfe.Substring(pDadosNfe.IndexOf("<NFe"), pDadosNfe.Length - pDadosNfe.IndexOf("<NFe"))


Else 'Ocorreu algum erro na assinatura
MessageBox.Show(OAd.vResultadoString, "Erro", MessageBoxButtons.OK, MessageBoxIcon.Error)
End If

'Validar o XML
Dim TxtXSD As String

TxtXSD = "C:\tmp\Schemas NF-e\nfe_v1.10.xsd"

If Not CaminhoArquivo = String.Empty And Not TxtXSD = String.Empty Then

Resultado = True
Dim settings As New XmlReaderSettings()
AddHandler settings.ValidationEventHandler, AddressOf Me.ValidationEventHandler

'Valida o arquivo XML com o seu Schema XSD
lstValida.Items.Add("Validando o arquivo XML " & CaminhoArquivo & " com o arquivo de Schema : " & TxtXSD)

Try

settings.ValidationType = ValidationType.Schema
settings.Schemas.Add("http://www.portalfiscal.inf.br/nfe",xmlReader.Create(TxtXSD))
Using XmlValidatingReader As XmlReader = XmlReader.Create(CaminhoArquivo, settings)
While XmlValidatingReader.Read()

End While

End Using

Catch ex As Exception

lstValida.Items.Add(ex.Message)
Exit Sub
End Try

lstValida.Items.Add("Status Validação -> " & IIf(Resultado = True, "Arquivo validado com SUCESSO", "Validação FALHOU"))

Else
MsgBox("Informe o arquivo XML e o arquivo XSD.")
End If


Catch ex As Exception

'se ocorrer uma exceção exibe a mensagem
lstValida.Items.Add(ex.Message)

End Try

End Sub

A função ValidaNfe chama outras duas funções em seu início: uma que seleciona o certificado automaticamente e outra que assina o documento. O código da função SelecionarCertificado() é que segue abaixo:

Function SelecionarCertificado() As Boolean

Dim vRetorna As Boolean
Dim oX509Cert As New X509Certificate2
Dim store As New X509Store
Dim collection As New X509Certificate2Collection
Dim collection1 As New X509Certificate2Collection
Dim collection2 As New X509Certificate2Collection
Dim scollection As New X509Certificate2Collection
Dim msgResultado As String
Dim xnome As String

xnome = "CN=CERTIFICADOTESTE:09999991000115, OU=Autenticado por AR Fenacon, OU=RFB e-CNPJ A1, OU=Secretaria da Receita Federal do Brasil - RFB, L=Manaus, S=AM, O=ICP-Brasil, C=BR"

oX509Cert = New X509Certificate2()
store = New X509Store("MY", StoreLocation.CurrentUser)
store.Open(OpenFlags.ReadOnly Or OpenFlags.OpenExistingOnly)
collection = store.Certificates
collection1 = collection.Find(X509FindType.FindByTimeValid, DateTime.Now, False)
collection2 = collection.Find(X509FindType.FindByKeyUsage, X509KeyUsageFlags.DigitalSignature, False)

'Encontra o certificado digital pelo nome do mesmo, se precisar pergunta por isso
'Resolvido em 13/05/2009 às 15:05h
scollection = collection.Find(X509FindType.FindBySubjectDistinguishedName, xnome, False)


'Para selecionar o certificado de uma lista
'scollection = X509Certificate2UI.SelectFromCollection(collection2, "Certificado(s) Digital(is) disponível(is)", "Selecione o certificado digital para uso no aplicativo", X509SelectionFlag.SingleSelection)

If (scollection.Count = 0) Then

msgResultado = "Nenhum certificado digital foi selecionado ou o certificado selecionado está com problemas."
MessageBox.Show(msgResultado, "Advertência", MessageBoxButtons.OK, MessageBoxIcon.Warning)
vRetorna = False

Else

oX509Cert = scollection.Item(0) 'Para selecionar o item em Vb.NET
oCertificado = oX509Cert
vRetorna = True
'msgResultado = "Certificado Selecionado."
'MessageBox.Show(msgResultado, "Advertência", MessageBoxButtons.OK, MessageBoxIcon.Warning)
Return vRetorna

End If

End Function

-----------------

Voce deve informar em xnome o nome por extenso do Certificado que irá usar para validar a XML a ser assinado. Para obter o nome por extenso do seu certificado você pode usar a próprioa função acima habilitando a que pede a seleção de certicados de uma lista e colocando o seguinte comando no Else da função acima:

xnome = oCertificado.Subject.ToString

Esse comando colocará o nome do certificado na variável xnome. Se você debugar, pode pegar o nome extenso do certificado que deve usar para validar o XML e colocar dentro da váriavel, como fiz no início do código:

xnome = "CN=CERTIFICADOTESTE:09999991000115, OU=Autenticado por AR Fenacon, OU=RFB e-CNPJ A1, OU=Secretaria da Receita Federal do Brasil - RFB, L=Manaus, S=AM, O=ICP-Brasil, C=BR"


Para a assinatura digital uma classe é acrescentada totalmente no final da classe do formulário. Essa classe é responsável pela assinatura do XML. Eis o código abaixo:

Public Class AssinaturaDigitalClass

Public vResultado As Integer
Public vResultadoString As String
Public vXMLStringAssinado As String
Public XmlDoc As XmlDocument

Sub Assinar(ByVal pArqXMLAssinar As String, ByVal pUri As String, ByVal pCertificado As X509Certificate2)

'Abrir o arquivo XML a ser assinado e ler o seu conteúdo
Dim SR As StreamReader
Dim vXMLString As String

SR = File.OpenText(pArqXMLAssinar)
vXMLString = SR.ReadToEnd()
SR.Close()

' //Atualizar atributos de retorno com conteúdo padrão
vResultado = 0
vResultadoString = "Assinatura realizada com sucesso"

Try

'Verifica o certificado a ser utilizado na assinatura
Dim _xnome As String
Dim _X509Cert As X509Certificate2
Dim store As X509Store
Dim collection As X509Certificate2Collection
Dim collection1 As X509Certificate2Collection

_xnome = ""

_xnome = pCertificado.Subject.ToString()

_X509Cert = New X509Certificate2()
store = New X509Store("MY", StoreLocation.CurrentUser)
store.Open(OpenFlags.ReadOnly Or OpenFlags.OpenExistingOnly)

collection = store.Certificates
collection1 = collection.Find(X509FindType.FindBySubjectDistinguishedName, _xnome, False)


If (collection1.Count = 0) Then
vResultado = 2
vResultadoString = "Problemas no certificado digital"
Else

' certificado ok
'oX509Cert = scollection.Item(0)

_X509Cert = collection1.Item(0)
Dim x As String
x = _X509Cert.GetKeyAlgorithm().ToString()

' Create a new XML document.
Dim doc As New XmlDocument
doc = New XmlDocument()

'Format the document to ignore white spaces.
doc.PreserveWhitespace = False

' Load the passed XML file using it’s name.
Try
doc.LoadXml(vXMLString)

' Verifica se a tag a ser assinada existe é única
Dim qtdeRefUri As Integer
qtdeRefUri = doc.GetElementsByTagName(pUri).Count

If (qtdeRefUri = 0) Then
' a URI indicada não existe
vResultado = 4
vResultadoString = "A tag de assinatura " + pUri.Trim() + " não existe"

Else
' Existe mais de uma tag a ser assinada
If (qtdeRefUri > 1) Then
' existe mais de uma URI indicada
vResultado = 5
vResultadoString = "A tag de assinatura " + pUri.Trim() + " não é unica"
Else

Try
' Create a SignedXml object.
Dim signedXml As SignedXml
signedXml = New SignedXml(doc)

' Add the key to the SignedXml document
signedXml.SigningKey = _X509Cert.PrivateKey

' Create a reference to be signed
Dim reference As New Reference
reference = New Reference()

'--------- RETIRAR COMENTÁRIOS DAS LINHAS ABAIXO
' pega o uri que deve ser assinada
Dim _Uri As XmlAttributeCollection
Dim _atributo As XmlAttribute

_Uri = doc.GetElementsByTagName(pUri).Item(0).Attributes
For Each _atributo In _Uri
If (_atributo.Name = "Id") Then
reference.Uri = "#" + _atributo.InnerText

End If
Next

' Add an enveloped transformation to the reference.
Dim env As New XmlDsigEnvelopedSignatureTransform
env = New XmlDsigEnvelopedSignatureTransform()
reference.AddTransform(env)

Dim c14 As New XmlDsigC14NTransform
c14 = New XmlDsigC14NTransform()
reference.AddTransform(c14)

' Add the reference to the SignedXml object.
signedXml.AddReference(reference)

' Create a new KeyInfo object
Dim keyinfo As New KeyInfo
keyinfo = New KeyInfo()

' Load the certificate into a KeyInfoX509Data object
' and add it to the KeyInfo object.
keyinfo.AddClause(New KeyInfoX509Data(_X509Cert))

' Add the KeyInfo object to the SignedXml object.
signedXml.KeyInfo = keyinfo
signedXml.ComputeSignature()

' Get the XML representation of the signature and save
' it to an XmlElement object.
Dim xmlDigitalSignature As XmlElement
xmlDigitalSignature = signedXml.GetXml()

' Gravar o elemento no documento XML
doc.DocumentElement.AppendChild(doc.ImportNode(xmlDigitalSignature, True))
XmlDoc = New XmlDocument()
XmlDoc.PreserveWhitespace = False
XmlDoc = doc

' Atualizar a string do XML já assinada
vXMLStringAssinado = XmlDoc.OuterXml

' Gravar o XML no HD
' abre um stream para escrita e cria um StreamWriter para implementar o stream
Dim fs As New FileStream(pArqXMLAssinar, FileMode.OpenOrCreate, FileAccess.Write)
Dim SW_2 As New StreamWriter(fs)
SW_2.Flush()
SW_2.BaseStream.Seek(0, SeekOrigin.Begin)
SW_2.Write(vXMLStringAssinado)
SW_2.Flush()
SW_2.Close()

Catch ex As Exception
vResultado = 6
vResultadoString = "Erro ao assinar o documento - " + ex.Message

End Try

End If

End If

Catch ex As Exception

vResultado = 3
vResultadoString = "XML mal formado - " + ex.Message

End Try

End If

Catch ex As Exception

vResultado = 1
vResultadoString = "Problema ao acessar o certificado digital" + ex.Message

End Try

End Sub

End Class


9) Dentro do botão que faz a validação é repassado o código do arquivo XSD que faz a validação:

TxtXSD = "C:\tmp\Schemas NF-e\nfe_v1.10.xsd"

Um EventHandler se faz necessário para a leitura da validação do XSD.

Abaixo, vemos o código da função de validação do EventHandler:


Public Sub ValidationEventHandler(ByVal sender As Object, ByVal args As ValidationEventArgs)


Resultado = False

'lstValida.Items.Add(vbTab + "Erro de Validação : " + args.Message)

If args.Severity = XmlSeverityType.Warning Then

MsgBox("Nenhum arquivo de Schema foi encontrado para efetuar a validação...")

ElseIf args.Severity = XmlSeverityType.Error Then

lstValida.Items.Add(args.Message)
'MsgBox("Ocorreu um erro durante a validação....")

End If

If Not (args.Exception Is Nothing) Then ' Erro na validação do schema XSD

'lstValida.Items.Add(args.Exception.SourceUri + "," & args.Exception.LinePosition & "," & args.Exception.LineNumber)
'MsgBox(args.Exception.SourceUri + "," & args.Exception.LinePosition & "," & args.Exception.LineNumber)

End If

End Sub

Essa função será chamada para retornar o erro que possa estar acontecendo com algum ponto do arquivo XML.

Pronto!!

Cada passo de uma validação para a Nf-e foi descrita acima.

Posto o código completo do arquivo form1.VB abaixo para dirrimir quaisquer dúvidas:

'Validador para arquivos Nf-e
'Data de criação: 12/05/2009
'Para ser utilizado com o Visual Basic 6
'A aplicação funciona com chamada de parâmetro na linha digitável
'Para executar esse aplicativo, use a linha de comando do Windwos
'clicando no botão iniciar de depois em Executar:
'Exemplo de chamada: C:\ValidarNfe.exe C:\NF-E\13090404672291000115550040000000270000000730-nfe.xml
'Desenvolvedor: Manoel Leonardo Metelis Florindo

Imports System.Collections.Generic
Imports System.Text
Imports System.Xml
Imports System.Xml.Schema
Imports System.IO
Imports System.Windows.Forms
Imports System.Security.Cryptography.Xml
Imports System.Security.Cryptography.X509Certificates

Public Class Form1

Private Resultado As Boolean = True
Public oCertificado As New X509Certificate2
Public vStrXmlRetorno As String
Public vArqERRRetorno As String
Public vPastaXMLErro As String
Public vPastaXMLEnvio As String
Public vArqXMLRetorno As String
Public vPastaXMLRetorno As String
Public vXmlNfeDadosMsg As String
Public vAmbiente As Integer
Public vUF As Integer

Private Sub ValidaNfe(ByVal NfeAler As String)

Try

'Abrir agora o arquivo XML criado e inserir o Protocolo encontrado!!
Dim arquivo2 As String = NfeAler
Dim xDoc As New XmlDocument : xDoc.Load(arquivo2)
Dim Tamanho As String
Dim Nfe As String


Nfe = arquivo2
Tamanho = Replace(Nfe, "C:\", "")
Tamanho = Replace(Tamanho, "F:\SisWin\NFE\BACKUP\200905\", "")
Tamanho = Replace(Tamanho, "F:\SisWin\NFE\BACKUP", "")
Tamanho = Replace(Tamanho, "F:\SisWin\NFE\AENVIAR", "")
Tamanho = Replace(Tamanho, "F:\SisWin\NFE\AENVIAR", "")
Tamanho = Replace(Tamanho, "\", "")
Tamanho = Replace(Tamanho, "\NF-E", "")
Tamanho = Replace(Tamanho, "NF-E", "")
Tamanho = Replace(Tamanho, "SisWin", "")
Tamanho = Replace(Tamanho, "SisWin", "")

'Fazer uma cópia d arquivo XML para gerar a assinatura
Dim CaminhoArquivo As String = "C:\NF-E\XML\" + Tamanho

'Salva o Arquivo
xDoc.Save(CaminhoArquivo)

'Selecionar certificado
SelecionarCertificado()

'Assinar o XML
Dim OAd As New AssinaturaDigitalClass()
Dim pDadosNfe As String
Dim vStringNfe As String
'Dim msgResultado As String


OAd.Assinar(CaminhoArquivo, "infNFe", oCertificado)

If OAd.vResultado = 0 Then 'Assinado corretamente

pDadosNfe = OAd.vXMLStringAssinado
vStringNfe = pDadosNfe.Substring(pDadosNfe.IndexOf("<NFe"), pDadosNfe.Length - pDadosNfe.IndexOf("<NFe"))

Else 'Ocorreu algum erro na assinatura
MessageBox.Show(OAd.vResultadoString, "Erro", MessageBoxButtons.OK, MessageBoxIcon.Error)
End If

'Validar o XML
Dim TxtXSD As String

TxtXSD = "C:\tmp\Schemas NF-e\nfe_v1.10.xsd"

If Not CaminhoArquivo = String.Empty And Not TxtXSD = String.Empty Then

Resultado = True
Dim settings As New XmlReaderSettings()
AddHandler settings.ValidationEventHandler, AddressOf Me.ValidationEventHandler

'Valida o arquivo XML com o seu Schema XSD
lstValida.Items.Add("Validando o arquivo XML " & CaminhoArquivo & " com o arquivo de Schema : " & TxtXSD)

Try

settings.ValidationType = ValidationType.Schema
settings.Schemas.Add("http://www.portalfiscal.inf.br/nfe", XmlReader.Create(TxtXSD))
Using XmlValidatingReader As XmlReader = XmlReader.Create(CaminhoArquivo, settings)
While XmlValidatingReader.Read()

End While

End Using

Catch ex As Exception

lstValida.Items.Add(ex.Message)
Exit Sub
End Try

lstValida.Items.Add("Status Validação -> " & IIf(Resultado = True, "Arquivo validado com SUCESSO", "Validação FALHOU"))

Else
MsgBox("Informe o arquivo XML e o arquivo XSD.")
End If


Catch ex As Exception

'se ocorrer uma exceção exibe a mensagem
lstValida.Items.Add(ex.Message)

End Try

End Sub


Function SelecionarCertificado() As Boolean

Dim vRetorna As Boolean
Dim oX509Cert As New X509Certificate2
Dim store As New X509Store
Dim collection As New X509Certificate2Collection
Dim collection1 As New X509Certificate2Collection
Dim collection2 As New X509Certificate2Collection
Dim scollection As New X509Certificate2Collection
Dim msgResultado As String
Dim xnome As String

xnome = "CN=COPLAST INDUSTRIA E COMERCIO DE RESIDUOS PLASTICO:04672291000115, OU=Autenticado por AR Fenacon, OU=RFB e-CNPJ A1, OU=Secretaria da Receita Federal do Brasil - RFB, L=Manaus, S=AM, O=ICP-Brasil, C=BR"

oX509Cert = New X509Certificate2()
store = New X509Store("MY", StoreLocation.CurrentUser)
store.Open(OpenFlags.ReadOnly Or OpenFlags.OpenExistingOnly)
collection = store.Certificates
collection1 = collection.Find(X509FindType.FindByTimeValid, DateTime.Now, False)
collection2 = collection.Find(X509FindType.FindByKeyUsage, X509KeyUsageFlags.DigitalSignature, False)

'Encontra o certificado digital pelo nome do mesmo, se precisar pergunta por isso
'Resolvido em 13/05/2009 às 15:05h
scollection = collection.Find(X509FindType.FindBySubjectDistinguishedName, xnome, False)


'Para selecionar o certificado de uma lista
'scollection = X509Certificate2UI.SelectFromCollection(collection2, "Certificado(s) Digital(is) disponível(is)", "Selecione o certificado digital para uso no aplicativo", X509SelectionFlag.SingleSelection)

If (scollection.Count = 0) Then

msgResultado = "Nenhum certificado digital foi selecionado ou o certificado selecionado está com problemas."
MessageBox.Show(msgResultado, "Advertência", MessageBoxButtons.OK, MessageBoxIcon.Warning)
vRetorna = False

Else

oX509Cert = scollection.Item(0) 'Para selecionar o item em Vb.NET
oCertificado = oX509Cert
xnome = oCertificado.Subject.ToString
vRetorna = True
'msgResultado = "Certificado Selecionado."
'MessageBox.Show(msgResultado, "Advertência", MessageBoxButtons.OK, MessageBoxIcon.Warning)
Return vRetorna

End If

End Function

Public Sub ValidationEventHandler(ByVal sender As Object, ByVal args As ValidationEventArgs)


Resultado = False

'lstValida.Items.Add(vbTab + "Erro de Validação : " + args.Message)

If args.Severity = XmlSeverityType.Warning Then

MsgBox("Nenhum arquivo de Schema foi encontrado para efetuar a validação...")

ElseIf args.Severity = XmlSeverityType.Error Then

lstValida.Items.Add(args.Message)
'MsgBox("Ocorreu um erro durante a validação....")

End If

If Not (args.Exception Is Nothing) Then ' Erro na validação do schema XSD

'lstValida.Items.Add(args.Exception.SourceUri + "," & args.Exception.LinePosition & "," & args.Exception.LineNumber)
'MsgBox(args.Exception.SourceUri + "," & args.Exception.LinePosition & "," & args.Exception.LineNumber)

End If

End Sub


Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
End
End Sub

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

Dim Valor As String

Me.Show()
'Valor = "F:\SisWin\NFE\BACKUP\200905\13090504672291000115550040000001520000002017-nfe.XML"
'ValidaNfe(Valor)
If Command() <> "" Then
Valor = Command()
ValidaNfe(Valor)

Me.Focus()
Me.Show()
Me.WindowState = FormWindowState.Normal

End If

End Sub

Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
Me.Show()
End Sub
End Class
Public Class AssinaturaDigitalClass

Public vResultado As Integer
Public vResultadoString As String
Public vXMLStringAssinado As String
Public XmlDoc As XmlDocument

Sub Assinar(ByVal pArqXMLAssinar As String, ByVal pUri As String, ByVal pCertificado As X509Certificate2)

'Abrir o arquivo XML a ser assinado e ler o seu conteúdo
Dim SR As StreamReader
Dim vXMLString As String

SR = File.OpenText(pArqXMLAssinar)
vXMLString = SR.ReadToEnd()
SR.Close()

' //Atualizar atributos de retorno com conteúdo padrão
vResultado = 0
vResultadoString = "Assinatura realizada com sucesso"

Try

'Verifica o certificado a ser utilizado na assinatura
Dim _xnome As String
Dim _X509Cert As X509Certificate2
Dim store As X509Store
Dim collection As X509Certificate2Collection
Dim collection1 As X509Certificate2Collection

_xnome = ""

_xnome = pCertificado.Subject.ToString()

_X509Cert = New X509Certificate2()
store = New X509Store("MY", StoreLocation.CurrentUser)
store.Open(OpenFlags.ReadOnly Or OpenFlags.OpenExistingOnly)

collection = store.Certificates
collection1 = collection.Find(X509FindType.FindBySubjectDistinguishedName, _xnome, False)


If (collection1.Count = 0) Then
vResultado = 2
vResultadoString = "Problemas no certificado digital"
Else

' certificado ok
'oX509Cert = scollection.Item(0)

_X509Cert = collection1.Item(0)
Dim x As String
x = _X509Cert.GetKeyAlgorithm().ToString()

' Create a new XML document.
Dim doc As New XmlDocument
doc = New XmlDocument()

'Format the document to ignore white spaces.
doc.PreserveWhitespace = False

' Load the passed XML file using it’s name.
Try
doc.LoadXml(vXMLString)

' Verifica se a tag a ser assinada existe é única
Dim qtdeRefUri As Integer
qtdeRefUri = doc.GetElementsByTagName(pUri).Count

If (qtdeRefUri = 0) Then
' a URI indicada não existe
vResultado = 4
vResultadoString = "A tag de assinatura " + pUri.Trim() + " não existe"

Else
' Existe mais de uma tag a ser assinada
If (qtdeRefUri > 1) Then
' existe mais de uma URI indicada
vResultado = 5
vResultadoString = "A tag de assinatura " + pUri.Trim() + " não é unica"
Else

Try
' Create a SignedXml object.
Dim signedXml As SignedXml
signedXml = New SignedXml(doc)

' Add the key to the SignedXml document
signedXml.SigningKey = _X509Cert.PrivateKey

' Create a reference to be signed
Dim reference As New Reference
reference = New Reference()

'--------- RETIRAR COMENTÁRIOS DAS LINHAS ABAIXO
' pega o uri que deve ser assinada
Dim _Uri As XmlAttributeCollection
Dim _atributo As XmlAttribute

_Uri = doc.GetElementsByTagName(pUri).Item(0).Attributes
For Each _atributo In _Uri
If (_atributo.Name = "Id") Then
reference.Uri = "#" + _atributo.InnerText

End If
Next

' Add an enveloped transformation to the reference.
Dim env As New XmlDsigEnvelopedSignatureTransform
env = New XmlDsigEnvelopedSignatureTransform()
reference.AddTransform(env)

Dim c14 As New XmlDsigC14NTransform
c14 = New XmlDsigC14NTransform()
reference.AddTransform(c14)

' Add the reference to the SignedXml object.
signedXml.AddReference(reference)

' Create a new KeyInfo object
Dim keyinfo As New KeyInfo
keyinfo = New KeyInfo()

' Load the certificate into a KeyInfoX509Data object
' and add it to the KeyInfo object.
keyinfo.AddClause(New KeyInfoX509Data(_X509Cert))

' Add the KeyInfo object to the SignedXml object.
signedXml.KeyInfo = keyinfo
signedXml.ComputeSignature()

' Get the XML representation of the signature and save
' it to an XmlElement object.
Dim xmlDigitalSignature As XmlElement
xmlDigitalSignature = signedXml.GetXml()

' Gravar o elemento no documento XML
doc.DocumentElement.AppendChild(doc.ImportNode(xmlDigitalSignature, True))
XmlDoc = New XmlDocument()
XmlDoc.PreserveWhitespace = False
XmlDoc = doc

' Atualizar a string do XML já assinada
vXMLStringAssinado = XmlDoc.OuterXml

' Gravar o XML no HD
' abre um stream para escrita e cria um StreamWriter para implementar o stream
Dim fs As New FileStream(pArqXMLAssinar, FileMode.OpenOrCreate, FileAccess.Write)
Dim SW_2 As New StreamWriter(fs)
SW_2.Flush()
SW_2.BaseStream.Seek(0, SeekOrigin.Begin)
SW_2.Write(vXMLStringAssinado)
SW_2.Flush()
SW_2.Close()

Catch ex As Exception
vResultado = 6
vResultadoString = "Erro ao assinar o documento - " + ex.Message

End Try

End If

End If

Catch ex As Exception

vResultado = 3
vResultadoString = "XML mal formado - " + ex.Message

End Try

End If

Catch ex As Exception

vResultado = 1
vResultadoString = "Problema ao acessar o certificado digital" + ex.Message

End Try

End Sub

End Class

quarta-feira, 29 de abril de 2009

NF-E: UM CAMINHO PARA O CÓDIGO DE BARRAS EM VB6

Se você está enfrentando dificuldades para gerar o código de barras em Visual Basic 6, pode pensar de um outro modo e usar o próprio VB.NET como caminho para a geração do código de barras 128C da NF-e.
Para isto, basta compilar uma aplicação Windows Form que simplesmente gere o código de barras e utilizar uma chamada call no Visual Basic 6 para esta simples aplicação.
1. Inicie um novo projeto Windows Form Applicattion no VB.Net
2. Chame este projeto de GerBarras
3. Quando os arquivos forem criados, vá ao menu Project -> GerBarras Properties. Clique na opção References na tela que se abre.

A tela será como a que segue abaixo:



Clique no botão Add e indique o caminho do diretório onde se encontra o Barcodelib.dll, conforme a figura.

Usaremos esta dll para fazer a geração do código de barras, recebendo como parâmetro de chamada a numeração que deve ser transformada em código de barras. O aplicativo deverá então gerar uma imagem da numeração do código de barras na pasta C:\NF-e\barras.


Após incluir o barcodelib.dll, clique na pasta Debug e na opção Command Line Arguments digite "parametro", conforme a tela mostrada abaixo:






Agora, nos resta informar o código para geração do código de barras.

4. No modo design do form1, inclua uma objeto Picture. Para isso, clique no menu View e depois em ToolBox. Do lado esquerdo, será aberto a barra de ferramentas. Procure no Common Controls pelo PictureBox. Pressione o mouse sobre ele e arraste-o para o formulário.

Defina as propriedades do PictureBox1 como segue:

Width: 361
Size: 104


5. Em seguida, informe o código abaixo para o form1:

Código na imagem:

Imports System.IO
Imports System.Text
Imports System.Drawing

Imports System.Collections
Imports System.ComponentModel
Imports System.Drawing.Text

Public Class Form1

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim Valor As String

If Command() <> "" Then
Valor = Command()
Dim Barcode As New BarcodeLib.Barcode(Valor, BarcodeLib.TYPE.CODE128C)
PictureBox1.Image = Barcode.Encode(BarcodeLib.TYPE.CODE128C, Valor, 300, 150)
PictureBox1.Visible = True
Barcode.SaveImage("C:\NF-E\Barras\BARRAS.JPG", BarcodeLib.SaveTypes.JPG)

'MsgBox("Gerado com Sucesso")

End
End If
End Sub
End Class


Clique no menu Build na opção Build GerBarras.

A aplicação será gerada. Se não houverem erros, teste o executável gerado:


6. Encontre o diretório Bin\Release dentro dos fontes do projeto GerBarras. O caminho dos fontes no VB.NET sempre fica identificado com o nome do seu projeto. Exemplo:

C:\Vb.NEt Fontes\GeraBarras\GerBarras\GerBarras\bin\Release

Dentro do diretório Release está o GerBarras.exe que você acaba de criar.

7. Copie o GerBarras.exe para o C:\ da sua máquina.

8. Após isso, clique no botão Iniciar do Windows XP Professional (estou supondo que o sistema operacional na sua máquina é o Windows XP. Fiz este exemplo em uma máquina com o Windows XP), e selecione a opção Executar no Menu:

Na caixa Abrir, digite C:\GerBarras.exe 123456895

Pronto!

Um arquivo jpg apresentando o código de barras do número 123456895 será criado na pasta C:\Nfe-e\Barras.

É só ir até lá e conferir.

Você pode mudar o diretório mudando a linha:


Barcode.SaveImage("C:\NF-E\Barras\BARRAS.JPG", BarcodeLib.SaveTypes.JPG)

Para o diretório que achar mais apropriado.

Para chamar este pequeno aplicativo no Visual Basic 6, use o comando Call:

'Código de Barras a ser gerado

CodigoNfe = Right(TxtID, 44)

'Gerar Código de barras

Call Shell("C:\GerBarras.exe " & CodigoNfe)

Abraço a todos!!

sábado, 11 de abril de 2009

NF-E: GERANDO RECIBO DE LOTE EM VB.NET

A seguir é apresentado um pequeno aplicativo gerado em VB.Net 2008 para gerar o pedido de recibo de um lote NF-e enviado a Sefaz. Você deve construir o formulário de acordo com o modelo abaixo apresentado:

Dois Textboxs, três pequenos botões, duas labels e um OpenDialog. A tela gerada deverá ficar como a apresentada abaixo:





Para gerar o código do XML para o pedido de lote, vamos nos aproveitar de um código válido de pedido de lote. Acrescente a seguinte função a seu aplicativo. Ela será chamada quando o botão Pedir Recibo for pressionado, sendo alterada para os dados do arquivo de retorno de lote que você selecionar da pasta retorno:

Function criarDocumentoXML(ByVal Protocolo As String) As XDocument
'Usa o código de um recibo existente como base para a geração
'de um novo arquivo xml de pedido de lote

Return
< ?xml version="1.0" encoding="UTF-8"?>
<consReciNFe xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance
xmlns:xsd="http://www.w3.org/2001/XMLSchema" versao="1.10" xmlns="http://www.portalfiscal.inf.br/nfe">
<tpamb>2</tpamb>
<nrec>130000000177443</nrec>
</consReciNFe>


Return

End Function






Na cláusula general do formulário acrescente essas duas classes:


Imports System.Xml
Imports System.Xml.Linq




No OpenDialog altere as seguintes propriedades:


Filename: *.xml
InitialDirectory: C:\NF-E\Retorno



Dentro do botão com as reticências (...) acrescente o código de chamada do OpenDialog:



Private Sub Button6_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button6.Click

OpenFileDialog1.ShowDialog()
TxtArquivo.Text = OpenFileDialog1.FileName

End Sub




Esse simples código fará a abertura do diretório C:\NF-e\Retorno. Dentro dele, você deverá clicar em um arquivo num-lot de retorno válido. No exemplo da figura foi selecionado o arquivo 13090404672291000115550040000000270000000730-num-lot.xml.



Já deu para perceber o que estamos fazendo?


Vamos selecionar um arquivo num-lot de retorno da NF-e e usar o layout de um arquivo de pedido de lote pré-existente para gerar um novo arquivo de pedido de lote para o arquivo num-lot que selecionarmos.


Para fazer isso, fornecemos o arquivo num-lot. Mas também precisaremos do arquivo de recibo para pegar o número do Protocolo. Usaremos o arquivo num-lot selecionado para pegar o número do recibo constante dentro do mesmo e abrir o arquivo de recibo em sequência dentro do botão Gerar Lote.

O código para o botão Gerar Recibo é apresentado abaixo:



Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
Dim NomeArquivoRecibo As String
Dim Protocolo As String
Dim Status As String
Dim ArquivoLote As String
'Dim CodigoErro As String
Dim Texto As String
' Dim NomeNfe As String
' Dim Tamanho As Integer
Dim Zeros As String

If TxtArquivo.Text = "" Then
MsgBox("Arquivo XML nÆo selecinado!!")
Exit Sub
TxtArquivo.Focus()
End If
Zeros = ""
ArquivoLote = TxtArquivo.Text
Status = ""
Protocolo = ""


'Abrir o arquivo de Status de Retorno
Dim xml As XElement = XElement.Load(ArquivoLote)
Dim elements As IEnumerable(Of XElement) = Xml.Elements()
Texto = xml.Element("NumeroLoteGerado").Value
If Len(Texto) = 1 Then Zeros = "00000000000000"
If Len(Texto) = 2 Then Zeros = "0000000000000"
If Len(Texto) = 3 Then Zeros = "000000000000"
If Len(Texto) = 4 Then Zeros = "00000000000"
NomeArquivoRecibo = "C:\NF-E\Retorno\" + Zeros + Texto + "-rec.xml"

'Abrir arquivo de recibo com os dados do arquivo de lote selecionado
'Dim testeXML As XElement = XElement.Load(NomeArquivoRecibo)
Dim reader As XmlTextReader = New XmlTextReader(NomeArquivoRecibo)
Do While (reader.Read())

Select reader.NodeType
Case XmlNodeType.Element
If reader.Name = "cStat" Then
Status = reader.ReadString
End If
'Obter o n£mero do protocolo
If reader.Name = "nRec" Then
Protocolo = reader.ReadString
End If

End Select
Loop
'Console.ReadLine()
reader.Close()
NomeProtocolo = Protocolo
If (Status <> "103") And (Protocolo = "") Then
MsgBox("Problemas com a Nf-e. Erro de Status: " + Status)
End If

'Gerando o novo arquivo de pedido de recibo
Dim arquivo As String = "C:\NF-E\Envio\" + Protocolo + "-ped-rec.xml"
Dim doc = criarDocumentoXML(Protocolo)
'Salvar o XML gerado
doc.Save(arquivo)


'Abrir agora o arquivo XML criado e inserir o Protocolo encontrado!!
Dim arquivo2 As String = "C:\NF-E\envio\" + Protocolo + "-ped-rec.xml"
Dim xDoc As New XmlDocument : xDoc.Load(arquivo)
'Declara um objeto Lista de Nodes
Dim nodeList As Xml.XmlNodeList
'Obtem todos os nodes para a lista com o nome desejado
nodeList = xDoc.GetElementsByTagName("nRec")
'Faz um la‡o para ler os nodes e alterar o seu conte£do.
For i As Integer = (nodeList.Count - 1) To 0 Step -1
nodeList.Item(i).InnerText = Protocolo
Next
'Salva o Arquivo
xDoc.Save(arquivo2)
LstValida.Text = arquivo2
MsgBox("Arquivo XML gerado com sucesso.")
'Timer1.Enabled = True
'carregaXML()

End Sub




O botão Close irá fechar o formulário chamado. Estou chamando este formulário de um outro:


Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click

'Fecha o formulário aberto. Altere para o comando END se for necessário sair do aplicativo
Me.Close()


End Sub




Com isso, apresentamos um modo rápido de gerar um pedido de recibo de um arquivo de lote.

Abraços a todos!!

quarta-feira, 8 de abril de 2009

VB.NET: DANFE EM CRYSTAL E CÓDIGO DE BARRAS 128C

A Danfe pode ser gerada em Crystal 8.5 e depois migrada para dentro do Vb.NET ou,
se você preferir, totalmente criada dentro do VB.NET 2008 com a ferramenta Crystal
ali contida - muito mais poderosa e fácil de trabalhar.

Usar a DANFE em VB.NET 2008 possibilita utilizar um DATASET para gerar a leitura do arquivo XML da NF-e.

Usando o VB.NET 2008

É preciso acrescentar ao form o uso das bibliotecas necessárias:

Imports System.Xml
Imports System.IO
Imports System.Text

Imports System.Drawing
Imports System.Collections
Imports System.ComponentModel
Imports System.Drawing.Text

Cada uma delas será necessária para o projeto em si

Isso se fará necessário quando o fornecedor da empresa enviar em vez da DANFE em pdf o arquivo XML propriamente dito. Muitas empresas além da DANFE impressa que acompanha a mercadoria podem disponibilizar o arquivo XML via e-mail da nf-e emitida.

LANÇANDO OS DADOS DO XML EM UM DATASET


Crie o DATASET normalmente e defina os campos do modo apropriada para receber os
dados do arquivo XML

No botão de impressão, você poderá definir os dados do seguinte modo:

Dim myDs1 As New DsXML1()
Dim myRow2 As DsXML1.DtDsXML1Row
Dim reader As XmlTextReader = New XmlTextReader(TxtArquivo.Text)

'DsXML1 é o nome do DATASET com o campos da XML

'abrindo o DATASET
myRow2 = myDs1.DtDsXML1.NewDtDsXML1Row

'Lendo o XML
Do While (reader.Read())

'Fazendo a seleção dos campos
Select Case reader.NodeType
Case XmlNodeType.Element 'Exibir o início do elemento.

If reader.HasAttributes Then 'Se existirem atributos
While reader.MoveToNextAttribute()

If reader.Name = "Id" Then
myRow2.IdChave = Mid(reader.Value, 4)
myRow2.Id = ValorTexto
endif

If reader.Name = "emit" Then
SelecionarEmitente = True
SelecionarDestinatario = False
End If

'----------------------------------------------------------
'Dados do EMITENTE
If SelecionarEmitente = True Then
If reader.Name = "CNPJ" Then
myRow2.EmitCNPJ = reader.ReadString
End If
If reader.Name = "IE" Then
myRow2.EmitIE = reader.ReadString
End If
If reader.Name = "xNome" Then
myRow2.EmitxNome = reader.ReadString
End If
If reader.Name = "xLgr" Then
myRow2.EmitxLgr = reader.ReadString
End If
If reader.Name = "xMun" Then
myRow2.EmitxMun = reader.ReadString
End If
If reader.Name = "UF" Then
myRow2.EmitUF = reader.ReadString
End If
If reader.Name = "CEP" Then
myRow2.EmitCEP = reader.ReadString
End If
End If

...
...

End Select
Loop

'Fecha o XML
reader.Close()
myDs1.DtDsXML1.AddDtDsXML1Row(myRow2)

'Imprimindo a DANFE
Dim caminho_imagem As String
caminho_imagem = "C:\NF-E\Barras\BARRAS.JPG"

Dim myRelatorio As New rptIAM()
myRelatorio.SetDataSource(myDs1)

myRelatorio.ParameterFields(0).AllowCustomValues = True
myRelatorio.ParameterFields(0).CurrentValues.AddValue(caminho_imagem)

'myRelatorio.SetParameterValue(0, caminho_imagem)
Me.CrvXml.ReportSource = myRelatorio

Me.CrvXml.Visible = True
TxtArquivo.Text = ""


Seguinte estes passos, você poderá imprimir a DANFE totalmente jogando os dados para um DATASET e associando este DATASET ao relatório em Crystal.


CÓDIGO DE BARRAS 128C para a NF-e

O BarcodeLib pode ser encontrado nas páginas do CodeProject (http://www.codeproject.com/KB/graphics/BarcodeLibrary.aspx), que se trata de uma área de projetos em várias linguagens da plataforma Vb.Net. O dll gerado pelo projeto
mostrado permite gerar o código de barras 128C no formato desejado pela NF-e.

Para integrar a dll no seu Projeto em Vb.Net você simplesmente precisa acessar em
seu projeto o menu Project - Properties e clicar em ADD, apontando para a pasta onde se encontra o barcodelib.dll.

Após acrescentar a DLL, acrescente a mesma à sua lista de bibliotecas no
início do form:

Imports BarcodeLib



Para gerar o código de barras do código da NF-e, basta usar o seguinte código:

Dim Barcode As New BarcodeLib.Barcode(ValorTexto, BarcodeLib.TYPE.CODE128C)
PictureBox2.Image = Barcode.Encode(BarcodeLib.TYPE.CODE128C, ValorTexto, 300, 150)
Barcode.SaveImage("C:\NF-E\Barras\BARRAS.JPG", BarcodeLib.SaveTypes.JPG)

Dim fs As New FileStream("C:\NF-E\Barras\BARRAS.JPG", FileMode.Open)
Dim br As New BinaryReader(fs)
myRow2.Imagem = br.ReadBytes(br.BaseStream.Length)

br.Close()
fs.Close()

br = Nothing
fs = Nothing

'myRow2 é um DATASET no qual está sendo jogado os dados da XML. Defina o
'campo que receberá o código de barras como sendo do tipo byte. No caso,
'o campo no dataset se chama Imagem

Após lançar a imagem dentro do campo imagem, basta arrasta este campo para a
área onde o código deverá ser impresso que a imagem será apresentada na visualização
do relatório


Arquivos disponíveis:

DANFE em Vb.NEt 2008
http://www.4shared.com/file/97470303/39ecd635/Danfe_VBNet.html


Danfe em Crystal 8.5
http://www.4shared.com/file/97468171/63f3f4ef/Danfe_Layout.html


BarcodeLib
http://www.4shared.com/file/97468816/a41cfd45/BarcodeLib.html

segunda-feira, 6 de abril de 2009

A BÍBLIA DO XML

Essa aqui é para aqueles que precisam realmente de ajuda!!

Eis o link da Bíblia do XML no 4shared:

http://www.4shared.com/file/10594264/1d5c518f/XML_Programming_Bible.html


A única ressalva: está em inglês!!!

NF-E - XML PARA O VISUAL BASIC

As funções abaixo ajudam na leitura de um arquivo XML da NF-e.

Você só precisa fazer a leitura das tags corretas e lançá-las na
base de dados - que pode ser em Access, SQL ou MySQL.

Para que funcione a contento, você precisa setar em References as
devidas bibliotecas associadas a MSXLM DOM.


As funções foram extraídas da internet.


'LENDO O XML
Private Sub LoadSettings()
Dim objNode As XMLNode
Dim objSubNode As XMLNode

'Does the Settings.xml file exist?
If PathExists("C:\NF-E\13090404672291000115550040000000280000000745-nfe.xml") Then
'Parse XML file and get top level node
Set objNode = XMLParse("C:\NF-E\13090404672291000115550040000000280000000745-nfe.xml", XML_FILE).Item("NFe")

Dim oRs As New ADODB.Recordset
Dim oRx As New ADODB.Recordset
Dim sSQL2 As String

'SE NÃO EXISTIR O MUNICÍPIO, INSERE OS DADOS DO MESMO
sSQL2 = "INSERT INTO XML(NFE, CUF, CNF) VALUES ( '" & _
Right(ID, 44) & "', '" & UF & "', '" & cNF & "')"


Cn.Execute sSQL2

MsgBox "LENDO OS DADOS COM SUCESSO!!", vbInformation, "XML"



End If
End Sub

Public Function Parse() As VBA.Collection
Dim strData As String
Dim i As Byte

'Get the XML data
If Flags And XML_FILE Then
'It is on disk so read it
strData = ReadFile(Data)
Else
'Otherwise just make a copy into our local
'variable (modifications are made)
strData = Data
End If

'Remove comments / id tags
StripTags strData, ""
StripTags strData, ""

'Remove the null characters
strData = Replace(strData, vbNullChar, vbNullString)

'Create a new collection
Set Parse = New Collection

'Are we supposed to overwrite data?
If Flags And XML_OVERWRITE Then
Set Nodes = Parse
End If

'Begin parsing!
ParseRec strData, Parse

End Function

Private Sub ParseRec(ByRef strData As String, ByVal colNodes As VBA.Collection)
'------------------------------------------------------------------
'Purpose: Recursive function which goes through all the data
' given to parse for XML until there is none left
'
'Params:
' strData: Data to parse
' colNodes: Current level collection of nodes
'------------------------------------------------------------------

Dim i As Long
Dim k As Long
Dim strValue As String
Dim strName As String
Dim objNode As XMLNode

'Find first <
i = InStrB(1, strData, "<")

'Keep looping while there are <
Do While i
'Alright there is a node; create a new one
Set objNode = New XMLNode

'Find end of first tag
k = InStrB(i, strData, ">")

'If there is no >, then we've got bad XML
If k = 0 Then
Exit Do
End If

'Extract data inbetween <>
strName = MidB$(strData, i + 2, k - i - 2)

'Check for a space in the name
i = InStrB(1, strName, " ")

'If there is a space, there may be attributes,
'otherwise no
If i Then
'Extract name of node
objNode.Name = LeftB$(strName, i - 1)

'Parse attributes if any
ParseAttr MidB$(strName, i + 2), objNode.Attributes

'If the name ends in a /, then there is no end tag
'otherwise there is
If AscW(RightB$(strName, 2)) = CHR_FSLASH Then
i = 0
Else
i = 1
End If
Else
'If the name ends in a /, then there is no end tag
'otherwise there is
If AscW(RightB$(strName, 2)) = CHR_FSLASH Then
'Trim off / from name
objNode.Name = LeftB$(strName, LenB(strName) - 2)
i = 0
Else
objNode.Name = strName
i = 1
End If
End If

'If i is non-zero, then we have to find the end tag
If i Then
'Find end tag position
i = InStrB(k, strData, "")

'Did we find it?
If i Then
'Extract value
strValue = MidB$(strData, k + 2, i - k - 2)

'Parse any nodes which might be inside
ParseRec strValue, objNode.Nodes

'Unescape escape sequences
objNode.Value = XMLUnescape(strValue)

If objNode.Name = "cUF" Then
UF = objNode.Value
End If
If objNode.Name = "cNF" Then
cNF = objNode.Value
End If
'Should equal position of last character for this node
k = i + LenB(objNode.Name) + 4
Else
'Malformed XML; quit
Exit Do
End If
End If

'Remove parsed data from string
strData = MidB$(strData, k + 2)

'Index node in collection
On Error Resume Next
colNodes.Add objNode, objNode.Name

'If an error occured, then we should add it to
'the collection without indexing it (it's already taken)
If Err.Number Then
colNodes.Add objNode

'Clear error
Err.Clear
End If

'Find next <
i = InStrB(1, strData, "<")
Loop

End Sub

Private Sub ParseAttr(ByRef strAttr As String, ByVal colAttr As VBA.Collection)
'------------------------------------------------------------------
'Purpose: To parse an attribute list for an XML tag and to place
' them inside the collection
'
'Params:
' strAttr: List of attributes/values seperated by
' spaces
' colAttr: Collection to add XMLAttr objects to
'------------------------------------------------------------------

Dim c As Integer
Dim i As Long
Dim objAttr As XMLAttr

'Find first equal's sign
i = InStrB(1, strAttr, "=")

'Loop as long as there are attributes
Do While i
'Create new attribute
Set objAttr = New XMLAttr

'Extract name (may have leading space(s))
objAttr.Name = LTrim$(LeftB$(strAttr, i - 1))

'Skip ahead to value
strAttr = MidB$(strAttr, i + 2)

'Get first character
c = AscW(strAttr)

'How is the attributed formated; surrounding quotes or no?
Select Case c
Case CHR_SQUOTE, CHR_DQUOTE
'Find ending quote
i = InStrB(3, strAttr, ChrW$(c))

'Did we find it?
If i Then
'Extract value and skip past this attribute
objAttr.Value = XMLUnescape(MidB$(strAttr, 3, i - 3))
strAttr = MidB$(strAttr, i + 2)
Else
'Bad XML!
Exit Do
End If
Case Else
'A space then will herald then end
i = InStrB(1, strAttr, " ")

'Did we find one?
If i Then
'Extract value and then skip past current attribute data
objAttr.Value = XMLUnescape(LeftB$(strAttr, i - 1))
strAttr = MidB$(strAttr, i + 2)
Else
'It is the last attribute; copy remaining data and
'exit loop
objAttr.Value = XMLUnescape(strAttr)
Exit Do
End If
End Select

If objAttr.Name = "Id" Then
ID = objAttr.Value
End If

If objAttr.Name = "UF" Then
UF = objAttr.Value
End If


'Add to collection
colAttr.Add objAttr, objAttr.Name

'Find next attribute
i = InStrB(1, strAttr, "=")
Loop

End Sub

Public Function XMLUnescape(ByRef strData As String) As String
'------------------------------------------------------------------
'Purpose: Converts escape sequences for XML into the actual
' characters
'
'Params:
' strData: String to search for escaped characters in
'
'Returns: String with escaped characters converted back to actual
' representation
'------------------------------------------------------------------

Dim i As Long

XMLUnescape = strData

If LenB(XMLUnescape) Then
i = InStrB(1, XMLUnescape, "&")

'If there is a & in the string, that is where we should start searching
If i Then
'Make sure there is a semi colon, telling us there may be escape sequences
If InStrB(i, XMLUnescape, ";") Then
'Escape various illegal characters
If InStrB(i, XMLUnescape, "<") Then XMLUnescape = Replace(XMLUnescape, "<", "<")
If InStrB(i, XMLUnescape, ">") Then XMLUnescape = Replace(XMLUnescape, ">", ">")
If InStrB(i, XMLUnescape, """) Then XMLUnescape = Replace(XMLUnescape, """, """")
If InStrB(i, XMLUnescape, "'") Then XMLUnescape = Replace(XMLUnescape, "'", "'")
If InStrB(i, XMLUnescape, "&") Then XMLUnescape = Replace(XMLUnescape, "&", "&")
End If
End If
End If

End Function

Public Function XMLParse(ByRef strData As String, ByVal lngFlags As Long) As VBA.Collection
'------------------------------------------------------------------
'Purpose: Wrapper method to quickly parse an XML document
'
'Params:
' strData: Data property of XMLDoc
' lngFlags: Flags property of XMLDoc
'
'Returns: Reference to top-level nodes collection
'------------------------------------------------------------------

Dim objXML As XMLDoc

'Create new XML object
Set objXML = New XMLDoc

'Copy data/flags params
objXML.Data = strData
objXML.Flags = lngFlags

'Parse / return collection
Set XMLParse = objXML.Parse()

'Destroy XMLDoc reference
Set objXML = Nothing

End Function

UM APLICATIVO PARA LEITURA DEVOCIONAL ANUAL DA BIBLIA EM ANDROID

Olá, pessoal!  Este novo projeto foi criado em Visual Studio 2019 em C#.Net com o Xamarin. Já está disponível no Google Play para vocês baix...