Exemplos de geração de arquivo para o Excel via AdvPL

Olá pessoal…

Hoje vou mostrar exemplos de como gerar arquivos para o Excel, utilizando o AdvPL e as classes FWMsExcel e FWMSExcelEx.


Existem duas classes para geração de arquivos xml do Excel, a FWMsExcel e a FWMsExcelEx, a segunda tem mais opções de edição de atributos de uma célula.

Abaixo irei mostrar 4 exemplos:
– Exemplo simples de FWMsExcel
– Exemplo simples de FWMsExcelEx
– Exemplo de FWMsExcel com cores e fonte diferente
– Exemplo de FWMsExcel com colunas dinâmicas (Produtos por dias de venda)

Exemplo simples de FWMsExcel:

Exemplo simples de FWMsExcel

Exemplo simples de FWMsExcel

Abaixo o código fonte utilizado:

//Bibliotecas
#Include "Protheus.ch"
#Include "TopConn.ch"

//Constantes
#Define STR_PULA	Chr(13)+Chr(10)

/*/{Protheus.doc} zTstExc1
Função que cria um exemplo de FWMsExcel
@author Atilio
@since 06/08/2016
@version 1.0
	@example
	u_zTstExc1()
/*/

User Function zTstExc1()
	Local aArea		:= GetArea()
	Local cQuery		:= ""
	Local oFWMsExcel
	Local oExcel
	Local cArquivo	:= GetTempPath()+'zTstExc1.xml'

	//Pegando os dados
	cQuery := " SELECT "													+ STR_PULA
	cQuery += " 	SB1.B1_COD, "											+ STR_PULA
	cQuery += " 	SB1.B1_DESC, "										+ STR_PULA
	cQuery += " 	SB1.B1_TIPO, "										+ STR_PULA
	cQuery += " 	SBM.BM_GRUPO, "										+ STR_PULA
	cQuery += " 	SBM.BM_DESC, "										+ STR_PULA
	cQuery += " 	SBM.BM_PROORI "										+ STR_PULA
	cQuery += " FROM "													+ STR_PULA
	cQuery += " 	"+RetSQLName('SB1')+" SB1 "							+ STR_PULA
	cQuery += " 	INNER JOIN "+RetSQLName('SBM')+" SBM ON ( "		+ STR_PULA
	cQuery += " 		SBM.BM_FILIAL = '"+FWxFilial('SBM')+"' "		+ STR_PULA
	cQuery += " 		AND SBM.BM_GRUPO = B1_GRUPO "					+ STR_PULA
	cQuery += " 		AND SBM.D_E_L_E_T_='' "							+ STR_PULA
	cQuery += " 	) "														+ STR_PULA
	cQuery += " WHERE "													+ STR_PULA
	cQuery += " 	SB1.B1_FILIAL = '"+FWxFilial('SBM')+"' "			+ STR_PULA
	cQuery += " 	AND SB1.D_E_L_E_T_ = '' "							+ STR_PULA
	cQuery += " ORDER BY "												+ STR_PULA
	cQuery += " 	SB1.B1_COD "											+ STR_PULA
	TCQuery cQuery New Alias "QRYPRO"
	
	//Criando o objeto que irá gerar o conteúdo do Excel
	oFWMsExcel := FWMSExcel():New()
	
	//Aba 01 - Teste
	oFWMsExcel:AddworkSheet("Aba 1 Teste") //Não utilizar número junto com sinal de menos. Ex.: 1-
		//Criando a Tabela
		oFWMsExcel:AddTable("Aba 1 Teste","Titulo Tabela")
		//Criando Colunas
		oFWMsExcel:AddColumn("Aba 1 Teste","Titulo Tabela","Col1",1,1) //1 = Modo Texto
		oFWMsExcel:AddColumn("Aba 1 Teste","Titulo Tabela","Col2",2,2) //2 = Valor sem R$
		oFWMsExcel:AddColumn("Aba 1 Teste","Titulo Tabela","Col3",3,3) //3 = Valor com R$
		oFWMsExcel:AddColumn("Aba 1 Teste","Titulo Tabela","Col4",1,1)
		//Criando as Linhas
		oFWMsExcel:AddRow("Aba 1 Teste","Titulo Tabela",{11,12,13,sToD('20140317')})
		oFWMsExcel:AddRow("Aba 1 Teste","Titulo Tabela",{21,22,23,sToD('20140217')})
		oFWMsExcel:AddRow("Aba 1 Teste","Titulo Tabela",{31,32,33,sToD('20140117')})
		oFWMsExcel:AddRow("Aba 1 Teste","Titulo Tabela",{41,42,43,sToD('20131217')})
	
	
	//Aba 02 - Produtos
	oFWMsExcel:AddworkSheet("Aba 2 Produtos")
		//Criando a Tabela
		oFWMsExcel:AddTable("Aba 2 Produtos","Produtos")
		oFWMsExcel:AddColumn("Aba 2 Produtos","Produtos","Codigo",1)
		oFWMsExcel:AddColumn("Aba 2 Produtos","Produtos","Descricao",1)
		oFWMsExcel:AddColumn("Aba 2 Produtos","Produtos","Tipo",1)
		oFWMsExcel:AddColumn("Aba 2 Produtos","Produtos","Grupo",1)
		oFWMsExcel:AddColumn("Aba 2 Produtos","Produtos","Desc.Grupo",1)
		oFWMsExcel:AddColumn("Aba 2 Produtos","Produtos","Procedencia",1)
		//Criando as Linhas... Enquanto não for fim da query
		While !(QRYPRO->(EoF()))
			oFWMsExcel:AddRow("Aba 2 Produtos","Produtos",{;
																	QRYPRO->B1_COD,;
																	QRYPRO->B1_DESC,;
																	QRYPRO->B1_TIPO,;
																	QRYPRO->BM_GRUPO,;
																	QRYPRO->BM_DESC,;
																	Iif(QRYPRO->BM_PROORI == '0', 'Não Original', 'Original');
			})
		
			//Pulando Registro
			QRYPRO->(DbSkip())
		EndDo
	
	//Ativando o arquivo e gerando o xml
	oFWMsExcel:Activate()
	oFWMsExcel:GetXMLFile(cArquivo)
		
	//Abrindo o excel e abrindo o arquivo xml
	oExcel := MsExcel():New() 			//Abre uma nova conexão com Excel
	oExcel:WorkBooks:Open(cArquivo) 	//Abre uma planilha
	oExcel:SetVisible(.T.) 				//Visualiza a planilha
	oExcel:Destroy()						//Encerra o processo do gerenciador de tarefas
	
	QRYPRO->(DbCloseArea())
	RestArea(aArea)
