FWBrowse com Array e atualizar por TTimer

Robson,

Eu tive alguns erros quando executei o POC, porém corrigindo os mesmos, o browse foi atualizado corretamente conforme a execução do TTimer.

Abaixo o seu POC com as correções que fiz para deixar de gerar error.log, remoção das variáveis private, tipagem das variáveis e criação dos cabeçalhos.


#include "protheus.ch"

//----------------------------------------------------------------------
/*/{Protheus.doc} Gerenciador
Exemplo de browse de array que atualiza os registros com TTimer

@sample U_Gerenciador()
@author Robson Gonçalves
@since 13/11/2020
@version 1.0
/*/
//----------------------------------------------------------------------
user function Gerenciador()
    local bSair as block
    local nHeight as numeric
    local nWidth as numeric
    local oArea as object
    local oBtn1 as object
    local oBtn2 as object
    local oBtn3 as object
    local oBtn4 as object
    local oBtn5 as object
    local oBtn6 as object
    local oBtn7 as object
    local oCenterPanel as object
    local oDlg as object
    local oLayout as object
    local oPanel as object
    local oOption as object
    local oSide as object
    local aHeader as array
    local nCateg as numeric
    local aList as array
    local oBrowse as object

    nCateg := 1
    aHeader := {'Coluna 1','Coluna 2','Coluna 3','Coluna 4','Coluna 5','Coluna 6','Coluna 7','Coluna 8','Coluna 9','Coluna 10','Coluna 11','Coluna 12'}
    bSair := {|| Iif(MsgYesNo('Deseja realmente sair do gerenciamento?','Gerenciamento'),(oDlg:End()),NIL)}

    oMainWnd:ReadClientCoors()

    nHeight := oMainWnd:nHeight-50
    nWidth  := oMainWnd:nWidth-15

    DEFINE MSDIALOG oDlg FROM 0,0 TO nHeight,nWidth TITLE "" PIXEL STYLE nOR(WS_VISIBLE,WS_POPUP)

    oPanel := TPanel():New(0,0,,oDlg,,,,,,15,0,.F.,.F.)
    oPanel:Align := CONTROL_ALIGN_ALLCLIENT

    oArea := FWArea():New(000,000,nHeight/2,nWidth,oPanel,0)
    oArea:CreateBorder(2)

    oArea:AddSideBar ( 12, 1, "oSide" )
    oSide := oArea:GetSideBar("oSide")

    oArea:AddWindow ( 100, 100, "cId1" ,"Ações", 3 , 2,oSide, CONTROL_ALIGN_TOP )
    oArea:AddPanel(100,100,"oOption")
    oOption := oArea:GetPanel("oOption")

    oBtn1 := TButton():New( 1,202,'Opção 1' ,oOption, bSair,35 ,15 ,,,.F. ,.T. ,.F. ,,.F. ,,,.F. )
    oBtn1:Align := CONTROL_ALIGN_TOP

    oBtn2 := TButton():New( 1,202,'Opção 2' ,oOption, bSair,35 ,15 ,,,.F. ,.T. ,.F. ,,.F. ,,,.F. )
    oBtn2:Align := CONTROL_ALIGN_TOP

    oBtn3 := TButton():New( 1,202,'Opção 3' ,oOption, bSair,35 ,15 ,,,.F. ,.T. ,.F. ,,.F. ,,,.F. )
    oBtn3:Align := CONTROL_ALIGN_TOP

    oBtn4 := TButton():New( 1,202,'Opção 4' ,oOption, bSair,35 ,15 ,,,.F. ,.T. ,.F. ,,.F. ,,,.F. )
    oBtn4:Align := CONTROL_ALIGN_TOP

    oBtn5 := TButton():New( 1,202,'Opção 5' ,oOption, bSair,35 ,15 ,,,.F. ,.T. ,.F. ,,.F. ,,,.F. )
    oBtn5:Align := CONTROL_ALIGN_TOP

    oBtn6 := TButton():New( 1,202,'Opção 6' ,oOption, bSair,35 ,15 ,,,.F. ,.T. ,.F. ,,.F. ,,,.F. )
    oBtn6:Align := CONTROL_ALIGN_TOP

    oBtn7 := TButton():New( 1,202,'Sair'    ,oOption, bSair,35 ,15 ,,,.F. ,.T. ,.F. ,,.F. ,,,.F. )
    oBtn7:Align := CONTROL_ALIGN_BOTTOM

    oArea:AddLayout ( "Default" )
    oLayout := oArea:GetLayout ( "Default" )

    oArea:AddWindow ( 100, 100, "cId2","Posicionamento", 3 , 3,oLayout, CONTROL_ALIGN_TOP )
    oArea:AddPanel(100,100,"oCenterPanel")
    oCenterPanel := oArea:GetPanel("oCenterPanel")

    MontaBrw(@oCenterPanel, aHeader, @oBrowse, @aList)

    DEFINE TIMER oTimer INTERVAL 4000 ACTION (UpdSetArray(oBrowse, @nCateg, @aList)) OF GetWndDefault()    
    oTimer:Activate()    

    ACTIVATE MSDIALOG oDlg CENTERED
return

