Tela que gera um gráfico conforme a linha posicionada | Ti Responde 0222

No vídeo de hoje, vamos demonstrar em como criar uma tela que tenha um gráfico que seja atualizado conforme navega nas linhas de um browse.

A dúvida de hoje, nos perguntaram, como criar um gráfico, sendo que ele será atualizado ao navegar nas linhas de um FWBrowse.

 

Pensando nisso, montamos um exemplo, onde vai ser exibido duas grids e uma delas ao navegar nas linhas vai atualizar um gráfico.

 

Segue abaixo o vídeo exemplificando:

 

E abaixo o código fonte desenvolvido:

//Bibliotecas
#Include "tlpp-core.th"
#Include "TOTVS.ch" //por causa da RGB()

//Declaração da namespace
Namespace custom.terminal.youtube

//Constantes
#Define CRLF Chr(13) + Chr(10) //Carriage Return Line Feed

//Armazena o último grupo posicionado
Static cLastGroup := ""

/*/{Protheus.doc} User Function video0222
Grupos de Produtos
@author Atilio
@since 27/05/2025
@version 1.0
@type function
@obs Codigo gerado automaticamente pelo Autumn Code Maker
@see http://autumncodemaker.com
@example custom.terminal.youtube.u_video0222()
/*/

User Function video0222()
	Local aArea           := FWGetArea()                  As Array
	Local aParameters     := {}                           As Array
	Local cFirstId        := Space(TamSX3("BM_GRUPO")[1]) As Character
	Local cLastId         := StrTran(cFirstId, " ", "Z")  As Character
	Local cStockWarehouse := Space(TamSX3("B2_LOCAL")[1]) As Character
	
	//Adicionando os parametros do ParamBox
	aAdd(aParameters, {1, "Grupo De", cFirstId,  "", ".T.", "SBM", ".T.", 80,  .F.})
	aAdd(aParameters, {1, "Grupo Até", cLastId,  "", ".T.", "SBM", ".T.", 80,  .T.})
	aAdd(aParameters, {1, "Armazém", cStockWarehouse,  "", ".T.", "NNR", ".T.", 80,  .T.})
	
	//Se a pergunta for confirma, chama a tela
	If ParamBox(aParameters, 'Informe os parâmetros', /*aRet*/, /*bOk*/, /*aButtons*/, /*lCentered*/, /*nPosx*/, /*nPosy*/, /*oDlgWizard*/, /*cLoad*/, .F., .F.)
		makeDialog()
	EndIf
	
	FWRestArea(aArea)
Return

/*/{Protheus.doc} makeDialog
Monta a tela com a marcação de dados
@author Atilio
@since 27/05/2025
@version 1.0
@type function
@obs Codigo gerado automaticamente pelo Autumn Code Maker
@see http://autumncodemaker.com
/*/

