Função para otimizar a busca de dados da SX3 (para substituir a OpenSXS)

No artigo de hoje vou mostrar uma função desenvolvida para otimizar a busca de dados da SX3 para enviar os fontes no Code Analysis.

Se você já precisou atender algum cliente e mexer com o Code Analysis, sabe que em muitos fontes antigos, analistas geralmente percorriam a sx3 para montar dados de um aHeader.

Pois bem, até podemos usar a função OpenSXs para abrir a SX3, mas a performance dela deixa a desejar, então como podemos solucionar isso?

Podemos chamar a GetSX3Cache dos campos necessários, e pensando nisso, criei uma função chamada zX3ToArr, então a título de curiosidade, olha como estava antes a montagem de um aHeader em um fonte bem antigo:

cAlias := "SZA"

//Cria vetor aHeader
dbSelectArea("SX3")
dbSetOrder(1)
dbSeek(cAlias)
aHeader := {}

While !SX3->(EOF()) .And. SX3->X3_Arquivo == cAlias
	  AAdd(aHeader, {SX3->X3_Titulo,;
					 SX3->X3_Campo       ,;
					 SX3->X3_Picture     ,;
					 SX3->X3_Tamanho     ,;
					 SX3->X3_Decimal     ,;
					 SX3->X3_Valid       ,;
					 SX3->X3_Usado       ,;
					 SX3->X3_Tipo        ,;
					 SX3->X3_Arquivo     ,;
					 SX3->X3_Context})

   SX3->(dbSkip())
EndDo

Agora com a função nova, veja como fica:

aStruct := SZA->(DbStruct())
aHeader := {}

//Percorre todos os campos da estrutura da tabela
For nAtual := 1 To Len(aStruct)
	//Chama a função que adiciona ao array via @, conforme o campo atual, e o tipo é 4 que será usado em um MsNewGetDados
	u_zX3ToArr(@aHeader, aStruct[nAtual][1], 4)
Next

Abaixo o fonte completo da função zX3ToArr:

//Bibliotecas
#Include "TOTVS.ch"

/*/{Protheus.doc} User Function zX3ToArr
Função que exporta a SX3 adicionando uma linha no array
@type  Function
@author Atilio
@since 10/06/2021
@version version
@param aArray, Array, Variável do Array que terá o conteúdo adicionado (deve ser passado com @)
@param cCampo, Caractere, Nome do campo a ser verificado na SX3
@param nTipo, Numeric, Tipo do array
@param cTituloDef, Caractere, Título default da coluna a ser considerado no lugar do X3_TITULO
@param cCampoDef, Caractere, Nome do campo que será usado no array (para MsNewGetDados)
@param cBlocoDef, Caractere, Texto do bloco de código que será adicionado no array (para FWBrwColumn)
@param cAliasDef, Caractere, Alias Default usado em FWMarkBrowse no método SetFields
@obs Tipos do nTipo:
    1 = Campos para FWTemporaryTable
    2 = Campos para um aHeader de um FWMarkBrowse
    3 = Campos para aSeek FWMarkBrowse
    4 = Campos para um aHeader de um MsNewGetDados
    5 = Campos para um aHeader composto de FWBrwColumn, porém para usar em um FWFormBrowse
    6 = Campos para filtro de SetFieldFilter em um FWFormBrowse
    7 = Campos para definição de um FWMarkBrowse (método SetFields)
/*/

