Campo Memo Alternativo

Aqui você poderá oferecer suas Contribuições, Dicas e Tutoriais (Texto ou Vídeo) que sejam de interesse de todos.

Moderador: Moderadores

Avatar do usuário
asimoes
Colaborador
Colaborador
Mensagens: 4919
Registrado em: 26 Abr 2007 16:48
Localização: RIO DE JANEIRO-RJ

Campo Memo Alternativo

Mensagem por asimoes »

Senhores,

Depois de muitos problemas com campo memo, contribuo com vocês a solução que usamos
em nossos sistemas clipper para o campo memo. A solução grava, lê e exclui somente o registro que precisa da informação de texto.

Código: Selecionar todos

/*
Solução para substituir campo memo de dbf.
O campo memo em dbf ocupa espaço e pode corromper o dbf.

Exemplo de uso:

Criar um dbf com nome arqobs (nome opcional)

Com a seguinte estrutura:

DBCREATE("ARQOBS.DBF", {
        { "CHAVE",      "C",   5,   0 },;
        { "NUM_LINHA",  "C",   4,   0 },;
        { "LINHA_MEMO", "C",  80,   0 },;
        })

A chave de indice:

INDEX ON Chave+Num_Linha TAG "C0001" TO ARQOBS

Para gravar o memo:

A  área DBFORI: Deve estar indexada, o conteúdo da chave de indice de DBFORI será gravado
no campo chave de ARQOBS usando INDEXKEY(), ver documentação da função F_GrMemo()

cObsMemo:=MEMOEDIT(cObsMemo,3,1,22,78, lEdita,"UFUNC", 80)

F_GrMemo(cObsMemo, 80, "DBFORI", "ARQOBS")

Para ler o memo:

cObsMemo:=F_LeMemo("DBFORI", "ARQOBS")

A  área de DBFORI deve estar indexada com o mesmo INDEXKEY() de ARQOBS.

Para excluir:

F_DelMemo("DBFORI", "ARQOBS")

A  área de DBFORI deve estar indexada com o mesmo INDEXKEY() de ARQOBS.

*/

#include "common.ch"
******************************************************************************
FUNCTION F_LeMemo(cArqMestre, cArqMemo, cEspecial)
******************************************************************************
* Autor(es)     : Carlos Eduardo Taylor                                      *
* Data          : Agosto/1999                                                *
*----------------------------------------------------------------------------*
* Ojetivo       : Le as linhas de memo do arq. MEMO para uma variavel memo   *
* Observacao    : O arquivo Mestre deve estar posicionado na chave correta   *
*                 O arquivo Memo deve ter os campos:                         *
*                   - CHAVE (carac.,tam >= tamanho da concatenacao completa  *
*                            da chave do cArqMestre)                         *
*                   - NUM_LINHA  (carac.,tam = qualquer)                     *
*                   - LINHA_MEMO (carac.,tam >= P_TAM)                       *
*                 O arquivo Memo deve estar indexado por CHAVE + NUM_LINHA   *
* Sintaxe       : F_LeMemo(cArqMestre, cArqMemo, [cEspecial])                *
* Parametros    : <cArqMestre> - nome do arquivo mestre                      *
*                 <cArqMemo>   - nome do arquivo onde ser„o lidas as linhas  *
*                                memo                                        *
*                 [<cEspecial>]- utilizado para qualquer condi‡„o especial   *
*                                a ser inserida na fun‡„o (DEFAULT "")       *
* Retorno       : cMemo - variavel do memoedit                               *
* Fun. chamadas :                                                            *
* Arquivo fonte : ArqMemo.prg                                                *
* Arq. de dados : arquivo mestre e arquivo memo                              *
* Veja tamb‚m   :                                                            *
******************************************************************************
LOCAL cMemo,cChave,bGrava,bCondicao,aMemo:={},i
LOCAL cAlias := ALIAS()

