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.
Daniel, sabe alguma forma pratica por query, para me dar uma lista de campos que são obrigatorios em tabelas, ou algum relatorio?
Bom dia Lucas, tudo joia?
Query eu desconheço, conheço apenas a função CpoObrigat ( https://terminaldeinformacao.com/2023/11/13/validando-se-um-campo-e-obrigatorio-com-a-funcao-cpoobrigat-maratona-advpl-e-tl-097/ ), que ela recebe o nome do campo e retorna se ele é obrigatório ou não.
Ai o que você poderia fazer, é:
1. Faz uma query na SX3 buscando os campos de uma tabela ou usa a DbStruct se for só de um alias
2. Percorre esses campos, e para cada um, você aciona a CpoObrigat
3. Ai você pega essa informação e utiliza no seu relatório
Um grande abraço.