User Function zX3ToArr(aArray, cCampo, nTipo, cTituloDef, cCampoDef, cBlocoDef, cAliasDef)
    Local aArea        := GetArea()
    Local cFieldX3     := ""
    Local cTipoX3      := ""
    Local cTitX3       := ""
    Local cPictX3      := ""
    Local cCBoxX3      := ""
    Local cF3X3        := ""
    Local cValidX3     := ""
    Local cUsadoX3     := ""
    Local cRelacaoX3   := ""
	Local aTamX3       := {}
    Local nTamArr      := 0
    Local cAliasTab    := ""
    Default aArray     := {}
    Default cCampo     := ""
    Default nTipo      := 0
    Default cTituloDef := ""
    Default cCampoDef  := ""
    Default cBlocoDef  := ""
    Default cAliasDef  := ""

    //Se tiver campo preenchido
    If ! Empty(cCampo)
        cFieldX3 := GetSX3Cache(cCampo, "X3_CAMPO")

        //Se o campo for encontrado na SX3
        If ! Empty(cFieldX3)
            nTamArr    := Len(aArray) + 1
            cAliasTab  := AliasCPO(cFieldX3)
            cTipoX3    := GetSX3Cache(cFieldX3, "X3_TIPO")
            aTamX3     := TamSX3(cFieldX3)
            cTitX3     := Iif(Empty(cTituloDef), GetSX3Cache(cFieldX3, "X3_TITULO"), cTituloDef)
            cPictX3    := PesqPict(cAliasTab, cFieldX3)
            cCBoxX3    := GetSX3Cache(cFieldX3, "X3_CBOX")
            cF3X3      := GetSX3Cache(cFieldX3, "X3_F3")
            cValidX3   := GetSX3Cache(cFieldX3, "X3_VALID")
            cUsadoX3   := GetSX3Cache(cFieldX3, "X3_USADO")
            cRelacaoX3 := GetSX3Cache(cFieldX3, "X3_RELACAO")

            //Para montar a Struct de uma FWTemporaryTable
            If nTipo == 1
                aAdd(aArray, {;
                    Iif(Empty(cCampoDef), cCampo, cCampoDef),;
                    cTipoX3,;
                    aTamX3[1],;
                    aTamX3[2];
                })

            //Para montar o aHeader de telas com Browse (FWMarkBrowse)
            ElseIf nTipo == 2
                aAdd(aArray, {;
                    Iif(Empty(cCampoDef), cCampo, cCampoDef),; 
                    cTitX3,;
                    nTamArr,;
                    cPictX3,;
                    1,;
                    aTamX3[1],;
                    aTamX3[2],;
                    cCBoxX3;
                })

            //Para montar o aSeek em telas com Pesquisa no Browse
            ElseIf nTipo == 3
                aAdd(aArray, { cTitX3, ;
                    { { "",;
                        cTipoX3,;
                        aTamX3[1],;
                        aTamX3[2],;
                        cTitX3,;
                        cPictX3;
                    } };
                })

            //Para montar o aHeader de telas com Browse (MsNewGetDados)
            ElseIf nTipo == 4
                aAdd(aArray, {;
                    cTitX3,;
                    Iif(Empty(cCampoDef), cCampo, cCampoDef),;
                    cPictX3,;
                    aTamX3[1],;
                    aTamX3[2],;
                    cValidX3,;
                    cUsadoX3,;
                    cTipoX3,;
                    cF3X3,;
                    cRelacaoX3,;
                    cCBoxX3;
                })

            //Para montar o aHeader de telas com FWBrwColumn (FWFormBrowse)
            ElseIf nTipo == 5
                aAdd(aArray, FWBrwColumn():New())
                nTamArr := Len(aArray)

                aArray[nTamArr]:SetType(cTipoX3)
                aArray[nTamArr]:SetTitle(cTitX3)
                aArray[nTamArr]:SetSize(aTamX3[1])
                aArray[nTamArr]:SetPicture(cPictX3)
                aArray[nTamArr]:SetDecimal(aTamX3[2])
                aArray[nTamArr]:SetData(&(cBlocoDef))

            //Para utilizar o método SetFieldFilter (FWFormBrowse)
            ElseIf nTipo == 6
                aAdd(aArray, {;
                    cCampo,;
                    cTitX3,;
                    cTipoX3,;
                    aTamX3[1],;
                    aTamX3[2],;
                    cPictX3;
                })

            //Para utilizar o método SetFields (FWMarkBrowse)
            ElseIf nTipo == 7
                aAdd(aArray, {;
                    cTitX3,;
                    &("{|| " + Iif(! Empty(cAliasDef), "(" + cAliasDef + ")->", "") + cCampo + "}"),;
                    cTipoX3,;
                    cPictX3,;
                    1,;
                    aTamX3[1],;
                    aTamX3[2],;
                    .F.,;
                    ,;
                    ,;
                    ,;
                    ,;
                    ,;
                    ,;
                    ,;
                    1;
                })
            EndIf

        EndIf
    EndIf

    RestArea(aArea)
Return

Obs.: O ideal é migrar as funções antigas, por exemplo, de MsNewGetDados para grids mais novas como FWBrowse e MVC, porém se tiver pouco tempo no projeto, ou até nas grids mais novas usar a SX3 para montar as informações, ai você pode adaptar a função acima

Bom pessoal, por hoje é só.

Abraços e até a próxima.

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

Deixe uma resposta