Return


Exemplo simples de FWMsExcelEx:

Exemplo simples de FWMsExcelEx

Exemplo simples de FWMsExcelEx

Abaixo o código fonte utilizado:

//Bibliotecas
#Include "Protheus.ch"
#Include "TopConn.ch"

//Constantes
#Define STR_PULA	Chr(13)+Chr(10)

/*/{Protheus.doc} zTstExc2
Função que cria um exemplo de FWMSExcelEx
@author Atilio
@since 06/08/2016
@version 1.0
	@example
	u_zTstExc2()
/*/

User Function zTstExc2()
	Local cArquivo	:= GetTempPath()+'zTstExc2c.xml'
	Local oFWMSEx		:= FWMsExcelEx():New()
	Local oExcel
	
	//Criando a Aba Teste 1
	oFWMSEx:AddworkSheet("Teste - 1")
		//Adicionando a tabela
		oFWMSEx:AddTable ("Teste - 1","Titulo de teste 1")
			//Adicionando as colunas
			oFWMSEx:AddColumn("Teste - 1","Titulo de teste 1","Col1",1,1)
			oFWMSEx:AddColumn("Teste - 1","Titulo de teste 1","Col2",2,2)
			oFWMSEx:AddColumn("Teste - 1","Titulo de teste 1","Col3",3,3)
			oFWMSEx:AddColumn("Teste - 1","Titulo de teste 1","Col4",1,1)
			
				//Alterando atributos da linha e adicionando
				oFWMSEx:SetCelBold(.T.)
				oFWMSEx:SetCelFont('Arial')
				oFWMSEx:SetCelItalic(.T.)
				oFWMSEx:SetCelUnderLine(.T.)
				oFWMSEx:SetCelSizeFont(10)
				oFWMSEx:AddRow("Teste - 1","Titulo de teste 1",{11,12,13,14},{1,3})
				
				//Alterando atributos da linha e adicionando
				oFWMSEx:SetCelBold(.T.)
				oFWMSEx:SetCelFont('Arial')
				oFWMSEx:SetCelItalic(.T.)
				oFWMSEx:SetCelUnderLine(.T.)
				oFWMSEx:SetCelSizeFont(15)
				oFWMSEx:SetCelFrColor("#FFFFFF")
				oFWMSEx:SetCelBgColor("#000666")
				oFWMSEx:AddRow("Teste - 1","Titulo de teste 1",{21,22,23,24},{1})
				
				//Alterando atributos da linha e adicionando
				oFWMSEx:SetCelBold(.T.)
				oFWMSEx:SetCelFont('Courier New')
				oFWMSEx:SetCelItalic(.F.)
				oFWMSEx:SetCelUnderLine(.T.)
				oFWMSEx:SetCelSizeFont(10)
				oFWMSEx:SetCelFrColor("#FFFFFF")
				oFWMSEx:SetCelBgColor("#000333")
				oFWMSEx:AddRow("Teste - 1","Titulo de teste 1",{31,32,33,34},{2,4})
				
				//Alterando atributos da linha e adicionando
				oFWMSEx:SetCelBold(.T.)
				oFWMSEx:SetCelFont('Line Draw')
				oFWMSEx:SetCelItalic(.F.)
				oFWMSEx:SetCelUnderLine(.F.)
				oFWMSEx:SetCelSizeFont(12)
				oFWMSEx:SetCelFrColor("#FFFFFF")
				oFWMSEx:SetCelBgColor("#D7BCFB")
				oFWMSEx:AddRow("Teste - 1","Titulo de teste 1",{41,42,43,44},{3})
	
	//Adicionando aba Teste 2
	oFWMSEx:AddworkSheet("Teste - 2")
		//Adicionando a tabela
		oFWMSEx:AddTable("Teste - 2","Titulo de teste 1")
			//Adicionando as colunas
			oFWMSEx:AddColumn("Teste - 2","Titulo de teste 1","Col1",1)
			oFWMSEx:AddColumn("Teste - 2","Titulo de teste 1","Col2",2)
			oFWMSEx:AddColumn("Teste - 2","Titulo de teste 1","Col3",3)
			oFWMSEx:AddColumn("Teste - 2","Titulo de teste 1","Col4",1)
			//Adicionando as linhas
			oFWMSEx:AddRow("Teste - 2","Titulo de teste 1",{11,12,13,stod("20121212")})
			oFWMSEx:AddRow("Teste - 2","Titulo de teste 1",{21,22,23,stod("20121212")})
			oFWMSEx:AddRow("Teste - 2","Titulo de teste 1",{31,32,33,stod("20121212")})
			oFWMSEx:AddRow("Teste - 2","Titulo de teste 1",{41,42,43,stod("20121212")})
			oFWMSEx:AddRow("Teste - 2","Titulo de teste 1",{51,52,53,stod("20121212")})
		
	//Criando o XML
	oFWMSEx:Activate()
	oFWMSEx:GetXMLFile(cArquivo)
	
	//Abrindo o excel e abrindo o arquivo xml
	oExcel := MsExcel():New() 			//Abre uma nova conexão com Excel
	oExcel:WorkBooks:Open(cArquivo) 	//Abre uma planilha
	oExcel:SetVisible(.T.) 				//Visualiza a planilha
	oExcel:Destroy()						//Encerra o processo do gerenciador de tarefas