Static Function makeDialog()
    Local aArea               := GetArea()                                          As Array
    //Barra de Botões
    Local bCloseBlock         := {|| oDialogTest:End()}                             As CodeBlock
    Local nWidthButton        := 50                                                 As Numeric
    //Cabeçalho
    Private oSayBigText                                                             As Object
    Private cSayBigText       := 'FAT'                                              As Character
    Private oSayTitle                                                               As Object
    Private cSayTitle         := 'Análise do Armazém ' + MV_PAR03                   As Character
    Private oSaySubtitle                                                            As Object
    Private cSaySubtitle      := 'Listando Grupos e Produtos'                       As Character
    //Janela e componentes
    Private oDialogTest                                                             As Object
    Private oFwLayer                                                                As Object
    Private oPanelTitle                                                             As Object
    Private oPanelButtons                                                           As Object
    Private oPanelGraphic                                                           As Object
    //Grupo de produtos
    Private oPanelGroup                                                             As Object
    Private oBrowseGroup                                                            As Object
    Private cAliasGroup       := GetNextAlias()                                     As Character
    Private aFieldsGroup      := {}                                                 As Array
    Private aColumnsGroup     := {}                                                 As Array
    Private oTempTableGroup   := Nil                                                As Object
    //Produtos e Saldos
    Private oPanelProduct                                                           As Object
    Private oBrowseProduct                                                          As Object
    Private cAliasProduct     := GetNextAlias()                                     As Character
    Private aFieldsProduct    := {}                                                 As Array
    Private aColumnsProduct   := {}                                                 As Array
    Private oTempTableProduct := Nil                                                As Object
    //Fontes
    Private cFont             := 'Tahoma'                                           As Character
    Private oFontBig          := TFont():New(cFont, /*uPar2*/, -38)                 As Object
    Private oFontTitle        := TFont():New(cFont, /*uPar2*/, -20)                 As Object
    Private oFontTitleBold    := TFont():New(cFont, /*uPar2*/, -20, /*uPar4*/, .T.) As Object
    Private oFontDefault      := TFont():New(cFont, /*uPar2*/, -14)                 As Object
    //Tamanho da janela
    Private aDialogSize       := MsAdvSize()                                        As Array
    Private nDialogWidth      := aDialogSize[5]                                     As Numeric
    Private nDialogHeight     := aDialogSize[6]                                     As Numeric
    
    //Adiciona as colunas que serão criadas na temporária
    aAdd(aFieldsGroup, { 'BM_GRUPO', 'C', TamSX3("BM_GRUPO")[1], 0}) //Grupo
    aAdd(aFieldsGroup, { 'BM_DESC',  'C', TamSX3("BM_DESC")[1],  0}) //Descrição

    aAdd(aFieldsProduct, { 'BM_GRUPO', 'C', TamSX3("BM_GRUPO")[1], 0})                    //Grupo
    aAdd(aFieldsProduct, { 'B1_COD',   'C', TamSX3("B1_COD")[1],   0})                    //Produto
    aAdd(aFieldsProduct, { 'B1_DESC',  'C', TamSX3("B1_DESC")[1],  0})                    //Descrição
    aAdd(aFieldsProduct, { 'B1_TIPO',  'C', TamSX3("B1_TIPO")[1],  0})                    //Tipo
    aAdd(aFieldsProduct, { 'B1_UM',    'C', TamSX3("B1_UM")[1],    0})                    //Unid. Med.
    aAdd(aFieldsProduct, { 'B2_QATU',  'N', TamSX3("B2_QATU")[1],  TamSX3("B2_QATU")[2]}) //Saldo

    //Cria a tabela temporária
    oTempTableGroup:= FWTemporaryTable():New(cAliasGroup)
    oTempTableGroup:SetFields( aFieldsGroup )
    oTempTableGroup:AddIndex("1", {"BM_GRUPO"} )
    oTempTableGroup:Create()

    oTempTableProduct:= FWTemporaryTable():New(cAliasProduct)
    oTempTableProduct:SetFields( aFieldsProduct )
    oTempTableProduct:AddIndex("1", {"BM_GRUPO", "B1_COD"} )
    oTempTableProduct:Create()

    //Popula a tabela temporária
    Processa({|| insertInTemporary()}, 'Processando...')

    //Adiciona as colunas que serão exibidas no FWBrowse
    createColumns()
     
    //Criando a janela
    oDialogTest := TDialog():New(0, 0, nDialogHeight, nDialogWidth, 'Tela para Consulta de Dados - Autumn Code Maker', , , , , , /*nCorFundo*/, , , .T.)
        
        //Criando as camadas
        oFwLayer := FwLayer():New()
        oFwLayer:init(oDialogTest,.F.)
        
        //Adicionando 5 linhas
        oFWLayer:addLine('TITULO', 010, .F.)
        oFWLayer:addLine('CABECALHO',  038, .F.)
        oFWLayer:addLine('SEPARACAO', 002, .F.)
        oFWLayer:addLine('PRODUTOS',  048, .F.)
        oFWLayer:addLine('RODAPE', 002, .F.)
        
        //Adicionando as colunas das linhas
        oFWLayer:addCollumn('HEADERTEXT',   050, .T., 'TITULO')
        oFWLayer:addCollumn('BLANK',        020, .T., 'TITULO')
        oFWLayer:addCollumn('BUTTONS',      030, .T., 'TITULO')
        
        oFWLayer:addCollumn('BLANKANTES',   001, .T., 'CABECALHO')
        oFWLayer:addCollumn('GRIDGRUP',     047, .T., 'CABECALHO')
        oFWLayer:addCollumn('BLANKMEIO',    001, .T., 'CABECALHO')
        oFWLayer:addCollumn('GRAFICO',      050, .T., 'CABECALHO')
        oFWLayer:addCollumn('BLANKDEPOIS',  001, .T., 'CABECALHO')

        oFWLayer:addCollumn('BLANKANTES',   001, .T., 'PRODUTOS')
        oFWLayer:addCollumn('GRIDPROD',     098, .T., 'PRODUTOS')
        oFWLayer:addCollumn('BLANKDEPOIS',  001, .T., 'PRODUTOS')
        
        //Criando os paineis
        oPanelHeader   := oFWLayer:GetColPanel('HEADERTEXT', 'TITULO')
        oPanelButtons  := oFWLayer:GetColPanel('BUTTONS',    'TITULO')
        oPanelGroup    := oFWLayer:GetColPanel('GRIDGRUP',   'CABECALHO')
        oPanelGraphic  := oFWLayer:GetColPanel('GRAFICO',    'CABECALHO')
        oPanelProduct  := oFWLayer:GetColPanel('GRIDPROD',   'PRODUTOS')
        
        //Títulos e SubTítulos
        oSayBigText  := TSay():New(004, 003, {|| cSayBigText},  oPanelHeader, '', oFontBig,       , , , .T., RGB(149, 179, 215), , 200, 30, , , , , , .F., , )
        oSayTitle    := TSay():New(004, 045, {|| cSayTitle},    oPanelHeader, '', oFontTitle,     , , , .T., RGB(031, 073, 125), , 200, 30, , , , , , .F., , )
        oSaySubtitle := TSay():New(014, 045, {|| cSaySubtitle}, oPanelHeader, '', oFontTitleBold, , , , .T., RGB(031, 073, 125), , 300, 30, , , , , , .F., , )
        
        //Botões
        oButtonClose := TButton():New(003, 001 + ((nWidthButton+2)*1), 'Fechar',    oPanelButtons, bCloseBlock, nWidthButton, 018, /*uParam8*/, oFontDefault, /*uParam10*/, .T.)
        
        //Dados dos Grupos
        oBrowseGroup := FWBrowse():New()
        oBrowseGroup:DisableFilter()
        oBrowseGroup:DisableConfig()
        oBrowseGroup:DisableReport()
        oBrowseGroup:DisableSeek()
        oBrowseGroup:DisableSaveConfig()
        oBrowseGroup:SetFontBrowse(oFontDefault)
        oBrowseGroup:SetAlias(cAliasGroup)
        oBrowseGroup:SetDataTable()
        oBrowseGroup:SetEditCell(.T., {|| .T.}) 
        oBrowseGroup:lHeaderClick := .F.
        oBrowseGroup:SetColumns(aColumnsGroup)
        oBrowseGroup:SetOwner(oPanelGroup)
        oBrowseGroup:bChange := {|| changeGroup()}
        oBrowseGroup:SetLineHeight(22)
        oBrowseGroup:Activate()

        //Dados dos Produtos
        oBrowseProduct := FWBrowse():New()
        oBrowseProduct:DisableFilter()
        oBrowseProduct:DisableConfig()
        oBrowseProduct:DisableReport()
        oBrowseProduct:DisableSeek()
        oBrowseProduct:DisableSaveConfig()
        oBrowseProduct:SetFontBrowse(oFontDefault)
        oBrowseProduct:SetAlias(cAliasProduct)
        oBrowseProduct:SetDataTable()
        oBrowseProduct:SetEditCell(.T., {|| .T.}) 
        oBrowseProduct:lHeaderClick := .F.
        oBrowseProduct:SetColumns(aColumnsProduct)
        oBrowseProduct:SetOwner(oPanelProduct)
        oBrowseProduct:Activate()
        
    oDialogTest:Activate(/*uParam1*/, /*uParam2*/, /*uParam3*/, .T., /*bValid*/, /*uParam6*/, /*bInit*/)
    
    //Deleta a temporária e desativa a tela de marcação
    oTempTableGroup:Delete()
    oBrowseGroup:DeActivate()

    oTempTableProduct:Delete()
    oBrowseProduct:DeActivate()

    //Limpa o último grupo aberto
    cLastGroup := ""
    
    RestArea(aArea)