DEFAULT cEspecial TO ""
cMemo    := ""

   SELECT (cArqMestre)
   bGrava   := { || cMemo += TRIM((cArqMemo)->Linha_Memo) + CHR(13)+CHR(10) }
   IF EMPTY(cEspecial)      
      cChave   := &((cArqMestre)->(INDEXKEY()))
      bCondicao:= { || TRIM((cArqMemo)->Chave) == cChave .AND. (cArqMemo)->(!EOF()) }
   ELSEIF LEFT(cEspecial,5) == 'CHAVE' // Especifica String Chave
      cChave   := RIGHT(cEspecial,LEN(cEspecial) - 5)
      bCondicao:= { || TRIM((cArqMemo)->Chave) == cChave .AND. (cArqMemo)->(!EOF()) }
   ENDIF

   SELECT (cArqMemo)
   OrdSetFocus(1)
   
   (cArqMemo)->(DBSEEK(cChave))
   (cArqMemo)->(DBEVAL(bGrava,,bCondicao,,,.T.))
   
   IF !EMPTY(cAlias)
      SELECT (cAlias)
   ENDIF

RETURN cMemo

******************************************************************************
FUNCTION F_GrMemo(cMemo, nTam, cArqMestre, cArqMemo, cEspecial)
******************************************************************************
* Autor(es)     : Alexandre Simäes                                           *
* Data          : Agosto/1999                                                *
*----------------------------------------------------------------------------*
* Ojetivo       : Grava as linhas de memo no cArqMemo a partir de uma        *
*                 variavel memo/car.                                         *
* Observacao    : O arquivo Mestre deve estar posicionado na chave correta   *
*                 O arquivo Memo deve ter os campos:                         *
*                   - CHAVE (carac.,tam >= tamanho da concatenacao completa  *
*                            da chave do cArqMestre)                         *
*                   - NUM_LINHA  (carac.,tam = qualquer)                     *
*                   - LINHA_MEMO (carac.,tam >= P_TAM)                       *
*                 O arquivo Memo deve estar indexado por CHAVE + NUM_LINHA   *
* Sintaxe       : GrMemo(cMemo, nTam, cArqMestre, cArqMemo, [cEspecial],;    *
* Parametros    : <cMemo> - variavel do memoedit a ser gravada               *
*                 <nTam>  - tamanho da linha                                 *
*                 <cArqMestre> - nome do arquivo mestre                      *
*                 <cArqMemo>   - nome do arquivo onde ser„o gravadas as      *
*                                linhas de memo                              *
*                 [<cEspecial>]- utilizado para qualquer condi‡„o especial   *
*                                a ser inserida na fun‡„o (DEFAULT "")       *
* Retorno       : NIL                                                        *
* Fun. chamadas :                                                            *
* Arquivo fonte : ArqMemo.prg                                                *
* Arq. de dados : arquivo mestre e arquivo memo                              *
* Veja tamb‚m   :                                                            *
******************************************************************************
LOCAL nTotLinha,i,j,cChave,nLen,dDtAux,CContinue:=0
LOCAL aCols:={},aAnda:={},lValido:=.T.
LOCAL cNumLinha,cLinhaMemo
LOCAL cAlias := ALIAS()

DEFAULT cEspecial TO ""

SELECT (cArqMestre)
IF EMPTY(cEspecial)
   cChave   := &((cArqMestre)->(INDEXKEY()))
ELSEIF LEFT(cEspecial,5) == 'CHAVE'   
   cChave   := RIGHT(cEspecial,LEN(cEspecial) - 5)
ENDIF

IF !EMPTY(cAlias)
   SELECT (cAlias)
ENDIF

nLen     := LEN((cArqMemo)->NUM_LINHA)
nTotLinha:= MLCOUNT(cMemo,nTam)
i := 0

IF EMPTY(cEspecial) .OR. LEFT(cEspecial,5) == 'CHAVE'

   * Grava primeiro sobre as linhas da mesma chave se houverem:
   IF (cArqMemo)->(DBSEEK(cChave))
      WHILE TRIM((cArqMemo)->CHAVE) == cChave .AND. ;
            (cArqMemo)->(!EOF()) .AND. i < nTotLinha
         i ++
         (cArqMemo)->(DbRLock())
         REPLACE (cArqMemo)->LINHA_MEMO  WITH MEMOLINE(cMemo,nTam,i)
         (cArqMemo)->(DBCOMMIT())
         (cArqMemo)->(DBUNLOCK())
         (cArqMemo)->(DBSKIP())
      ENDDO
   ENDIF

   * Apaga as linhas restantes da mesma chave se houverem: (novo memo menor que o anterior)
   WHILE TRIM((cArqMemo)->CHAVE) == cChave .AND. (cArqMemo)->(!EOF())
      (cArqMemo)->(DbRLock())
      (cArqMemo)->(DBDELETE())
      (cArqMemo)->(DBCOMMIT())
      (cArqMemo)->(DBUNLOCK())
      (cArqMemo)->(DBSKIP())
   ENDDO

   * Acrescenta linhas novas se o novo memo for maior que o anterior:
   FOR j :=  i+1 TO nTotLinha STEP 1

      (cArqMemo)->(DbAppend())
      REPLACE (cArqMemo)->CHAVE       WITH cChave          ,;
              (cArqMemo)->NUM_LINHA   WITH STRZERO(j,nLen) ,;
              (cArqMemo)->LINHA_MEMO  WITH MEMOLINE(cMemo,nTam,j)
              (cArqMemo)->(DBCOMMIT())
              (cArqMemo)->(DBUNLOCK())
   NEXT

ENDIF

RETURN lValido

******************************************************************************
FUNCTION F_DelMemo(cArqMestre, cArqMemo, cEspecial)
******************************************************************************
* Autor(es)     : Carlos Eduardo Taylor                                      *
* Data          : Agosto/1999                                                *
*----------------------------------------------------------------------------*
* Ojetivo       : Apaga as linhas de memo no cArqMemo a partir de uma        *
*                 chave.                                                     *
* Observacao    : O arquivo Mestre deve estar posicionado na chave correta   *
*                 O arquivo Memo deve ter os campos:                         *
*                   - CHAVE (carac.,tam >= tamanho da concatenacao completa  *
*                            da chave do cArqMestre)                         *
*                   - NUM_LINHA  (carac.,tam = qualquer)                     *
*                   - LINHA_MEMO (carac.,tam >= P_TAM)                       *
*                 O arquivo Memo deve estar indexado por CHAVE + NUM_LINHA   *
* Sintaxe       : F_DelMemo(cArqMestre, cArqMemo, [cEspecial])               *
* Parametros    : <cArqMestre> - nome do arquivo mestre                      *
*                 <cArqMemo>   - nome do arquivo onde ser„o apagadas as      *
*                                linhas de memo                              *
*                 [<cEspecial>]- utilizado para qualquer condi‡„o especial   *
*                                a ser inserida na fun‡„o (DEFAULT "")       *
* Retorno       : NIL                                                        *
* Fun. chamadas :                                                            *
* Arquivo fonte : ArqMemo.prg                                                *
* Arq. de dados : arquivo mestre e arquivo memo                              *
* Veja tamb‚m   :                                                            *
******************************************************************************
LOCAL cChave,cTabela,CContinue:=0
LOCAL cAlias := ALIAS()

DEFAULT cEspecial TO ""

SELECT (cArqMestre)
IF EMPTY(cEspecial)
   cChave   := &((cArqMestre)->(INDEXKEY()))   
ELSEIF LEFT(cEspecial,5) == 'CHAVE'   
   cChave   := RIGHT(cEspecial,LEN(cEspecial) - 5)
ENDIF

IF !EMPTY(cAlias)
   SELECT (cAlias)
ENDIF

* Apaga as linhas da mesma chave se houverem:

   IF (cArqMemo)->(DBSEEK(cChave))

      IF EMPTY(cEspecial)

         WHILE TRIM((cArqMemo)->CHAVE) == cChave .AND. (cArqMemo)->(!EOF())
            (cArqMemo)->(DbRLock())
            (cArqMemo)->(DBDELETE())
            (cArqMemo)->(DBCOMMIT())
            (cArqMemo)->(DBUNLOCK())
            (cArqMemo)->(DBSKIP())
         ENDDO
      ENDIF
   ENDIF
RETURN NIL
►Harbour 3.x | Minigui xx-x | HwGui◄
Pense nas possibilidades abstraia as dificuldades.
Não corrigir nossas falhas é o mesmo que cometer novos erros.
A imaginação é mais importante que o conhecimento. (Albert Einstein)
Responder