Return


Exemplo de FWMsExcel com cores e fonte diferente:

Exemplo de FWMsExcel com cores e fonte diferente

Exemplo de FWMsExcel com cores e fonte diferente

Abaixo o código fonte utilizado:

//Bibliotecas
#Include "Protheus.ch"
#Include "TopConn.ch"

//Constantes
#Define STR_PULA	Chr(13)+Chr(10)

/*/{Protheus.doc} zTstExc3
Função que cria um exemplo de FWMsExcel utilizando outras cores e fontes
@author Atilio
@since 06/08/2016
@version 1.0
	@example
	u_zTstExc3()
/*/

User Function zTstExc3()
	Local aArea		:= GetArea()
	Local cQuery		:= ""
	Local oFWMsExcel
	Local oExcel
	Local cArquivo	:= GetTempPath()+'zTstExc3.xml'

	//Pegando os dados
	cQuery := " SELECT "													+ STR_PULA
	cQuery += " 	SB1.B1_COD, "											+ STR_PULA
	cQuery += " 	SB1.B1_DESC, "										+ STR_PULA
	cQuery += " 	SB1.B1_TIPO, "										+ STR_PULA
	cQuery += " 	SBM.BM_GRUPO, "										+ STR_PULA
	cQuery += " 	SBM.BM_DESC, "										+ STR_PULA
	cQuery += " 	SBM.BM_PROORI "										+ STR_PULA
	cQuery += " FROM "													+ STR_PULA
	cQuery += " 	"+RetSQLName('SB1')+" SB1 "							+ STR_PULA
	cQuery += " 	INNER JOIN "+RetSQLName('SBM')+" SBM ON ( "		+ STR_PULA
	cQuery += " 		SBM.BM_FILIAL = '"+FWxFilial('SBM')+"' "		+ STR_PULA
	cQuery += " 		AND SBM.BM_GRUPO = B1_GRUPO "					+ STR_PULA
	cQuery += " 		AND SBM.D_E_L_E_T_='' "							+ STR_PULA
	cQuery += " 	) "														+ STR_PULA
	cQuery += " WHERE "													+ STR_PULA
	cQuery += " 	SB1.B1_FILIAL = '"+FWxFilial('SBM')+"' "			+ STR_PULA
	cQuery += " 	AND SB1.D_E_L_E_T_ = '' "							+ STR_PULA
	cQuery += " ORDER BY "												+ STR_PULA
	cQuery += " 	SB1.B1_COD "											+ STR_PULA
	TCQuery cQuery New Alias "QRYPRO"
	
	//Criando o objeto que irá gerar o conteúdo do Excel
	oFWMsExcel := FWMSExcel():New()
	
	//Alterando atributos
	oFWMsExcel:SetFontSize(12)                 //Tamanho Geral da Fonte
	oFWMsExcel:SetFont("Arial")                //Fonte utilizada
	oFWMsExcel:SetBgGeneralColor("#000000")    //Cor de Fundo Geral
	oFWMsExcel:SetTitleBold(.T.)               //Título Negrito
	oFWMsExcel:SetTitleFrColor("#94eaff")      //Cor da Fonte do título - Azul Claro
	oFWMsExcel:SetLineFrColor("#d4d4d4")       //Cor da Fonte da primeira linha - Cinza Claro
	oFWMsExcel:Set2LineFrColor("#ffffff")      //Cor da Fonte da segunda linha - Branco
	
	//Aba 01 - Teste
	oFWMsExcel:AddworkSheet("Aba 1 Teste") //Não utilizar número junto com sinal de menos. Ex.: 1-
		//Criando a Tabela
		oFWMsExcel:AddTable("Aba 1 Teste","Titulo Tabela")
		//Criando Colunas
		oFWMsExcel:AddColumn("Aba 1 Teste","Titulo Tabela","Col1",1,1) //1 = Modo Texto
		oFWMsExcel:AddColumn("Aba 1 Teste","Titulo Tabela","Col2",2,2) //2 = Valor sem R$
		oFWMsExcel:AddColumn("Aba 1 Teste","Titulo Tabela","Col3",3,3) //3 = Valor com R$
		oFWMsExcel:AddColumn("Aba 1 Teste","Titulo Tabela","Col4",1,1)
		//Criando as Linhas
		oFWMsExcel:AddRow("Aba 1 Teste","Titulo Tabela",{11,12,13,sToD('20140317')})
		oFWMsExcel:AddRow("Aba 1 Teste","Titulo Tabela",{21,22,23,sToD('20140217')})
		oFWMsExcel:AddRow("Aba 1 Teste","Titulo Tabela",{31,32,33,sToD('20140117')})
		oFWMsExcel:AddRow("Aba 1 Teste","Titulo Tabela",{41,42,43,sToD('20131217')})
	
	
	//Aba 02 - Produtos
	oFWMsExcel:AddworkSheet("Aba 2 Produtos")
		//Criando a Tabela
		oFWMsExcel:AddTable("Aba 2 Produtos","Produtos")
		oFWMsExcel:AddColumn("Aba 2 Produtos","Produtos","Codigo",1)
		oFWMsExcel:AddColumn("Aba 2 Produtos","Produtos","Descricao",1)
		oFWMsExcel:AddColumn("Aba 2 Produtos","Produtos","Tipo",1)
		oFWMsExcel:AddColumn("Aba 2 Produtos","Produtos","Grupo",1)
		oFWMsExcel:AddColumn("Aba 2 Produtos","Produtos","Desc.Grupo",1)
		oFWMsExcel:AddColumn("Aba 2 Produtos","Produtos","Procedencia",1)
		//Criando as Linhas... Enquanto não for fim da query
		While !(QRYPRO->(EoF()))
			oFWMsExcel:AddRow("Aba 2 Produtos","Produtos",{;
																	QRYPRO->B1_COD,;
																	QRYPRO->B1_DESC,;
																	QRYPRO->B1_TIPO,;
																	QRYPRO->BM_GRUPO,;
																	QRYPRO->BM_DESC,;
																	Iif(QRYPRO->BM_PROORI == '0', 'Não Original', 'Original');
			})
		
			//Pulando Registro
			QRYPRO->(DbSkip())
		EndDo
	
	//Ativando o arquivo e gerando o xml
	oFWMsExcel:Activate()
	oFWMsExcel:GetXMLFile(cArquivo)
		
	//Abrindo o excel e abrindo o arquivo xml
	oExcel := MsExcel():New() 			//Abre uma nova conexão com Excel
	oExcel:WorkBooks:Open(cArquivo) 	//Abre uma planilha
	oExcel:SetVisible(.T.) 				//Visualiza a planilha
	oExcel:Destroy()						//Encerra o processo do gerenciador de tarefas
	
	QRYPRO->(DbCloseArea())
	RestArea(aArea)