Return

/*/{Protheus.doc} insertInTemporary
Executa a query SQL e popula essa informação na tabela temporária usada no browse
@author Atilio
@since 27/05/2025
@version 1.0
@type function
@obs Codigo gerado automaticamente pelo Autumn Code Maker
@see http://autumncodemaker.com
/*/

Static Function insertInTemporary()
    Local cQueryGroup    := '' As Character
    Local cQueryProduct  := '' As Character

    cQueryGroup := " INSERT INTO " + CRLF
    cQueryGroup += "      " + oTempTableGroup:GetRealName() + CRLF
    cQueryGroup += "      (BM_GRUPO, BM_DESC) " + CRLF
    cQueryGroup += " SELECT " + CRLF
    cQueryGroup += " 	    BM_GRUPO, " + CRLF
    cQueryGroup += " 	    BM_DESC " + CRLF
    cQueryGroup += " FROM " + CRLF
    cQueryGroup += " 	    " + RetSQLName("SBM") + " SBM " + CRLF
    cQueryGroup += " 	    INNER JOIN " + RetSQLName("SB1") + " SB1 ON ( " + CRLF
    cQueryGroup += " 	    	B1_FILIAL = '" + FWxFilial("SB1") + "' " + CRLF
    cQueryGroup += " 	    	AND B1_GRUPO = BM_GRUPO " + CRLF
    cQueryGroup += " 	    	AND SB1.D_E_L_E_T_ = ' ' " + CRLF
    cQueryGroup += " 	    ) " + CRLF
    cQueryGroup += " 	    INNER JOIN " + RetSQLName("SB2") + " SB2 ON ( " + CRLF
    cQueryGroup += " 	    	B2_FILIAL = '" + FWxFilial("SB2") + "' " + CRLF
    cQueryGroup += " 	    	AND B2_COD = B1_COD " + CRLF
    cQueryGroup += " 	    	AND B2_LOCAL = '" + MV_PAR03 + "' " + CRLF
    cQueryGroup += " 	    	AND SB2.D_E_L_E_T_ = ' ' " + CRLF
    cQueryGroup += " 	    ) " + CRLF
    cQueryGroup += " WHERE " + CRLF
    cQueryGroup += " 	    BM_FILIAL = '" + FWxFilial("SBM") + "' " + CRLF
    cQueryGroup += " 	    AND BM_GRUPO >= '" + MV_PAR01 + "' " + CRLF
    cQueryGroup += " 	    AND BM_GRUPO <= '" + MV_PAR02 + "' " + CRLF
    cQueryGroup += " 	    AND SBM.D_E_L_E_T_ = ' ' " + CRLF
    cQueryGroup += " GROUP BY " + CRLF
    cQueryGroup += " 	    BM_GRUPO, " + CRLF
    cQueryGroup += " 	    BM_DESC " + CRLF
    cQueryGroup += " ORDER BY " + CRLF
    cQueryGroup += " 	    BM_GRUPO " + CRLF
    u_zExecQry(cQueryGroup)

    cQueryProduct := " INSERT INTO " + CRLF
    cQueryProduct += "      " + oTempTableProduct:GetRealName() + CRLF
    cQueryProduct += "      (BM_GRUPO, B1_COD, B1_DESC, B1_TIPO, B1_UM, B2_QATU) " + CRLF
    cQueryProduct += " SELECT " + CRLF
    cQueryProduct += "      	BM_GRUPO, " + CRLF
    cQueryProduct += "      	B1_COD, " + CRLF
    cQueryProduct += "      	B1_DESC, " + CRLF
    cQueryProduct += "      	B1_TIPO, " + CRLF
    cQueryProduct += "      	B1_UM, " + CRLF
    cQueryProduct += "      	B2_QATU " + CRLF
    cQueryProduct += " FROM " + CRLF
    cQueryProduct += "      	" + RetSQLName("SBM") + " SBM " + CRLF
    cQueryProduct += "      	INNER JOIN " + RetSQLName("SB1") + " SB1 ON ( " + CRLF
    cQueryProduct += "      		B1_FILIAL = '" + FWxFilial("SB1") + "' " + CRLF
    cQueryProduct += "      		AND B1_GRUPO = BM_GRUPO " + CRLF
    cQueryProduct += "      		AND SB1.D_E_L_E_T_ = ' ' " + CRLF
    cQueryProduct += "      	) " + CRLF
    cQueryProduct += "      	INNER JOIN " + RetSQLName("SB2") + " SB2 ON ( " + CRLF
    cQueryProduct += "      		B2_FILIAL = '" + FWxFilial("SB2") + "' " + CRLF
    cQueryProduct += "      		AND B2_COD = B1_COD " + CRLF
    cQueryProduct += "      		AND B2_LOCAL = '" + MV_PAR03 + "' " + CRLF
    cQueryProduct += "      		AND SB2.D_E_L_E_T_ = ' ' " + CRLF
    cQueryProduct += "      	) " + CRLF
    cQueryProduct += " WHERE " + CRLF
    cQueryProduct += "      	BM_FILIAL = '" + FWxFilial("SBM") + "' " + CRLF
    cQueryProduct += " 	    AND BM_GRUPO >= '" + MV_PAR01 + "' " + CRLF
    cQueryProduct += " 	    AND BM_GRUPO <= '" + MV_PAR02 + "' " + CRLF
    cQueryProduct += "      	AND SBM.D_E_L_E_T_ = ' ' " + CRLF
    cQueryProduct += " ORDER BY " + CRLF
    cQueryProduct += "      	B2_QATU DESC " + CRLF
    u_zExecQry(cQueryProduct)

    (cAliasGroup)->(DbGoTop())
    (cAliasProduct)->(DbGoTop())
