No artigo de hoje, vamos demonstrar uma função, onde é possível exportar o resultado de uma query para um arquivo txt.
No passado, já haviamos feito isso para Excel ( nesse link – https://terminaldeinformacao.com/2017/10/03/funcao-gera-arquivo-excel-atraves-de-uma-query-sql/ ). A ideia, seria ao informar uma query, a customização montar sozinha já um arquivo TXT com o resultado.
A lógica então da rotina é a seguinte:
- É recebido em um parâmetro a query que será executada
- Essa query vai ser executada com PLSQuery
- Nisso através do DbStruct, vai ser avaliado quais são as colunas e os tamanhos delas, para definir a estrutura do TXT
- Será então feito um laço de repetição nos dados, e adicionado nesse arquivo texto
- Por fim, será aberto o arquivo TXT
O nome da customização é zQry2Txt, abaixo uma forma de acionar ela, buscando informações do cadastro de produtos:
u_zQry2Txt("SELECT B1_COD, B1_DESC FROM SB1990 SB1 WHERE B1_FILIAL = '' AND D_E_L_E_T_ = ' '", .T.)
Abaixo um print do resultado:
E abaixo o código fonte da zQry2Txt:
//Bibliotecas
#Include "TOTVS.ch"
#Include "TopConn.ch"
/*/{Protheus.doc} User Function zQry2Txt
Executa uma query e gera num arquivo TXT
@type Function
@author Atilio
@since 20/12/2023
@example u_zQry2Txt("SELECT TOP 10 B1_COD, B1_DESC FROM " + RetSQLName("SB1"), .T.)
/*/
User Function zQry2Txt(cQryAux, lAbreArq)
Local aArea := FWGetArea()
Default lAbreArq := .F.
Private oProcess
Private lSemTela := IsBlind()
Private cNomeArq := ""
Private lVaiAbrir := lAbreArq
//Somente se veio query
If ! Empty(cQryAux)
//Aciona o processamento
If lSemTela
fProcessa(cQryAux)
Else
oProcess := MsNewProcess():New({|| fProcessa(cQryAux) }, "Processando...", "Aguarde...", .T.)
oProcess:Activate()
EndIf
EndIf
FWRestArea(aArea)
Return cNomeArq
Static Function fProcessa(cQryAux)
Local aArea := GetArea()
Local oFWriter
Local cPasta := Iif(lSemTela, "\x_temp\", GetTempPath() + "files\")
Local cArquivo := "zqry2txt_" + dToS(Date()) + "_" + StrTran(Time(), ":", "-") + ".txt"
Local nColuna := 0
//Executa a query
PLSQuery(cQryAux, "QRY_AUX")
If ! QRY_AUX->(EoF())
//Se a pasta não existir, cria
If ! ExistDir(cPasta)
MakeDir(cPasta)
EndIf
//Pega os campos
aEstrut := QRY_AUX->(DbStruct())
//Cria o arquivo
oFWriter := FWFileWriter():New(cPasta + cArquivo, .T.)
//Se houve falha ao criar, mostra a mensagem
If ! oFWriter:Create()
FWAlertError("Falha o criar o arquivo " + cPasta + cArquivo)
Else
//Linha 1 que é o cabeçalho das colunas
cLinha := ""
For nColuna := 1 To Len(aEstrut)
cCampo := aEstrut[nColuna][1]
cTipo := aEstrut[nColuna][2]
nTamanho := aEstrut[nColuna][3]
//Se for Data, aumenta de 8 para 10 (DD/MM/YYYY)
If cTipo == "D"
nTamanho := 10
EndIf
//Se tiver underline, busca o nome do campo direto na SX3
If "_" $ cCampo
cTitulo := RetTitle(cCampo)
If ! Empty(cTitulo)
cCampo := cTitulo
EndIf
EndIf
//Se o tamanho for menor que 10, define um tamanho minimo
If nTamanho < 10
nTamanho := 10
EndIf
cLinha += PadR(Capital(cCampo), nTamanho) + "|"
Next
cLinha += CRLF
oFWriter:Write(cLinha)
//Linha 2 que é de separação
cLinha := ""
For nColuna := 1 To Len(aEstrut)
cCampo := aEstrut[nColuna][1]
cTipo := aEstrut[nColuna][2]
nTamanho := aEstrut[nColuna][3]
//Se o tamanho for menor que 10, define um tamanho minimo
If nTamanho < 10
nTamanho := 10
EndIf
cLinha += Replicate("-", nTamanho) + "*"
Next
cLinha += CRLF
oFWriter:Write(cLinha)
//Definindo o total da barra
DbSelectArea("QRY_AUX")
QRY_AUX->(DbGoTop())
Count To nTotal
u_zProcRegua(oProcess, nTotal, 5)
nAtual := 0
//Agora da linha 3 em diante busca os dados da query
QRY_AUX->(DbGoTop())
While !QRY_AUX->(EoF())
nAtual++
u_zIncProc(oProcess, "Processando registro...")
//Monta a linha
cLinha := ""
For nColuna := 1 To Len(aEstrut)
cCampo := aEstrut[nColuna][1]
cTipo := aEstrut[nColuna][2]
nTamanho := aEstrut[nColuna][3]
//Se o tamanho for menor que 10, define um tamanho minimo
If nTamanho < 10
nTamanho := 10
EndIf
//Formata o campo
xConteudo := &("QRY_AUX->" + cCampo)
If cTipo $ "N;L;"
xConteudo := PadR(cValToChar(xConteudo), nTamanho)
ElseIf cTipo == "D"
xConteudo := dToC(xConteudo)
Else
xConteudo := PadR(xConteudo, nTamanho)
EndIf
cLinha += xConteudo + "|"
Next
cLinha += CRLF
oFWriter:Write(cLinha)
QRY_AUX->(DbSkip())
EndDo
EndIf
oFWriter:Close()
cNomeArq := cPasta + cArquivo
//Abre o arquivo
If ! lSemTela .And. File(cPasta + cArquivo) .And. lVaiAbrir
ShellExecute("OPEN", cArquivo, "", cPasta, 1)
EndIf
EndIf
QRY_AUX->(DbCloseArea())
RestArea(aArea)
Return
Bom pessoal, por hoje é só.
Abraços e até a próxima.