//----------------------------------------------------------------------
/*/{Protheus.doc} MontaBrw
Cria e ativa o browse (FWBrowse) com suas respectivas colunas

@param oObjFather Objeto owner do browse
@param aHeader Array contendo as informações das colunas do browse
@param oBrowse Objeto do browse
@param aList Array que corresponde as linhas do browse

@author Robson Gonçalves
@since 13/11/2020
@version 1.0
/*/
//----------------------------------------------------------------------
static function MontaBrw(oObjFather, aHeader, oBrowse, aList)
    local aFields as array
    local nI as numeric
    local oColumn as object

    if oBrowse != nil
        oBrowse:DeActivate()
    endif

    aFields := {}

    Aadd( aFields, { "Coluna 1","Coluna 1","C",2,0,""} )
    Aadd( aFields, { "Coluna 2","Coluna 2","C",40,0,""} )

    aList := {}

    for nI := 1 to 20
        AAdd(aList,{LTrim(StrZero(nI,2)),'ADULTO '+Chr(64+nI),'0','1','2','0','1','2','0','1','2',''})
    next

    oBrowse := FwBrowse():New()
    oBrowse:SetOwner(oObjFather)
    oBrowse:SetDataArray()
    oBrowse:SetArray(aList)
    oBrowse:SetFieldFilter(aFields)
    oBrowse:SetUseFilter()

    oBrowse:DisableSeek()
    oBrowse:DisableReport()
    oBrowse:DisableConfig()
    oBrowse:DisableLocate()

    oColumn := FWBrwColumn():New()
    oColumn:SetData( &(" { || aList[oBrowse:At(),1]}"))
    oColumn:SetTitle(aHeader[1])
    oColumn:SetSize(2)
    oBrowse:SetColumns({oColumn})

    oColumn := FWBrwColumn():New()
    oColumn:SetData( &(" { || aList[oBrowse:At(),2]}"))
    oColumn:SetTitle(aHeader[2])
    oColumn:SetSize(40)
    oBrowse:SetColumns({oColumn})

    oBrowse:AddStatusColumns({|| Status(aList[oBrowse:nAt,3])}, {|| Legend()})
    oBrowse:aColumns[3]:cTitle := aHeader[3]
    oBrowse:AddStatusColumns({|| Status(aList[oBrowse:nAt,4])}, {|| Legend()})
    oBrowse:aColumns[4]:cTitle := aHeader[4]
    oBrowse:AddStatusColumns({|| Status(aList[oBrowse:nAt,5])}, {|| Legend()})
    oBrowse:aColumns[5]:cTitle := aHeader[5]
    oBrowse:AddStatusColumns({|| Status(aList[oBrowse:nAt,6])}, {|| Legend()})
    oBrowse:aColumns[6]:cTitle := aHeader[6]
    oBrowse:AddStatusColumns({|| Status(aList[oBrowse:nAt,7])}, {|| Legend()})
    oBrowse:aColumns[7]:cTitle := aHeader[7]
    oBrowse:AddStatusColumns({|| Status(aList[oBrowse:nAt,8])}, {|| Legend()})
    oBrowse:aColumns[8]:cTitle := aHeader[8]
    oBrowse:AddStatusColumns({|| Status(aList[oBrowse:nAt,9])}, {|| Legend()})
    oBrowse:aColumns[9]:cTitle := aHeader[9]
    oBrowse:AddStatusColumns({|| Status(aList[oBrowse:nAt,10])}, {|| Legend()})
    oBrowse:aColumns[10]:cTitle := aHeader[10]
    oBrowse:AddStatusColumns({|| Status(aList[oBrowse:nAt,11])}, {|| Legend()})
    oBrowse:aColumns[11]:cTitle := aHeader[11]

    oColumn := FWBrwColumn():New()
    oColumn:SetData( &(" { || aList[oBrowse:At(),12]}"))
    oColumn:SetTitle(aHeader[12])
    oColumn:SetSize(2)
    oBrowse:SetColumns({oColumn})

    oBrowse:Activate()
return

//----------------------------------------------------------------------
/*/{Protheus.doc} UpdSetArray
Atualiza as linhas do browse conforme o TTimer é executado

@param oBrowse Objeto do browse
@param nCateg Inteiro que indica a categoria que será utilizada
@param aList Array que corresponde as linhas do browse

@author Robson Gonçalves
@since 13/11/2020
@version 1.0
/*/
//----------------------------------------------------------------------
static function UpdSetArray(oBrowse, nCateg, aList)
    local aCateg as array
    local nI as numeric
    local aNewList as array

    nCateg++
    aCateg := {'ADULTO ','INFANTIL ', 'JUNIOR ', 'EXPERT '}

    if nCateg > Len(aCateg)
        nCateg := 1
    endif

    aNewList := {}

    for nI := 1 to 20
        AAdd(aNewList,{LTrim(StrZero(nI,2)),aCateg[nCateg]+Chr(64+nI),'0','1','2','0','1','2','0','1','2',''})
    next

    aSize(aList, 0)
    aList := nil

    aList := aNewList

    oBrowse:SetDataArray()
    oBrowse:SetArray(aList)
    oBrowse:Refresh()
    oBrowse:GoTop()
return

//----------------------------------------------------------------------
/*/{Protheus.doc} Legend
Exibe as legendas do browse

@author Robson Gonçalves
@since 13/11/2020
@version 1.0
/*/
//----------------------------------------------------------------------
static function Legend()
    local oLegend as object

    oLegend := FWLegend():New()
    oLegend:Add('','BR_VERDE'    ,'Realizado' )
    oLegend:Add('','BR_VERMELHO','A realizar' )
    oLegend:Activate()
    oLegend:View()
    oLegend:DeActivate()

    FreeObj(oLegend)

    oLegend := nil
return

//----------------------------------------------------------------------
/*/{Protheus.doc} Status
Retorna a imagem do browse (resource) conforme a situação recebida

@param cSit String contendo o código da situação

@return cStatus String contendo o nome do resource

@author Robson Gonçalves
@since 13/11/2020
@version 1.0
/*/
//----------------------------------------------------------------------
static function Status(cSit)
    local cStatus as char

    cStatus := ''

    if cSit == '1'
        cStatus := 'BR_BRANCO'
    elseif cSit == '2'
        cStatus := 'BR_VERDE'
    endif

return cStatus