Return


Exemplo de FWMsExcel com colunas dinâmicas (Produtos por dias de venda):

Exemplo de FWMsExcel com colunas dinâmicas (Produtos por dias de venda)

Exemplo de FWMsExcel com colunas dinâmicas (Produtos por dias de venda)

Abaixo o código fonte utilizado:

//Bibliotecas
#Include "Protheus.ch"
#Include "TopConn.ch"

//Constantes
#Define STR_PULA	Chr(13)+Chr(10)

/*/{Protheus.doc} zTstExc4
Função que cria um exemplo de FWMsExcel com colunas dinâmicas
@author Atilio
@since 06/08/2016
@version 1.0
	@example
	u_zTstExc4()
/*/

User Function zTstExc4()
	Local aArea		:= GetArea()
	Local cQryCol		:= ""
	Local cQryPro		:= ""
	Local cQryVen		:= ""
	Local nAux			:= 0
	Local oFWMsExcel
	Local oExcel
	Local cArquivo	:= GetTempPath()+'zTstExc4.xml'
	Local cWorkSheet	:= "Aba - Produtos"
	Local cTable		:= "Produtos x Datas"
	Local aColunas	:= {}
	Local dDataDe		:= sToD("20150101")
	Local dDataAt		:= sToD("20161231")
	Local aLinhaAux	:= {}
	
	//Buscando as datas que tiveram pedidos
	cQryCol := " SELECT DISTINCT "
	cQryCol += " 	C5_EMISSAO "
	cQryCol += " FROM "
	cQryCol += " 	"+RetSQLName('SC5')+" SC5 "
	cQryCol += " WHERE "
	cQryCol += " 	C5_FILIAL = '"+FWxFilial('SC5')+"' "
	cQryCol += " 	AND C5_TIPO = 'N' "
	cQryCol += " 	AND C5_EMISSAO >= '"+dToS(dDataDe)+"' "
	cQryCol += " 	AND C5_EMISSAO <= '"+dToS(dDataAt)+"' "
	cQryCol += " 	AND SC5.D_E_L_E_T_ = ' ' "
	cQryCol += " ORDER BY "
	cQryCol += " 	C5_EMISSAO "
	TCQuery cQryCol New Alias "QRY_COL"
	TCSetField("QRY_COL", "C5_EMISSAO", "D")

	//Compondo as colunas do relatório
	aAdd(aColunas, "Produto")
	aAdd(aColunas, "Descrição")
	While !QRY_COL->(EoF())
		aAdd(aColunas, dToC(QRY_COL->C5_EMISSAO))
		QRY_COL->(DbSkip())
	EndDo
	QRY_COL->(DbCloseArea())
	
	//Montando a consulta de produtos
	cQryPro := " SELECT "
	cQryPro += " 	B1_COD, "
	cQryPro += " 	B1_DESC "
	cQryPro += " FROM "
	cQryPro += " 	"+RetSQLName('SB1')+" SB1 "
	cQryPro += " WHERE "
	cQryPro += " 	B1_FILIAL = '"+FWxFilial('SB1')+"' "
	cQryPro += " 	AND B1_TIPO = 'PA' "
	cQryPro += " 	AND SB1.D_E_L_E_T_ = ' ' "
	cQryPro += " ORDER BY "
	cQryPro += " 	B1_COD "
	TCQuery cQryPro New Alias "QRY_PRO"
	
	//Criando o objeto que irá gerar o conteúdo do Excel
	oFWMsExcel := FWMSExcel():New()
	
	//Aba 01 - Teste
	oFWMsExcel:AddworkSheet(cWorkSheet) //Não utilizar número junto com sinal de menos. Ex.: 1-
		
		//Criando a Tabela
		oFWMsExcel:AddTable(cWorkSheet, cTable)
		
		//Criando Colunas
		For nAux := 1 To Len(aColunas)
			oFWMsExcel:AddColumn(cWorkSheet, cTable, aColunas[nAux], 1, 1)
		Next
		
		//Percorrendo os produtos
		While !QRY_PRO->(EoF())
			//Criando a linha
			aLinhaAux := Array(Len(aColunas))
			aLinhaAux[1] := QRY_PRO->B1_COD
			aLinhaAux[2] := QRY_PRO->B1_DESC
			For nAux := 3 To Len(aColunas)
				cQryVen := " SELECT "
				cQryVen += " 	ISNULL(SUM(C6_QTDVEN),0) AS TOT "
				cQryVen += " FROM "
				cQryVen += " 	"+RetSQLName('SC6')+" SC6 "
				cQryVen += " 	INNER JOIN "+RetSQLName('SC5')+" SC5 ON ( "
				cQryVen += " 		C5_FILIAL = '"+FWxFilial('SC5')+"' "
				cQryVen += " 		AND C5_NUM = C6_NUM "
				cQryVen += " 		AND C5_TIPO = 'N' "
				cQryVen += " 		AND C5_EMISSAO = '"+dToS(cToD(aColunas[nAux]))+"' "
				cQryVen += " 		AND SC5.D_E_L_E_T_ = ' ' "
				cQryVen += " 	) "
				cQryVen += " 	INNER JOIN "+RetSQLName('SB1')+" SB1 ON ( "
				cQryVen += " 		B1_FILIAL = '"+FWxFilial('SB1')+"' "
				cQryVen += " 		AND B1_COD = C6_PRODUTO "
				cQryVen += " 		AND B1_TIPO = 'PA' "
				cQryVen += " 		AND SB1.D_E_L_E_T_ = ' ' "
				cQryVen += " 	) "
				cQryVen += " WHERE "
				cQryVen += " 	C6_FILIAL = '"+FWxFilial('SC6')+"' "
				cQryVen += " 	AND C6_PRODUTO = '"+QRY_PRO->B1_COD+"' "
				cQryVen += " 	AND SC6.D_E_L_E_T_ = ' ' "
				TCQuery cQryVen New Alias "QRY_VEN"
				
				//Atribuindo o valor
				aLinhaAux[nAux] := QRY_VEN->TOT
				QRY_VEN->(DbCloseArea())
			Next
			
			//Adiciona a linha no Excel
			oFWMsExcel:AddRow(cWorkSheet, cTable, aLinhaAux)
			
			QRY_PRO->(DbSkip())
		EndDo
		
		//Tratativa para o Total
		aLinhaAux := Array(Len(aColunas))
		aLinhaAux[1] := "Total: "
		aLinhaAux[2] := ""
		For nAux := 3 To Len(aColunas)
			cQryVen := " SELECT "
			cQryVen += " 	ISNULL(SUM(C6_QTDVEN),0) AS TOT "
			cQryVen += " FROM "
			cQryVen += " 	"+RetSQLName('SC6')+" SC6 "
			cQryVen += " 	INNER JOIN "+RetSQLName('SC5')+" SC5 ON ( "
			cQryVen += " 		C5_FILIAL = '"+FWxFilial('SC5')+"' "
			cQryVen += " 		AND C5_NUM = C6_NUM "
			cQryVen += " 		AND C5_TIPO = 'N' "
			cQryVen += " 		AND C5_EMISSAO = '"+dToS(cToD(aColunas[nAux]))+"' "
			cQryVen += " 		AND SC5.D_E_L_E_T_ = ' ' "
			cQryVen += " 	) "
			cQryVen += " 	INNER JOIN "+RetSQLName('SB1')+" SB1 ON ( "
			cQryVen += " 		B1_FILIAL = '"+FWxFilial('SB1')+"' "
			cQryVen += " 		AND B1_COD = C6_PRODUTO "
			cQryVen += " 		AND B1_TIPO = 'PA' "
			cQryVen += " 		AND SB1.D_E_L_E_T_ = ' ' "
			cQryVen += " 	) "
			cQryVen += " WHERE "
			cQryVen += " 	C6_FILIAL = '"+FWxFilial('SC6')+"' "
			cQryVen += " 	AND SC6.D_E_L_E_T_ = ' ' "
			TCQuery cQryVen New Alias "QRY_VEN"
			
			//Atribuindo o valor
			aLinhaAux[nAux] := QRY_VEN->TOT
			QRY_VEN->(DbCloseArea())
		Next
		
		//Adiciona a linha no Excel
		oFWMsExcel:AddRow(cWorkSheet, cTable, aLinhaAux)
		
	//Ativando o arquivo e gerando o xml
	oFWMsExcel:Activate()
	oFWMsExcel:GetXMLFile(cArquivo)
		
	//Abrindo o excel e abrindo o arquivo xml
	oExcel := MsExcel():New() 			//Abre uma nova conexão com Excel
	oExcel:WorkBooks:Open(cArquivo) 	//Abre uma planilha
	oExcel:SetVisible(.T.) 				//Visualiza a planilha
	oExcel:Destroy()						//Encerra o processo do gerenciador de tarefas
	
	QRY_PRO->(DbCloseArea())
	RestArea(aArea)