Return

/*/{Protheus.doc} createColumns
Função que gera as colunas usadas no browse (similar ao antigo aHeader)
@author Atilio
@since 27/05/2025
@version 1.0
@type function
@obs Codigo gerado automaticamente pelo Autumn Code Maker
@see http://autumncodemaker.com
/*/

Static Function createColumns()
    Local nCurrent      := 0  As Numeric
    Local aInfoColumns  := {} As Array
    Local oColumn             As Object
    
    //Adicionando campos que serão mostrados na tela
    //[1] - Campo da Temporaria
    //[2] - Titulo
    //[3] - Tipo
    //[4] - Tamanho
    //[5] - Decimais
    //[6] - Máscara
    //[7] - Editável? .T. = sim, .F. = não
    //[8] - Código da Consulta Padrão
    //[9] - Bloco de Código usado na Validação (ex.: {|| fSuaValid()} )
    aInfoColumns := {}
    aAdd(aInfoColumns, { 'BM_GRUPO', 'Grupo',     'C', TamSX3('BM_GRUPO')[1], 0, '', .F., Nil, Nil})
    aAdd(aInfoColumns, { 'BM_DESC',  'Descrição', 'C', TamSX3('BM_DESC')[1],  0, '', .F., Nil, Nil})

    //Percorrendo todos os campos da estrutura
    For nCurrent := 1 To Len(aInfoColumns)
        //Cria a coluna
        oColumn := FWBrwColumn():New()
        oColumn:SetData(&('{|| ' + cAliasGroup + '->' + aInfoColumns[nCurrent][1] +'}'))
        oColumn:SetTitle(aInfoColumns[nCurrent][2])
        oColumn:SetType(aInfoColumns[nCurrent][3])
        oColumn:SetSize(aInfoColumns[nCurrent][4])
        oColumn:SetDecimal(aInfoColumns[nCurrent][5])
        oColumn:SetPicture(aInfoColumns[nCurrent][6])

        //Muda o alinhamento conforme o tipo, Data será Centralizado
        If aInfoColumns[nCurrent][3] == 'D'
        	oColumn:nAlign := 0
        
        //Numérico, direita
        ElseIf aInfoColumns[nCurrent][3] == 'N'
        	oColumn:nAlign := 2
        
        //Senão, esquerda (caractere)
        Else
        	oColumn:nAlign := 1
        EndIf

        //Se for ser possível ter o duplo clique para editar
        If aInfoColumns[nCurrent][7]
        	oColumn:SetEdit(.T.)
        	oColumn:SetReadVar(cAliasGroup + "->" + aInfoColumns[nCurrent][1])
        	
        	//Se tiver Consulta Padrão
        	If ! Empty(aInfoColumns[nCurrent][8])
        		oColumn:xF3 := aInfoColumns[nCurrent][8]
        	EndIf
        	
        	//Se tiver Validação
        	If ! Empty(aInfoColumns[nCurrent][9])
        		oColumn:SetValid(aInfoColumns[nCurrent][9])
        	EndIf
        EndIf
        
        //Adiciona a coluna
        aAdd(aColumnsGroup, oColumn)
    Next

    //Adicionando campos que serão mostrados na tela
    //[1] - Campo da Temporaria
    //[2] - Titulo
    //[3] - Tipo
    //[4] - Tamanho
    //[5] - Decimais
    //[6] - Máscara
    //[7] - Editável? .T. = sim, .F. = não
    //[8] - Código da Consulta Padrão
    //[9] - Bloco de Código usado na Validação (ex.: {|| fSuaValid()} )
    aInfoColumns := {}
    aAdd(aInfoColumns, { 'B1_COD',   'Produto',    'C', TamSX3('B1_COD')[1] , 0,                    '', .F., Nil, Nil})
    aAdd(aInfoColumns, { 'B1_DESC',  'Descrição',  'C', TamSX3('B1_DESC')[1], 0,                    '', .F., Nil, Nil})
    aAdd(aInfoColumns, { 'B1_TIPO',  'Tipo',       'C', TamSX3('B1_TIPO')[1], 0,                    '', .F., Nil, Nil})
    aAdd(aInfoColumns, { 'B1_UM',    'Unid. Med.', 'C', TamSX3('B1_UM')[1]  , 0,                    '', .F., Nil, Nil})
    aAdd(aInfoColumns, { 'B2_QATU',  'Saldo',      'N', TamSX3('B2_QATU')[1], TamSX3('B2_QATU')[2], PesqPict('SB2', 'B2_QATU'), .F., Nil, Nil})

    //Percorrendo todos os campos da estrutura
    For nCurrent := 1 To Len(aInfoColumns)
        //Cria a coluna
        oColumn := FWBrwColumn():New()
        oColumn:SetData(&('{|| ' + cAliasProduct + '->' + aInfoColumns[nCurrent][1] +'}'))
        oColumn:SetTitle(aInfoColumns[nCurrent][2])
        oColumn:SetType(aInfoColumns[nCurrent][3])
        oColumn:SetSize(aInfoColumns[nCurrent][4])
        oColumn:SetDecimal(aInfoColumns[nCurrent][5])
        oColumn:SetPicture(aInfoColumns[nCurrent][6])

        //Muda o alinhamento conforme o tipo, Data será Centralizado
        If aInfoColumns[nCurrent][3] == 'D'
        	oColumn:nAlign := 0
        
        //Numérico, direita
        ElseIf aInfoColumns[nCurrent][3] == 'N'
        	oColumn:nAlign := 2
        
        //Senão, esquerda (caractere)
        Else
        	oColumn:nAlign := 1
        EndIf

        //Se for ser possível ter o duplo clique para editar
        If aInfoColumns[nCurrent][7]
        	oColumn:SetEdit(.T.)
        	oColumn:SetReadVar(cAliasProduct + "->" + aInfoColumns[nCurrent][1])
        	
        	//Se tiver Consulta Padrão
        	If ! Empty(aInfoColumns[nCurrent][8])
        		oColumn:xF3 := aInfoColumns[nCurrent][8]
        	EndIf
        	
        	//Se tiver Validação
        	If ! Empty(aInfoColumns[nCurrent][9])
        		oColumn:SetValid(aInfoColumns[nCurrent][9])
        	EndIf
        EndIf
        
        //Adiciona a coluna
        aAdd(aColumnsProduct, oColumn)
    Next
