Pessoal
Procurei em todo o forum solução para um problema que eu tinha e que também outros tem ou já tiveram: Como tratar de dar um "chega pra lá" naqueles amáveis usuários que "dormem" sobre um registro bloqueado e não saem nunca do modo de edição.
A solução mais prática que vi foi o uso da função KeySec().
Mas bolei uma solução tupiniquim, que resolveu bem o meu problema, embora seja aplicável apenas aos casos get/read. Acho que com um TBrowse já não dá pra usar. Mas vamos lá:
O macete é não bloquear o registro para edição. Apenas permita que o gajo leia o registro em questão e atribua a variáveis os valores dos diferentes campos.
O registro só é bloqueado no instante que o cara cair fora do read.
Tipo assim:
1) Atribua a variáveis os valores dos campos:
global xCampo[fcount()]
for i = 1 to fcount()
xCampo := fieldget(i)
next
2) Depois crie o conjunto get/read:
@ 2, 4 SAY Fieldname(1) color cColor1 GET xCampo[1] color cColor2 //ANOMES
@ 2, 24 SAY Fieldname(2) color cColor1 GET xCampo[2] color cColor2 //LOTE
@ 2, 34 SAY Fieldname(3) color cColor1 GET xCampo[3] color cColor2 //DIG
@ 2, 44 SAY Fieldname(4) color cColor1 GET xCampo[4] color cColor2 //DOM
@ 2, 54 SAY Fieldname(5) color cColor1 GET xCampo[5] color cColor2 //FAM
@ 2, 64 SAY Fieldname(6) color cColor1 GET xCampo[6] color cColor2
.
.
.
read
3) Quando o read for liberado, grave
if updated()
try
rlock()
for i = 1 to fcount()
fieldput(i, xCampo)
next
dbcommit()
dbunlock()
catch
//Aqui eu coloquei uma rotina para gravar em outro banco de dados os casos em que //deu rolo. Até este momento não houve nenhum registro de ocorrencia de problemas.
end
endif
Pode ser que já tenha sido postado sobre isto, mas achei que valia a pena registrar.
Até
Para os que dormem sobre um get/read aberto
Moderador: Moderadores
Re: Para os que dormem sobre um get/read aberto
Ola Romeuk
bem eu faco um pouco diferente...
desenvolvi uma estrutura que me permite trabalhar com ambiente multiusuario e uma mesma rotina fazendo a inclusao, alteracao, exclusao e detalhe, nao sei se é mais correta, mas pra mim que preciso estar sempre alterando rotinas, incluindo funcoes e mexendo no codigo, seria uma verdadeira loucura alterar a rotina de incluir, de alterar, de excluir.... principalmente porque a tela e os dados sao os mesmos, o que muda na verdade é a gravacao no DB e o tratamento das operacoes..
Veja um exemplo:
Por favor... deem suas opnioes!
Abracos
bem eu faco um pouco diferente...
desenvolvi uma estrutura que me permite trabalhar com ambiente multiusuario e uma mesma rotina fazendo a inclusao, alteracao, exclusao e detalhe, nao sei se é mais correta, mas pra mim que preciso estar sempre alterando rotinas, incluindo funcoes e mexendo no codigo, seria uma verdadeira loucura alterar a rotina de incluir, de alterar, de excluir.... principalmente porque a tela e os dados sao os mesmos, o que muda na verdade é a gravacao no DB e o tratamento das operacoes..
Veja um exemplo:
Código: Selecionar todos
*-----------------------------------------------------------------------------
*
* Departamento de Informatica - CPD MK
*
* Sistema....:
* Programa...: Cd_ICM01.prg
* Autor......: Erwin Bogner - Analista Programador
* Objetivo...: Cadastro de Percentuais de ICMS por Estado
* Parametros.: NIL
* Saidas.....: NIL
* Dt.Criacao.: 19 de Dezembro de 1996
*
* Dt.Atualiz.: 20.11.2001.
*
*-----------------------------------------------------------------------------
LOCAL GetList := {}
LOCAL Tel_001 := SaveScreen( 00,00,24,79 )
LOCAL CorAnt := SetColor()
LOCAL aaCampo[04], aaMasca[04], aaPictu[04]
aaCampo[01] := "ICMS->CD_ESTAD"
aaCampo[02] := "ICMS->NO_ESTAD"
aaCampo[03] := "ICMS->PER_ICMS"
aaCampo[04] := "ICMS->PER_ICM2"
*
aaMasca[01] := "UF"
aaMasca[02] := "Nome Estado"
aaMasca[03] := "% ICM"
aaMasca[04] := "% ICM2"
*
aaPictu[01] := "!!"
aaPictu[02] := "@!@X20"
aaPictu[03] := "@ZE 999,99"
aaPictu[04] := "@ZE 999,99"
*
SELE ICMS
SET ORDER TO 1
GO TOP
Modulo( 'Cadastro ICMS' )
Moldura( 04,00,23,79,3,1,1,"ICMS p/Estado",'B+/BG+','BG+/B+' )
Opcoes( 22, { '<F2> Inclui','<F3> Altera','<F4> Exclui','<F6> Pesquisa','<ESC> Retorna' } )
DBEDIT( 05,01,21,78,aaCampo,'J_ManICMS',aaPictu,aaMasca )
//
SELE ICMS
SET ORDER TO 1
GO TOP
//
RestScreen( 04,00,23,79,Tel_001 )
SetColor( CorAnt )
RETURN
*-----------------------------------------------------------------------------
FUNCTION J_ManICMS( Modo )
*-----------------------------------------------------------------------------
* Funcao.....:
* Parametros.:
* Retorna....:
*
LOCAL GetList := {}
LOCAL Tel_001 := SaveScreen( 00,00,24,79 )
LOCAL Cursor := SetCursor(1)
LOCAL CorAnt := SetColor()
LOCAL xDate := date()
LOCAL nTecla := LastKey()
LOCAL xOpcao := SPACE(1)
LOCAL XESTADO := 0
DO CASE
CASE nTecla == -1
IF M->DIREITO == 'M' .OR. ValAcesso( M->sUsuario,09,94 )
DO Man_ICMS01 WITH 'I'
ENDIF
//
RestScreen( 00,00,24,79,Tel_001 )
RETURN( 1 )
CASE nTecla == -2
IF M->DIREITO == 'M' .OR. ValAcesso( M->sUsuario,09,95 )
DO Man_ICMS01 WITH 'A'
ENDIF
//
RestScreen( 00,00,24,79,Tel_001 )
RETURN( 12 )
CASE nTecla == -3
IF M->DIREITO == 'M' .OR. ValAcesso( M->sUsuario,09,96 )
DO Man_ICMS01 WITH 'E'
GO TOP
ENDIF
//
RestScreen( 00,00,24,79,Tel_001 )
RETURN( 1 )
CASE nTecla == -4
DO Man_ICMS01 WITH 'D'
//
RestScreen( 00,00,24,79,Tel_001 )
RETURN( 1 )
CASE nTecla == -5
@ 24,00
@ 24,01 SAY 'Digite o Estado ==> ' GET XESTADO PICT '99999999'
READ
IF LastKey() # 27
SET SOFTSEEK ON
SEEK AllTRIM( XESTADO )
SET SOFTSEEK OFF
ENDIF
//
RestScreen( 00,00,24,79,Tel_001 )
KeyBoard ' '
RETURN( 1 )
CASE nTecla == 27 // Retorna (Esc (27) )
RestScreen( 00,00,24,79,Tel_001 )
KeyBoard ' '
RETURN(0)
ENDCASE
IF Modo >= 1 .AND. Modo <= 4
MDBEdit( Modo )
ENDIF
RETURN( 1 )
*-----------------------------------------------------------------------------
PROCEDURE Man_ICMS01( PFUNC )
*-----------------------------------------------------------------------------
* Funcao.....: Rotina de manutencao da base de dados de cadastro de ICMS's
* Parametros.: PFUNC -> variavel indicando forma de atuacao da procedure
* Retorna....: NIL
*
LOCAL GetList := {}
LOCAL Tel_001 := SaveScreen( 00,00,24,79 )
LOCAL Tel_002 := SaveScreen( 00,00,24,79 )
LOCAL Cursor := SetCursor(1)
LOCAL CorAnt := SetColor()
LOCAL xDate := date()
LOCAL xEstado := SPACE(2)
LOCAL xNome__ := SPACE(20)
LOCAL xP_ICMS := 0
LOCAL xP_ICM2 := 0
IF PFUNC$('AED') // Consulta/Alteracao/Exclusao
xEstado := ICMS->CD_ESTAD
xNome__ := ICMS->NO_ESTAD
xP_ICMS := ICMS->PER_ICMS
xP_ICM2 := ICMS->PER_ICM2
ENDIF
Modelo( PFUNC )
Moldura( 10,20,17,59,3,1,1,'ICMS','B+/BG+','BG+/B+' )
SetColor( 'W+/B+' )
@ 12,25 SAY 'Estado ===> '
@ 13,25 SAY 'Nome =====> '
@ 14,25 SAY '% ICMS ===> '
@ 15,25 SAY '% ICMS 2==> '
SetColor( CorAnt )
Tel_002 := SaveScreen( 00,00,24,79 )
DO WHILE .T.
//
RestScreen( 00,00,24,79,Tel_002 )
//
Centra( 24,'Digite a Sigla do Estado ou <ESC> para Voltar.','W+/BG+',1)
@ 12,37 GET xEstado PICT '!!'
IF PFUNC$( 'IA' )
READ
IF LastKey() == 27
EXIT
ENDIF
ELSE
CLEAR GETS
ENDIF
//
Centra( 24,'Digite o Nome do Estado ou <ESC> para Voltar.','W+/BG+',1)
@ 13,37 GET xNome__ PICT '@!@X20'
IF PFUNC$( 'IA' )
READ
IF LastKey() == 27
LOOP
ENDIF
ELSE
CLEAR GETS
ENDIF
//
Centra( 24,'Digite o Percentual de ICMS (1_2) do Estado ou <ESC> para Voltar.','W+/BG+',1)
@ 14,37 GET xP_ICMS PICT '@ZE 999.99'
@ 15,37 GET xP_ICM2 PICT '@ZE 999.99'
IF PFUNC$( 'IA' )
READ
IF LastKey() == 27
LOOP
ENDIF
ELSE
CLEAR GETS
ENDIF
//
SELE ICMS
IF PFUNC == 'D'
Mensagem( 24,'Pressione qquer tecla para continuar consulta...','W+/R+',20 )
EXIT
ENDIF
//
IF Confirma( 20,'Confirma a Execucao da Operacao Solicitada ?' )
//
SELE ICMS
IF PFUNC == 'I'
IF AdiReg( 20 )
REPLACE ICMS->DT_INCLU WITH xDate ,;
ICMS->SITUACAO WITH PFUNC
COMMIT
UNLOCK
ENDIF
ENDIF
IF RegLock( 20 )
IF PFUNC$('AI')
REPLACE ICMS->SITUACAO WITH PFUNC
REPLACE ICMS->CD_ESTAD WITH xEstado ,;
ICMS->NO_ESTAD WITH xNome__ ,;
ICMS->PER_ICMS WITH xP_ICMS ,;
ICMS->PER_ICM2 WITH xP_ICM2
ELSE
REPLACE ICMS->SITUACAO WITH PFUNC
DELE
ENDIF
REPLACE ICMS->USU WITH M->sUsuario ,;
ICMS->OPE WITH PFUNC ,;
ICMS->EST WITH Cript( M->ESTACAO) ,;
ICMS->MAQ WITH Cript( M->MAQUINA) ,;
ICMS->DTA WITH F_DT()
//
// Controle Transferencia
//
DO CASE
CASE PARAM->TRANSFER == '1'
REPLACE ICMS->FLAGTR1 WITH 'T'
CASE PARAM->TRANSFER == '2'
REPLACE ICMS->FLAGTR2 WITH 'T'
CASE PARAM->TRANSFER == '3'
REPLACE ICMS->FLAGTR3 WITH 'T'
ENDCASE
//
COMMIT
UNLOCK
ENDIF
ENDIF
EXIT
ENDDO
//
RestScreen( 00,00,24,79,Tel_001 )
SetCursor( Cursor )
SetColor( CorAnt )
KeyBoard ' '
RETURN
*-------------------------------------------------------------------------------Abracos
- alaminojunior
- Colaborador

