Função para gerar DANFE e XML de uma nota em uma pasta via AdvPL

Você já precisou gerar o PDF e o XML de uma nota em uma pasta qualquer?

Basicamente, nessa função desenvolvida, você passa por parâmetro o número da nota, a série e a pasta em que quer os arquivos gerados. A partir disso, é chamado a função zSpedXML (Função que retorna o xml de uma nota em AdvPL). Depois disso, é acessado o RDMake da DANFEII e gerado o pdf da danfe.

Abaixo o código fonte desenvolvido:

//Bibliotecas
#Include "Protheus.ch"
#Include "TBIConn.ch" 
#Include "Colors.ch"
#Include "RPTDef.ch"
#Include "FWPrintSetup.ch"

/*/{Protheus.doc} zGerDanfe
Função que gera a danfe e o xml de uma nota em uma pasta passada por parâmetro
@author Atilio
@since 10/02/2019
@version 1.0
@param cNota, characters, Nota que será buscada
@param cSerie, characters, Série da Nota
@param cPasta, characters, Pasta que terá o XML e o PDF salvos
@type function
@example u_zGerDanfe("000123ABC", "1", "C:\TOTVS\NF")
@obs Para o correto funcionamento dessa rotina, é necessário:
	1. Ter baixado e compilado o rdmake danfeii.prw
	2. Ter baixado e compilado o zSpedXML.prw - https://terminaldeinformacao.com/2017/12/05/funcao-retorna-xml-de-uma-nota-em-advpl/
/*/
User Function zGerDanfe(cNota, cSerie, cPasta)
	Local aArea     := GetArea()
	Local cIdent    := ""
	Local cArquivo  := ""
	Local oDanfe    := Nil
	Local lEnd      := .F.
	Local nTamNota  := TamSX3('F2_DOC')[1]
	Local nTamSerie := TamSX3('F2_SERIE')[1]
	Private PixelX
	Private PixelY
	Private nConsNeg
	Private nConsTex
	Private oRetNF
	Private nColAux
	Default cNota   := ""
	Default cSerie  := ""
	Default cPasta  := GetTempPath()
	
	//Se existir nota
	If ! Empty(cNota)
		//Pega o IDENT da empresa
		cIdent := RetIdEnti()
		
		//Se o último caracter da pasta não for barra, será barra para integridade
		If SubStr(cPasta, Len(cPasta), 1) != "\"
			cPasta += "\"
		EndIf
		
		//Gera o XML da Nota
		cArquivo := cNota + "_" + dToS(Date()) + "_" + StrTran(Time(), ":", "-")
		u_zSpedXML(cNota, cSerie, cPasta + cArquivo  + ".xml", .F.)
		
		//Define as perguntas da DANFE
		Pergunte("NFSIGW",.F.)
		MV_PAR01 := PadR(cNota,  nTamNota)     //Nota Inicial
		MV_PAR02 := PadR(cNota,  nTamNota)     //Nota Final
		MV_PAR03 := PadR(cSerie, nTamSerie)    //Série da Nota
		MV_PAR04 := 2                          //NF de Saida
		MV_PAR05 := 1                          //Frente e Verso = Sim
		MV_PAR06 := 2                          //DANFE simplificado = Nao
		
		//Cria a Danfe
		oDanfe := FWMSPrinter():New(cArquivo, IMP_PDF, .F., , .T.)
		
		//Propriedades da DANFE
		oDanfe:SetResolution(78)
		oDanfe:SetPortrait()
		oDanfe:SetPaperSize(DMPAPER_A4)
		oDanfe:SetMargin(60, 60, 60, 60)
		
		//Força a impressão em PDF
		oDanfe:nDevice  := 6
		oDanfe:cPathPDF := cPasta				
		oDanfe:lServer  := .F.
		oDanfe:lViewPDF := .F.
		
		//Variáveis obrigatórias da DANFE (pode colocar outras abaixo)
		PixelX    := oDanfe:nLogPixelX()
		PixelY    := oDanfe:nLogPixelY()
		nConsNeg  := 0.4
		nConsTex  := 0.5
		oRetNF    := Nil
		nColAux   := 0
		
		//Chamando a impressão da danfe no RDMAKE
		RptStatus({|lEnd| StaticCall(DANFEII, DanfeProc, @oDanfe, @lEnd, cIdent, , , .F.)}, "Imprimindo Danfe...")
		oDanfe:Print()
	EndIf
	
	RestArea(aArea)
Return
Esses e outros códigos, estão disponíveis gratuitamente no nosso GitHub, acesse em github.com/dan-atilio/AdvPL.

Caso precise gerar várias notas, basta fazer um while ou for com os dados e chamar a função zGerDanfe, abaixo um exemplo com for:

Local nAtual := 0
Local aNotas := {}

//            Nota        Série Pasta
aAdd(aNotas, {"000000001", "1", "C:\TOTVS\NF"})
aAdd(aNotas, {"000000002", "1", "C:\TOTVS\NF"})
aAdd(aNotas, {"000000003", "1", "C:\TOTVS\NF"})
aAdd(aNotas, {"000000004", "1", "C:\TOTVS\NF"})
aAdd(aNotas, {"000000005", "1", "C:\TOTVS\NF"})
aAdd(aNotas, {"000000006", "1", "C:\TOTVS\NF"})
aAdd(aNotas, {"000000007", "1", "C:\TOTVS\NF"})
aAdd(aNotas, {"000000008", "1", "C:\TOTVS\NF"})

For nAtual := 1 To Len(aNotas)
	u_zGerDanfe(aNotas[nAtual][01], aNotas[nAtual][02], aNotas[nAtual][03])
Next

Abaixo um Exemplo com While:

//Monta a consulta e executa
cQuery := " SELECT F2_DOC, F2_SERIE ...."
TCQuery cQuery New Alias "QRY"

//enquanto houver dados
While ! QRY->(EoF())

    //chama a rotina
    u_zGerDanfe(QRY->F2_DOC, QRY->F2_SERIE, "C:\TOTVS\NF")

    //pula registro
    QRY->(DbSkip())
EndDo

Bom pessoal, por hoje é só.

Abraços e até a próxima.

Dan_Atilio
Analista e desenvolvedor de sistemas. Técnico em Informática pelo CTI da Unesp. Graduado em Banco de Dados pela Fatec Bauru. Entusiasta de soluções Open Source e blogueiro nas horas vagas.

1 Response

  1. Fabrício Antunes disse:

    Boa tarde teria como ao invés de passar o número da chave fazer uma pesquisa por data de emissão e baixar várias notas de uma vez?

Deixe uma resposta