Return

Static Function changeGroup()
    Local cGroupId         := (cAliasGroup)->BM_GRUPO
    Local cFilterProduct   := cAliasProduct + "->BM_GRUPO == '" + cGroupId + "'"

    //Aplica o filtro no alias de produtos
    (cAliasProduct)->(DbClearFilter())
    (cAliasProduct)->(DbSetFilter({|| &(cFilterProduct)}, cFilterProduct))
    (cAliasProduct)->(DbGoTop())

    //Atualiza a grid
    If Type("oBrowseProduct") != "U"
        oBrowseProduct:Refresh(.T.)
    EndIf

    createGraph()
Return

Static Function createGraph()
    Local cGraphTitle := "" As Character

    If cLastGroup != (cAliasGroup)->BM_GRUPO
        cGraphTitle := Alltrim((cAliasGroup)->BM_DESC)

        //Instância a classe
        oFWChart := FWChartFactory():New()
        oFWChart := oFWChart:getInstance(PIECHART)
            
        //Inicializa pertencendo a janela
        oFWChart:Init(oPanelGraphic, .T., .T. )
        
        //Seta o título do gráfico
        oFWChart:SetTitle(cGraphTitle, CONTROL_ALIGN_CENTER)
        
        //Adiciona a comparação dos gráficos
        While ! (cAliasProduct)->(EoF())
            oFWChart:addSerie((cAliasProduct)->B1_DESC, (cAliasProduct)->B2_QATU)
            (cAliasProduct)->(DbSkip())
        EndDo
        (cAliasProduct)->(DbGoTop())
        
        //Define que a legenda será mostrada na esquerda
        oFWChart:setLegend( CONTROL_ALIGN_BOTTOM )
            
        //Seta a máscara mostrada
        oFWChart:cPicture := PesqPict('SB2', 'B2_QATU')
            
        //Seta as cores utilizadas como aleatórias
        oFWChart:oFWChartColor:SetColor('Random')
            
        //Constrói o gráfico
        oFWChart:Build()
        cLastGroup := (cAliasGroup)->BM_GRUPO

    EndIf
Return

Bom pessoal, por hoje é só.

 

Abraços e até a próxima.

Dan (Daniel Atilio)
Cristão de ramificação protestante. Especialista em Engenharia de Software pela FIB, graduado em Banco de Dados pela FATEC Bauru e técnico em informática pelo CTI da Unesp. Entusiasta de soluções Open Source e blogueiro nas horas vagas. Autor e mantenedor do portal Terminal de Informação.

Deixe uma resposta

Terminal de Informação