- Mensagens: 1717
- Registrado em: 16 Dez 2005 21:26
- Localização: Ubatuba - SP
Re: Para os que dormem sobre um get/read aberto
Mas este sempre foi o procedimento correto mesmo, e sempre será: sempre editar variáveis, e nunca os campos.O macete é não bloquear o registro para edição. Apenas permita que o gajo leia o registro em questão e atribua a variáveis os valores dos diferentes campos.
O registro só é bloqueado no instante que o cara cair fora do read.
E mesmo assim, no momento de travar o registro para gravar, precisa prever que outro usuário o tenha feito, por isso, uma rotina que verifique se o bloqueio foi feito ou não, e caso não, tente outras n vezes, é essencial.
Compilador xHarbour 1.2.3 + Embarcadero C++ 7.30
MySQL c/ SQLRDD
HwGui + GTWVG
MySQL c/ SQLRDD
HwGui + GTWVG
Re: Para os que dormem sobre um get/read aberto
Com certeza o procedimento é nunca travar um registro durante um get, sempre carregar os campos do DB em variaveis, edita-las e no final, somente no final fazer a atualizacao do registro, e sempre atualizar o registro sem que o usuario tenha a necessidade de intervir, caso contrario, teremos uma brecha para dar problemas :? .
o que eu fazia para encher o saco de usuarios moles que travam em cima dos get/readers era ativar uma protecao de tela, ai o usuario perdia a imagem do que estava fazendo e era obrigado a voltar ao sistema.
Ps: claro que no mesmo ponto onde ele estava
o que eu fazia para encher o saco de usuarios moles que travam em cima dos get/readers era ativar uma protecao de tela, ai o usuario perdia a imagem do que estava fazendo e era obrigado a voltar ao sistema.
Ps: claro que no mesmo ponto onde ele estava
