Olá pessoal…
Hoje vou mostrar um exemplo de função para editar os usuários contidos em um parâmetro na SX6 via AdvPL.
Imagine que você colocou alguns usuários em um parâmetro do sistema (por exemplo, MV_X_USERS), e precisa dar manutenção sempre, para isso criei uma rotina com marcação, para você selecionar os usuários que irão compor o parâmetro.
Abaixo um print da rotina.
Abaixo a função desenvolvida:
//Bibliotecas
#Include "Protheus.ch"
//Constantes
#Define POS_CODIGO 001 //Linha 1
#Define POS_NOME 002 //Linha 1
#Define POS_NOMCOM 004 //Linha 1
#Define POS_FILIAL 006 //Linha 2
/*/{Protheus.doc} zMVUsers
Função para editar o MV_USERS
@author Atilio
@since 16/05/2016
@version 1.0
@example
u_zMVUsers()
/*/
User Function zMVUsers()
u_zParUsr("MV_X_USERS", ";", .T.)
Return
/*/{Protheus.doc} zParUsr
Usuários contidos em um parâmetro
@author Atilio
@since 16/05/2016
@version 1.0
@param cParam, Caracter, Códigos dos usuários contidos no parâmetro
@param cCarSep, Caracter, Caracter de separação
@param lUsrFil, Lógico, Define se trará apenas os usuários que tem acesso a filial logada
@example
u_zParUsr("MV_X_USERS", ";", .T.)
/*/
User Function zParUsr(cParam, cCarSep, lUsrFil)
Local aArea := GetArea()
Local nTamBtn := 50
Local lEditM := .F.
Default cCarSep := ";"
Default lUsrFil := .F.
Private lUsrFilM := lUsrFil
Private nTamFim := 0
Private cParamPvt := ""
Private aUsers := {}
//MsSelect
Private oMAux
Private cArqs
Private cMarca := "OK"
Private aStrut := {}
Private aHeadRegs := {}
Private cAliasTmp := "USR_"+RetCodUsr()
//Tamanho da janela
Private nJanLarg := 0800
Private nJanAltu := 0500
//Gets e Dialog
Private oDlgMark
Private oGetPesq, cGetPesq := Space(100)
Private oGetReto, cGetReto := ""
//Se o parâmetro estiver em branco, finaliza a rotina
If Empty(cParam)
MsgStop("Parâmetro em branco!", "Atenção")
Return
EndIf
//Pegando o tamanho final
DbSelectArea("SX6")
nTamFim := Len(SX6->X6_CONTEUD)
//Pegando o conteúdo
cGetReto := GetMV(cParam)
cParamPvt := cParam
//Pegando os usuários
aUsers := AllUsers()
//Criando a estrutura para a MsSelect
fCriaMsSel()
//Criando a janela
DEFINE MSDIALOG oDlgMark TITLE "Consulta de Usuários ("+cParam+")" FROM 000, 000 TO nJanAltu, nJanLarg COLORS 0, 16777215 PIXEL
//Pesquisar
@ 003, 003 GROUP oGrpPesqui TO 025, (nJanLarg/2)-3 PROMPT "Pesquisar: " OF oDlgMark COLOR 0, 16777215 PIXEL
@ 010, 006 MSGET oGetPesq VAR cGetPesq SIZE (nJanLarg/2)-12, 010 OF oDlgMark COLORS 0, 16777215 VALID (fVldPesq()) PIXEL
//Dados
@ 028, 003 GROUP oGrpDados TO (nJanAltu/2)-28, (nJanLarg/2)-3 PROMPT "Dados: " OF oDlgMark COLOR 0, 16777215 PIXEL
oMAux := MsSelect():New( cAliasTmp, "XX_OK",, aHeadRegs,, cMarca, { 035, 006, (nJanAltu/2)-28-028, (nJanLarg/2)-6 } ,,, )
oMAux:bAval := { || ( fGetMkA( cMarca ), oMAux:oBrowse:Refresh() ) }
oMAux:oBrowse:lHasMark := .T.
oMAux:oBrowse:lCanAllMark := .F.
@ (nJanAltu/2)-28-025, 006 SAY oSayReto PROMPT "Usuários:" SIZE 040, 007 OF oDlgMark COLORS RGB(0,0,0) PIXEL
@ (nJanAltu/2)-28-015, 006 MSGET oGetReto VAR cGetReto SIZE (nJanLarg/2)-12, 010 OF oDlgMark COLORS 0, 16777215 PIXEL
//Populando os dados da MsSelect
fPopula()
//Ações
@ (nJanAltu/2)-25, 003 GROUP oGrpAcoes TO (nJanAltu/2)-3, (nJanLarg/2)-3 PROMPT "Ações: " OF oDlgMark COLOR 0, 16777215 PIXEL
@ (nJanAltu/2)-19, (nJanLarg/2)-((nTamBtn*1)+06) BUTTON oBtnConf PROMPT "Confirmar" SIZE nTamBtn, 013 OF oDlgMark ACTION(fConfirm()) PIXEL
@ (nJanAltu/2)-19, (nJanLarg/2)-((nTamBtn*2)+09) BUTTON oBtnLimp PROMPT "Limpar" SIZE nTamBtn, 013 OF oDlgMark ACTION(fLimpar()) PIXEL
@ (nJanAltu/2)-19, (nJanLarg/2)-((nTamBtn*3)+12) BUTTON oBtnCanc PROMPT "Cancelar" SIZE nTamBtn, 013 OF oDlgMark ACTION(fCancela()) PIXEL
//Se não for editável, desabilita o get de retorno
If ! lEditM
oGetReto:lReadOnly := .T.
EndIf
oMAux:oBrowse:SetFocus()
//Ativando a janela
ACTIVATE MSDIALOG oDlgMark CENTERED
RestArea(aArea)
Return
/*---------------------------------------------------------------------*
| Func: fCriaMsSel |
| Autor: Daniel Atilio |
| Data: 16/05/2016 |
| Desc: Função para criar a estrutura da MsSelect |
*---------------------------------------------------------------------*/
Static Function fCriaMsSel()
Local aAreaX3 := SX3->(GetArea())
//Zerando o cabeçalho e a estrutura
aHeadRegs := {}
aStrut := {}
//Adicionando coluna de OK
// Campo Titulo Mascara
aAdd( aHeadRegs, { "XX_OK", , " ", "" } )
aAdd( aHeadRegs, { "XX_CODIGO", , "Código", "@!" } )
aAdd( aHeadRegs, { "XX_NOME", , "Nome", "@!" } )
aAdd( aHeadRegs, { "XX_NOMCOM", , "Nome Completo", "@!" } )
// Campo Tipo Tamanho Decimal
aAdd( aStrut, { "XX_OK", "C", 002, 0} )
aAdd( aStrut, { "XX_CODIGO", "C", Len(aUsers[1][1][POS_CODIGO]), 0} )
aAdd( aStrut, { "XX_NOME", "C", Len(aUsers[1][1][POS_NOME]), 0} )
aAdd( aStrut, { "XX_NOMCOM", "C", Len(aUsers[1][1][POS_NOMCOM]), 0} )
//Excluindo dados da tabela temporária, se tiver aberta, fecha a tabela
If Select(cAliasTmp)>0
(cAliasTmp)->(DbCloseArea())
EndIf
fErase(cAliasTmp+".DBF")
//Criando tabela temporária
cArqs:= CriaTrab( aStrut, .T. )
dbUseArea( .T.,"DBFCDX", cArqs, cAliasTmp, .T., .F. )
RestArea(aAreaX3)
Return
/*---------------------------------------------------------------------*
| Func: fPopula |
| Autor: Daniel Atilio |
| Data: 16/05/2016 |
| Desc: Função que popula a tabela auxiliar da MsSelect |
*---------------------------------------------------------------------*/
Static Function fPopula()
Local nAtu
Local nFilAux
Local aFilAux
Local lContinua
//Excluindo dados da tabela temporária, se tiver aberta, fecha a tabela
If Select(cAliasTmp)>0
(cAliasTmp)->(DbCloseArea())
EndIf
fErase(cAliasTmp+".DBF")
//Criando tabela temporária
cArqs:= CriaTrab( aStrut, .T. )
dbUseArea( .T.,"DBFCDX", cArqs, cAliasTmp, .T., .F. )
//Percorrendo as filiais listadas
For nAtu := 1 To Len(aUsers)
//Se filtrar filial e o usuário não for o Administrador
If lUsrFilM .And. aUsers[nAtu][1][POS_CODIGO] != "000000"
aFilAux := aUsers[nAtu][2][POS_FILIAL]
lContinua := .F.
//Percorrendo as filiais
For nFilAux := 1 To Len(aFilAux)
//Se tiver acesso a filial atual
If aFilAux[nFilAux] == cEmpAnt+cFilAnt
lContinua := .T.
EndIf
Next
//Caso não tenha acesso a filial
If !lContinua
Loop
EndIf
EndIf
//Se tiver pesquisa
If !Empty(cGetPesq)
//Se não bater a pesquisa, pula o registro
If !( Alltrim(Upper(cGetPesq)) $ Upper(aUsers[nAtu][1][POS_CODIGO]) .Or.;
Alltrim(Upper(cGetPesq)) $ Upper(aUsers[nAtu][1][POS_NOME]) .Or.;
Alltrim(Upper(cGetPesq)) $ Upper(aUsers[nAtu][1][POS_NOMCOM]))
Loop
EndIf
EndIf
cOk := Space(Len(cMarca))
//Se já existir no retorno, será Ok
If Alltrim(aUsers[nAtu][1][POS_CODIGO]) $ cGetReto
cOk := cMarca
EndIf
//Gravando registro
RecLock(cAliasTmp, .T.)
XX_OK := cOK
XX_CODIGO := aUsers[nAtu][1][POS_CODIGO]
XX_NOME := aUsers[nAtu][1][POS_NOME]
XX_NOMCOM := aUsers[nAtu][1][POS_NOMCOM]
(cAliasTmp)->(MsUnlock())
Next
//Posiciona no topo e atualiza grid
(cAliasTmp)->(DbGoTop())
oMAux:oBrowse:Refresh()
Return
/*---------------------------------------------------------------------*
| Func: fConfirm |
| Autor: Daniel Atilio |
| Data: 16/05/2016 |
| Desc: Função de confirmação da rotina |
*---------------------------------------------------------------------*/
Static Function fConfirm()
PutMv(cParamPvt, cGetReto)
oDlgMark:End()
Return
/*---------------------------------------------------------------------*
| Func: fLimpar |
| Autor: Daniel Atilio |
| Data: 16/05/2016 |
| Desc: Função que limpa os dados da rotina |
*---------------------------------------------------------------------*/
Static Function fLimpar()
//Zerando gets
cGetPesq := Space(100)
cGetReto := Space(nTamFim)
oGetPesq:Refresh()
oGetReto:Refresh()
//Atualiza grid
fPopula()
//Setando o foco na pesquisa
oGetPesq:SetFocus()
Return
/*---------------------------------------------------------------------*
| Func: fCancela |
| Autor: Daniel Atilio |
| Data: 16/05/2016 |
| Desc: Função de cancelamento da rotina |
*---------------------------------------------------------------------*/
Static Function fCancela()
oDlgMark:End()
Return
/*---------------------------------------------------------------------*
| Func: fVldPesq |
| Autor: Daniel Atilio |
| Data: 16/05/2016 |
| Desc: Função que valida o campo digitado |
*---------------------------------------------------------------------*/
Static Function fVldPesq()
Local lRet := .T.
//Se tiver apóstrofo ou porcentagem, a pesquisa não pode prosseguir
If "'" $ cGetPesq .Or. "%" $ cGetPesq
lRet := .F.
MsgAlert("<b>Pesquisa inválida!</b><br>A pesquisa não pode ter <b>'</b> ou <b>%</b>.", "Atenção")
EndIf
//Se houver retorno, atualiza grid
If lRet
fPopula()
EndIf
Return lRet
/*---------------------------------------------------------------------*
| Func: fGetMkA |
| Autor: Daniel Atilio |
| Data: 16/05/2016 |
| Desc: Função que marca o registro |
*---------------------------------------------------------------------*/
Static Function fGetMkA(cMarca)
Local lChecado:= .F.
Local lFalhou := .F.
//Verificando se o registro foi checado
DbSelectArea(cAliasTmp)
lChecado:=XX_OK <> cMarca
cChave := Alltrim(&(cAliasTmp+"->XX_CODIGO"))+";"
//Se for checado
If lChecado
//Se o tamanho do retorno +chave for maior que o retorno
If Len(Alltrim(cGetReto) + cChave) > nTamFim
MsgAlert("Tamanho do Parâmetro Excedido!", "Atenção")
lFalhou := .T.
//Atualiza chave
Else
cGetReto := Alltrim(cGetReto)+cChave
EndIf
//Senão retira do retorno
Else
cGetReto := StrTran(cGetReto, cChave, '')
EndIf
cGetReto := cGetReto + Space(nTamFim - Len(cGetReto))
//Se não houve falhas
If !lFalhou
//Gravando a marca
RecLock( cAliasTmp, .F. )
XX_OK := IIF( lChecado, cMarca, "" )
&(cAliasTmp)->(MsUnlock())
EndIf
oGetReto:Refresh()
oMAux:oBrowse:Refresh()
Return
Bom pessoal, por hoje é só.
Abraços e até a próxima.

Ainda é possivel fazer isso nas Versões 2310/2410 ?
Bom dia Johnny, tudo joia?
Não chegamos a testar nas versões mais recentes.
Está dando alguma mensagem de erro?
Ficamos no aguardo.
Tenha uma ótima e abençoada sexta feira.
Um forte abraço.