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:
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:
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:
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):
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.
Ótimo post Daniel, bem explicado, com os exemplos, bem legal mesmo cara. Obrigado por compartilhar! 🙂
George Allan
http://www.userfunction.com.br
Grande George, tudo bem?
Eu que agradeço.
Um grande abraço.
Muito legal a dica, parabéns!
Muito Obrigado Thiago.
Um grande abraço.
Muito Legal!!! Acabei de usar, otimo exemplo.
Boa noite Tiago.
Eu que agradeço.
Um grande abraço.
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
Boa noite Luis, tudo bem?
Não sei te dizer se é possível, mas você poderia tentar usa o LibreOffice via linha de comando para a conversão, eu já fiz o procedimento para converter XLS para DBF (https://terminaldeinformacao.com/2015/12/03/funcao-que-converte-excel-xls-para-dbf-em-advpl/).
Ai você poderia instalar o LibreOffice no servidor, e tentar converter o xml para xls ou para algum outro padrão que o celular consiga abrir.
Abraços.
Obrigado Dan_Atilio,
Vou dar uma estudada e se encontrar algo lhe posto.
Abraços,
Luís Gustavo
Ok Luis.
Um grande abraço.
Qual a diferença entre :
– FWMsExcel
– FWMsExcelEx
?
Nenhuma , ou é sútil ?
Obrigado, ótimos post !
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.
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
Boa noite Erick, tudo bem?
Creio eu que a função não deve ter compatibilidade via Scheduler,
Tente abrir um chamado na matriz e ver se há alguma forma paliativa de gerar.
Abraços.
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
Bom dia Abel, tudo bem?
Ele não está conseguindo chamar a classe para abrir o Excel, tente abrir com ShellExecute.
Nesse link tem um exemplo – https://terminaldeinformacao.com/2017/10/03/funcao-gera-arquivo-excel-atraves-de-uma-query-sql/
Um grande abraço.
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
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.
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?
Obrigado jovem.
Desconheço, o que sei é que via AdvPL, daria para você já mandar os dados finais (sem precisar da Fórmula do Excel).
É possível colocar duas colunas diferentes na mesma planilha?
Exemplo:
Nome | CPF
Joao 9999999999
Codigo | Descrição | Valor
Infelizmente não é possível você colocar 2 tabelas em uma mesma aba, você ou separa em duas abas, ou utiliza outra classe como a zExcelXML – https://terminaldeinformacao.com/portfolio/zexcelxml-integracao-protheus-excel/
Abraços.
Bom Dia, parabéns Atilio.!! use seu exemplo hoje como guia, muito obrigado por compartilhar..!!
Eu que agradeço pelo comentário jovem.
Grande abraço.
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
Boa noite, tudo bem?
Obrigado pelo comentário jovem.
Tente usar a função __CopyFile para fazer as copias (esse link é meio antigo, mas tem alguns exemplos – https://terminaldeinformacao.com/2016/05/10/copiando-arquivos-advpl/ )
Abraços.
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?
Bom dia.
Obrigado pelo feedback.
No caso, você precisa incluir uma coluna, e depois quando for adicionar as linhas, mandar a informação dessa nova coluna.
Inclusive no Autumn Code Maker, é possível fazer isso, veja nesse vídeo, a partir de 1:28 a adição das colunas de uma query: https://www.youtube.com/watch?v=FSSYE1fTwJM
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
Infelizmente não, você teria que fazer uma rotina em AdvPL que gerasse em Excel.
Inclusive, tem uma forma bem rápida e fácil, dê uma olhada nesse vídeo: https://www.youtube.com/watch?v=FSSYE1fTwJM
@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
Bom dia Luis, tudo bem?
Que estranho, olhando por cima, a sintaxe parece correta.
Se possível, nos envie por e-Mail o log completo e o código fonte completo também, ai eu consigo rastrear onde e em que linha deu o erro exato.
Grande abraço.
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;
})
Boa tarde Luis.
Note que na linha que você adiciona o campo F2_EMISSAO, tem duas referências, por exemplo:
QRY->QRY->F2_EMISSAO,;
Quando ao certo, seria apenas 1 referência:
QRY->F2_EMISSAO,;
Grande abraço.
Boa tarde! Conseguiram identificar o problema? Estou com o mesmo erro acontecendo!
Boa tarde Caroline.
Se possível nos envie o error log completo.
Boa tarde, Obrigada pelo retorno. Consegui resolver. Muito Obrigada!
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.
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.
Boa tarde Mauricio, tudo bem?
Se você tiver o modelo do Excel, ai recomendo usar a zExcelXML, nesse link tem um vídeo demonstrativo de como usar: https://terminaldeinformacao.com/portfolio/zexcelxml-integracao-protheus-excel/
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:
Abraços.
Gostei bastente do conteudo e me ajudou muito, porem fiquei com uma duvido, e nao achei nada sobre, alguem sabe me dizer se o metodo SetCelBgColor(), ainda funciona?
Bom dia Kauan.
Sim, mas somente na FWMsExcelEX (acho que não funciona na FWMsExcel nem na FWMsExcelXLSX).
Caso queira, segue link do TDN da FWMsExcelEX: https://tdn.totvs.com/display/public/framework/FWMsExcelEx
Muito obrigado mesmo de coração, era isso mesmo eu estava usando a FWMsExcel, ai não estava dando certo. Sei nem como-lhe agradecer, você já salvou e muito minha pele com os seus posts incríveis.
Opa, por nada Kauan.
Eu que agradeço pelo feedback.
Grande abraço.
Boa tarde!
Os valores ficam no formato texto ( Alltrim(Transform(xTOTAL, “@E 999,999,999.99”)),;) e fica trabalhoso converte em planilhas extensas, tentei utilizar Val(Alltrim(Transform(xTOTAL, “@E 999,999,999.99”))),; mas perdem-se as casas decimais, tem algum sugestão?
abs
Bom dia Altair, tudo bem?
Nos seus AddColumn, no parâmetro nFormat passe como 2 (numérico) ou 3 (monetário). E no nAlign passe 3 (alinhamento a direita).
Os parâmetros do AddColumn são: FWMsExcel():AddColumn(< cWorkSheet >, < cTable >, < cColumn >, < nAlign >, < nFormat >, < lTotal >)
Ai dessa forma, você não precisa usar o Transform, basta adicionar diretamente o seu xTOTAL.
Link de apoio com a documentação: https://tdn.totvs.com/display/public/framework/FWMsExcel
Pessoal, bom dia! Estamos usando o webclient na release 12.1.2210(em substituição ao antigo smatrclient html) e nos relatórios gerados neste formato, dá erro quando tento gerar a planilha. Alguém sabe qual ajuste tem que ser feito? Pergunto pois esta nova versão interage com os componentes do computador, como disco e tal, coisa que não ocorria antes
Bom dia Luiz, tudo joia?
Ainda não pegamos nenhuma situação parecida em nossos clientes. Assim que conseguirmos reproduzir, ai atualizamos aqui o artigo.
Se você encontrar também algo, nos avise para atualizarmos os exemplos.
Um forte abraço.
Boa tarde , eu fiz uma cópia da rotina criei um menu em teste , ele gera o arquivo normal , porém na segunda aba ele não retorna os dados da tabela, poderia me dar uma força nessa questão
Bom dia Leonardo, tudo joia?
Veja se na sua outra tabela, você esta passando o nome da AddWorkSheet e o nome da AddTable corretamente.
Abraços.
Olá boa tarde , ao gerar o relatório ele gera o arquivo porém não carrega os dados da tabela, poderia me auxiliar qual o motivo , lembrando que tanto a minha SB1 quanto a minha SBM está preenchida
Bom dia Leonardo, tudo joia?
Coloque um breakpoint na linha que ele da o AddRow, e veja se ta entrando certinho no comando durante a depuração.
Caso não esteja, pode ser algo no seu laço de repetição.
Um grande abraço.
Olá tento gerar esse fonte , porém ele não retorna nenhum dado das tabelas , poderia me auxiliar o motivo , as tabelas estão populadas.
Bom dia Leonardo, tudo joia?
Faz assim:
1. Crie uma conta grátis no Autumn Code Maker – https://autumncodemaker.com
2. Siga o passo a passo nesse vídeo do YouTube – https://www.youtube.com/watch?v=FSSYE1fTwJM
3. Com isso, ele vai gerar para você um fonte que gera Excel, e aí você usa esse fonte
Abraços.
Olá Dan, acompanho a muito seus artigos e quero parabeniza-lo pela contricuição dada a comunidade. A pergunta é a seguinte: até aqui isso funcionou muito bem, mas percebi que meus relatorio gerados em excel usando essa classe geram erro quando executado no ambiente WEB. Tem alguma solução ou teremos que reescrever o codigo para tReport ou smartviwew por exemplo?
Bom dia Harley, tudo joia?
Primeiramente obrigado pelo contato e feedback.
Para utilização de integrações com o Microsoft Office (seja Word ou Excel), para a versão web do Protheus, tem que ter instalado o WebAgent na estação que está com o Protheus aberto.
Nesse link, no vídeo, veja a Parte 13, 15 e 16: https://terminaldeinformacao.com/2024/11/13/instalacao-do-protheus-12-1-2410-onca-preta-com-webagent-e-webapp-ti-especial-0001/
Tenha uma ótima e abençoada quinta feira.
Um forte abraço.