Return


Referências:
tdn.totvs.com/display/public/mp/FWMsExcel
tdn.totvs.com/display/framework/FWMsExcelEx

Bom pessoal, por hoje é só.
Abraços e até a próxima.

Dan (Daniel Atilio)
Especialista em Engenharia de Software pela FIB. Entusiasta de soluções Open Source. E blogueiro nas horas vagas.

43 Responses

  1. George Allan disse:

    Ótimo post Daniel, bem explicado, com os exemplos, bem legal mesmo cara. Obrigado por compartilhar! 🙂

    George Allan
    http://www.userfunction.com.br

  2. Muito legal a dica, parabéns!

  3. Tiago Freitas disse:

    Muito Legal!!! Acabei de usar, otimo exemplo.

  4. Luis Gustavo disse:

    Legal o port Dan_Atilio, parabéns pela iniciativa.

    Recentemente utilizei para montar um KPI para área comercial, onde o mesmo é enviado todos os dias para diretoria e gerencia.
    Porém, não contente agora, o pessoal quer ver pelo celular antes de chegar na empresa.
    O xml gerado não abre no excel para celular por não ser compatível com o office 2013 e posteriores.

    Você sabe algum meio que possa converter esse arquivo xml em padrão office .xlsx?

    Abraços
    Luís Gustavo

  5. Ricardo Cassolatto disse:

    Qual a diferença entre :
    – FWMsExcel
    – FWMsExcelEx
    ?

    Nenhuma , ou é sútil ?

    Obrigado, ótimos post !

    • Dan_Atilio disse:

      Bom dia Ricardo.
      Conforme disse no começo da postagem:
      “Existem duas classes para geração de arquivos xml do Excel, a FWMsExcel e a FWMsExcelEx, a segunda tem mais opções de edição de atributos de uma célula”

      A segunda tem opções de você editar somente uma célula (como cor, fonte, fundo, etc), e não mudar a cor da planilha inteira.
      Espero ter ajudado.
      Abraços e muito obrigado.

  6. Erick disse:

    boa tarde, consegui gerar o arquivo, porem via schedule não gera, alguma dica ?
    da erro
    oExcel:Activate()

    invalid handle used in file C:\bamboo-agent-5.7.2\xml-data\build-dir\TP11-BUILDV1APPSRV-PROTHEUSWIN32\lib_base\diskman.cpp at line 265
    on FWMSEXCEL:GETXMLFILE(FWMSEXCEL.PRX) 09/12/2016 15:19:44 line : 467

  7. Abel Ribeiro disse:

    Atilio, Boa Tarde

    Estou utilizando esse exemplo e na linha oExcel := MsExcel():New() , o sistema trava e nao abre a planilha,
    vc sabe o que pode ser?

    Att

    Abel

  8. Jose Ricardo disse:

    Boa tarde! Antes de mais nada parabéns pelo post, estou com a necessidade de inserir um imagem na Planilha ( logotipo da empresa), existe recurso para isto

    • Dan_Atilio disse:

      Bom dia Jose.
      Infelizmente acho que não é possível. Pois, a geração de arquivo do Excel via AdvPL, utliza XML e nele não tem como embutir uma imagem, mas você poderia abrir um chamado no Suporte da TOTVS perguntando se eles estão planejando adicionar esse recurso.
      Um grande abraço.

  9. Jose Santos disse:

    Parabéns pelo post!!! Um desenvolvedor novo conseguiu gerar um código com facilidade usando seu exemplo!!!
    Agora um dúvida… sabe de alguma forma de gerar um Excel com fórmulas nas células via AdvPL?

  10. narba disse:

    É possível colocar duas colunas diferentes na mesma planilha?
    Exemplo:
    Nome | CPF
    Joao 9999999999

    Codigo | Descrição | Valor

  11. Walmar De Freitas G disse:

    Bom Dia, parabéns Atilio.!! use seu exemplo hoje como guia, muito obrigado por compartilhar..!!

  12. Rogério disse:

    Boa noite

    Parabéns pelo conteúdo. Atendeu o que eu precisava.

    Uma dúvida! Estou usando o CpyS2T para copiar o arquivo de um diretório para o outro. (Isso funciona somente acessando via smartclient).

    Qual função posso usar para fazer isso via schedule, job ?

    Se for o caso, pode ser alguma função para gravar diretamente o .CSV / .XML no diretório também

    Obrigado e um grande abraço

  13. Alice disse:

    Boa tarde, parabéns pelo conteúdo atendeu o que eu precisava, mas se eu quiser colocar além da quantidade do produto, colocar tbm o valor pra cada mês, eu consigo fazer?

  14. Fernando Braga disse:

    Boa tarde

    Agora o sx3 fica no banco e pelo apsu só existe opção de salvar em ctree e txt, teria algum jeito mais fácil de geral em DBF ou Excel parte do sx3 tipo todo o conteúdo do SRA.

    Grato

  15. Luis disse:

    @Dan_Atilio parabéns e obrigado pelo exemplo!! Estou tentando colocar resultados de 2 query, uma em cada aba e não estou conseguindo. Em uma única aba dá certo, mas na segunda dá error.log
    THREAD ERROR ([9540], lakn, LAKN) 23/06/2021 15:32:14
    erro no parâmetroFWMSEXCEL: WorkSheet or Table out of range on FWMSEXCEL:ADDROW(FWMSEXCEL.PRX) 08/04/2021 17:34:09 line : 470

    Este é o código que estou tentando
    //Bibliotecas
    #Include “Protheus.ch”
    #Include “TopConn.ch”

    //Constantes
    #Define STR_PULA Chr(13)+Chr(10)

    User Function OXGPE033()
    Local aArea := GetArea()
    Local cQuery,cQuery2 := “”
    Local oFWMsExcel
    Local oExcel
    Local cArquivo := GetTempPath()+’OXGPE033.xml’

    //Pegando os dados

    cQuery := ” select RB_MAT Matricula,RA_NOME Nome,COUNT(RB_COD) QtdeFilhos,RA_CC+’-‘+CTT_DESC01 As CentrodeCusto”
    cQuery += ” from SRB010 SRB, SRA010 SRA, CTT010 CTT(NOLOCK)”
    cQuery += ” where SRB.D_E_L_E_T_ ‘*'”
    cQuery += ” and CTT.D_E_L_E_T_ = ””
    cQuery += ” and RA_FILIAL = CTT_FILIAL”
    cQuery += ” and RA_CC = CTT_CUSTO”
    cQuery += ” and SRA.D_E_L_E_T_ ‘*'”
    cQuery += ” and RB_FILIAL = RA_FILIAL”
    cQuery += ” and RB_MAT = RA_MAT”
    cQuery += ” and RA_SITFOLH ‘D'”
    cQuery += ” and RB_GRAUPAR = ‘F'”
    cQuery += ” and RA_SEXO = ‘M'”
    cQuery += ” group by RB_MAT, RA_NOME, RA_CC, CTT_DESC01, RA_SITFOLH”
    cQuery += ” order by RA_NOME”
    TCQuery cQuery New Alias “QRYPRO”

    //Criando o objeto que irá gerar o conteúdo do Excel
    oFWMsExcel := FWMSExcel():New()
    /*
    //Aba 01 – Teste
    oFWMsExcel:AddworkSheet(“Aba 1 Teste”) //Não utilizar número junto com sinal de menos. Ex.: 1-
    //Criando a Tabela
    oFWMsExcel:AddTable(“Aba 1 Teste”,”Titulo Tabela”)
    //Criando Colunas
    oFWMsExcel:AddColumn(“Aba 1 Teste”,”Titulo Tabela”,”Col1″,1,1) //1 = Modo Texto
    oFWMsExcel:AddColumn(“Aba 1 Teste”,”Titulo Tabela”,”Col2″,2,2) //2 = Valor sem R$
    oFWMsExcel:AddColumn(“Aba 1 Teste”,”Titulo Tabela”,”Col3″,3,3) //3 = Valor com R$
    oFWMsExcel:AddColumn(“Aba 1 Teste”,”Titulo Tabela”,”Col4″,1,1)
    //Criando as Linhas
    oFWMsExcel:AddRow(“Aba 1 Teste”,”Titulo Tabela”,{11,12,13,sToD(‘20140317’)})
    oFWMsExcel:AddRow(“Aba 1 Teste”,”Titulo Tabela”,{21,22,23,sToD(‘20140217’)})
    oFWMsExcel:AddRow(“Aba 1 Teste”,”Titulo Tabela”,{31,32,33,sToD(‘20140117’)})
    oFWMsExcel:AddRow(“Aba 1 Teste”,”Titulo Tabela”,{41,42,43,sToD(‘20131217′)})

    */
    //Aba 02 – FUNCIONARIOS QUE SAO PAIS
    oFWMsExcel:AddworkSheet(“PAIS”)
    //Criando a Tabela
    oFWMsExcel:AddTable(“PAIS”,”FUNCIONARIOS QUE SAO PAIS”)
    oFWMsExcel:AddColumn(“PAIS”,”FUNCIONARIOS QUE SAO PAIS”,”Matricula”,1)
    oFWMsExcel:AddColumn(“PAIS”,”FUNCIONARIOS QUE SAO PAIS”,”Nome”,1)
    oFWMsExcel:AddColumn(“PAIS”,”FUNCIONARIOS QUE SAO PAIS”,”QtdeFilhos”,1)
    oFWMsExcel:AddColumn(“PAIS”,”FUNCIONARIOS QUE SAO PAIS”,”CentrodeCusto”,1)
    //Criando as Linhas… Enquanto não for fim da query
    While !(QRYPRO->(EoF()))
    oFWMsExcel:AddRow(“PAIS”,”FUNCIONARIOS QUE SAO PAIS”,{;
    QRYPRO->Matricula,;
    QRYPRO->Nome,;
    QRYPRO->QtdeFilhos,;
    QRYPRO->CentrodeCusto;
    })

    //Pulando Registro
    QRYPRO->(DbSkip())
    EndDo
    QRYPRO->(DbCloseArea())
    RestArea(aArea)

    cQuery2 := ” select RB_MAT Matricula,RA_NOME Nome,COUNT(RB_COD) QtdeFilhos,RA_CC+’-‘+CTT_DESC01 As CentrodeCusto”
    cQuery2 += ” from SRB010 SRB, SRA010 SRA, CTT010 CTT(NOLOCK)”
    cQuery2 += ” where SRB.D_E_L_E_T_ ‘*'”
    cQuery2 += ” and CTT.D_E_L_E_T_ = ””
    cQuery2 += ” and RA_FILIAL = CTT_FILIAL”
    cQuery2 += ” and RA_CC = CTT_CUSTO”
    cQuery2 += ” and SRA.D_E_L_E_T_ ‘*'”
    cQuery2 += ” and RB_FILIAL = RA_FILIAL”
    cQuery2 += ” and RB_MAT = RA_MAT”
    cQuery2 += ” and RA_SITFOLH ‘D'”
    cQuery2 += ” and RB_GRAUPAR = ‘F'”
    cQuery2 += ” and RA_SEXO = ‘F'”
    cQuery2 += ” group by RB_MAT, RA_NOME, RA_CC, CTT_DESC01, RA_SITFOLH”
    cQuery2 += ” order by RA_NOME”
    TCQuery cQuery2 New Alias “QRYPRO2”

    //Aba 02 – FUNCIONARIOS QUE SAO MAE
    oFWMsExcel:AddworkSheet(“MAES”)
    //Criando a Tabela
    oFWMsExcel:AddTable(“MAES”,”FUNCIONARIAS QUE SAO MAES”)
    oFWMsExcel:AddColumn(“MAES”,”FUNCIONARIAS QUE SAO MAES”,”Matricula”,1)
    oFWMsExcel:AddColumn(“MAES”,”FUNCIONARIAS QUE SAO MAES”,”Nome”,1)
    oFWMsExcel:AddColumn(“MAES”,”FUNCIONARIAS QUE SAO MAES”,”QtdeFilhos”,1)
    oFWMsExcel:AddColumn(“MAES”,”FUNCIONARIAS QUE SAO MAES”,”CentrodeCusto”,1)
    //Criando as Linhas… Enquanto não for fim da query
    While !(QRYPRO2->(EoF()))
    oFWMsExcel:AddRow(“MAES”,”FUNCIONARIAS QUE SAO MAE”,{;
    QRYPRO2->Matricula,;
    QRYPRO2->Nome,;
    QRYPRO2->QtdeFilhos,;
    QRYPRO2->CentrodeCusto;
    })

    //Pulando Registro
    QRYPRO2->(DbSkip())
    EndDo

    //Ativando o arquivo e gerando o xml
    oFWMsExcel:Activate()
    oFWMsExcel:GetXMLFile(cArquivo)

    //Abrindo o excel e abrindo o arquivo xml
    oExcel := MsExcel():New() //Abre uma nova conexão com Excel
    oExcel:WorkBooks:Open(cArquivo) //Abre uma planilha
    oExcel:SetVisible(.T.) //Visualiza a planilha
    oExcel:Destroy() //Encerra o processo do gerenciador de tarefas

    QRYPRO2->(DbCloseArea())
    //QRYPRO2->(DbCloseArea())

    RestArea(aArea)
    Return

  16. Luis Nagasako disse:

    BOm dia, pessoal, estou com esse trecho do fonte, onde está dando Syntax error na última linha no }), alguém tem alguma ideia?

    While !(QRY->(EoF()))
    wvalliq := QRY->F2_VALBRUT – QRY->IPI – QRY->PRODUTOX – QRY->D2_VALIMP5 – QRY->D2_VALIMP6
    wvallitro := wvalliq/QRY->D2_QTSEGUM
    wvalltdolar := wvallitro/QRY->C5_ZDOLAR

    oFWMsExcel:AddRow(“Campanhas PRODUTOYYYY”,”Campanhas PRODUTOYYYY”,{;
    QRY->D2_DOC,;
    QRY->D2_SERIE,;
    QRY->QRY->F2_EMISSAO,;
    QRY->D2_COD,;
    QRY->B1_DESC,;
    QRY->D2_UM,;
    QRY->D2_QUANT,;
    QRY->D2_SEGUM,;
    QRY->D2_QTSEGUM,;
    QRY->E1_VALOR,;
    QRY->F2_VALBRUT,;
    QRY->D2_VALIMP6,;
    QRY->D2_VALIMP5,;
    QRY->IPI,;
    QRY->PRODUTOX,;
    wvalliq,;
    wvallitro,;
    QRY->C5_ZDOLAR,;
    wvalltdolar,;
    QRY->E1_NOMCLI,;
    QRY->E1_VENCREA,;
    QRY->D2_NUMPCOM,;
    QRY->D2_PEDIDO,;
    QRY->C5_ZCAMPAN,;
    QRY->F2_ZMUNTRO;
    })

  17. Caroline Cazela disse:

    Boa tarde! Conseguiram identificar o problema? Estou com o mesmo erro acontecendo!

  18. Lucas Lopez disse:

    Boa tarde!

    Primeiramente gostaria de agradecer o ótimo conteúdo que você trás pra gente…

    Estou com uma dúvida em relação ao FWMsExcel e o TReport, os dois são classes Advpl para geração de relatório e pelo que entendo o TRport é uma forma mais antiga e com menos recursos e a FWMsExcel é uma forma mais nova com mais recursos.

    Seria isso mesmo ?

    Obrigado!

    • Boa tarde Lucas, tudo bem?
      Obrigado pelo feedback, é gentileza sua.

      Contextualizando um pouco sobre as classes de relatórios que são usadas atualmente:
      A TReport ela é uma classe de relatórios para gerar pdfs, imprimir na Spool, Excel, etc.
      A FSMsExcel e derivadas são classes específicas para o Excel, com muito mais possibilidades.
      A FWMsPrinter é uma classe para relatórios gráficos em pdf com muito mais possibilidades que a classe TReport.

      Resumindo então, se você quiser relatórios genéricos que funcionem em várias formas diferentes, use TReport. Se precisa de algo específico no Excel, use a FWMsExcel ou derivadas. Se precisa de uma específica para PDF com possibilidades de imprimir imagens, gráficos, etc use a FWMsPrinter.

      As formas antigas nem citei acima (como SetPrint, TMSPrinter, etc), então você pode sim usar TReport, assim como as outras que eu citei acima.

      Abraços.

  19. Mauricio disse:

    Ola. Boa tarde. Sei que esse link é antigo, mas poderia me tirar uma duvida se usando o FWMSEXCEl tem um jeito de exportar a tabela formatada na forma original do excel, digo com as celulas mantendo o grid padrão do excel e só incluindo os dados. Tentei de tudo aqui…mas fica tudo em uma cor somente…sem o grid original do excel.

  20. Thiago Ewerton disse:

    Boa tarde, precisando montar algo parecido, porém que exporte no LibreOffice ou gere um arquivo XML num diretório para abrir via LibreOfficeCalc. poderia me ajudar ?
    OBS: Ainda sou muito leigo em ADVPL.

    • Boa tarde Thiago, tudo bem?
      Certo, deixe o LibreOffice Calc como programa padrão para abrir arquivos XML.
      Ai via AdvPL, ao invés de você utilizar a classe MsExcel, você aciona o comando para abrir o arquivo via ShellExecute, por exemplo:

      ShellExecute("open", cArquivo, "", cDiretorio, 1)
      

      Abraços.

Deixe uma resposta