Página 1 de 1

Filtrar com Subntx

Enviado: 02 Abr 2011 17:37
por rubens
Olá...

Tenho um dbf de contas a receber com os campos
CODIGO, DTVENC
Preciso Filtrar pelo código e ordem DTVENC
Uso
Set Order to DTVENC
SET FILTER TO cCodigo = CR->CODIGO

Como fazer essa filtragem com subntx? só com o código eu consigo
SUBTNX( "CODIGO.NTX","CODTMP","","","*"+cCODIGO+"*")
Mas aí não fica ordem de data, como eu faria deixar em ordem de data e filtra pelo código ?

Vlw...
Rubens

Re: Filtrar com Subntx

Enviado: 02 Abr 2011 23:31
por alxsts
Olá!

Rubens, talvez você consiga resolver o problema alterando a chave de índice. Não temos muitos detalhes mas tente indexar por código e data:

Código: Selecionar todos

Str( CODIGO ) + DtoS(DTVENC )
.
Se puder evitar o uso do SET FILTER, também ajuda.

Dependendo do Clipper que você usa, poderá usar a função OrdScope() (Clipper 5.3).

Re: Filtrar com Subntx

Enviado: 04 Abr 2011 12:15
por rochinha
Amiguinho,

A SUBNTX trabalha em cima de um arquivo de indice, extraindo dele o conjunto de registro que voce selecionou, criando um arquivo de indice menor e ativando-o para uso.

Para usa-lo voce:

- Abre a tabela
- Seta os indices do arquivo
- Seleciona a ordem que voce deseja filtrar
- Usa SUBNTX para criar o filtro desejado
- Adiciona o novo indice aos ja abertos
- Usa browse ou dbEdit sobre o conjunto filtrado

Para ajuda-lo voce pode integrar algumas facilidades ao seu codigo:

Código: Selecionar todos

#command DELETE TAGS => F_Erase( "SUB*.NTX" )
	 
#command ADD INDEX <SubIndex> => ordListAdd( <"SubIndex"> ) ;;
	                                 ordSetFocus( NDXCOUNT() )
	 
#command RESET ORDER <order> => ordListReset( <order> )
Para o bom uso de SUBNTX voce de sempre eliminar os temporarios criados por ela.

ADD INDEX <SubIndex> vai adicionar o novo indices ao final dos indices da area aberta.

RESET ORDER <order> vai derrubar um indice da ordem e restabelece-la ao padrao.

As funcoes de apoio são:

Código: Selecionar todos

FUNCTION F_ERASE( ARQUIVOS )
   CONTADOR  := ADIR( ARQUIVOS )
   IF CONTADOR != 0
      DECLARE TXT_NOMES[ CONTADOR ]
      ADIR( ARQUIVOS, TXT_NOMES )
      FOR CONTADOR := 1 TO LEN( TXT_NOMES )
          FERASE( TXT_NOMES[CONTADOR] )
      NEXT
   ENDIF
   RETURN .T.

FUNCTION NDXCOUNT()
   LOCAL counter
   FOR counter = 1 TO 15
       IF EMPTY(INDEXKEY(counter))
          EXIT
       ENDIF
   NEXT
   RETURN (counter-1)

FUNCTION ordList()
   LOCAL counter
   PUBLIC nomes_ndx := {}
   FOR counter = 1 TO 15
       IF EMPTY(INDEXKEY(counter))
          EXIT
       ENDIF
       AADD(nomes_ndx,ORDNAME(counter))
   NEXT
   RETURN nomes_ndx

FUNCTION ordListReset( ord_number )
   LOCAL counter, nomes_ndx := ordList()
   if valtype(ord_number) = 'C'
      ord_number := ordSetList( ord_number )
   endif
   ordListClear()
   FOR counter = 1 TO len(nomes_ndx)
       IF counter = ord_number
       ELSE
          ordListAdd(nomes_ndx[counter])
       ENDIF
   NEXT
   RETURN .t.

FUNCTION ordSetList( O_R_DEM )
   FOR counter = 1 TO 15
       ordSFocus := counter
       IF EMPTY(INDEXKEY(counter))
          EXIT
       ENDIF
       IF UPPER(ALLTRIM(ORDNAME(counter))) = UPPER(ALLTRIM(O_R_DEM))
          EXIT
       ENDIF
   NEXT
   RETURN ordSFocus
O codigo exemplo:

Código: Selecionar todos

// Sample showing how to use SUBNTX with NTX indexes

#include "FiveWin.ch"

static oWnd, cTempo1, cTempo2, cName := "COMERC"

//----------------------------------------------------------------------------//

function Main()

   DEFINE WINDOW oWnd FROM 1, 1 TO 20, 60 ;
      TITLE "Sistema de Faturamento" 

   SET MESSAGE OF oWnd TO OemToAnsi( "5volution.com - (r) Jose Carlos da Rocha, 2004 - Brasil" )
   ACTIVATE WINDOW oWnd ;
      ON INIT ShowDlg()

return nil

//----------------------------------------------------------------------------//

function ShowDlg()
      IF ! FILE("CLIENTES.DBF")
         msgrun("CLIENTES.DBF nao encontrado!")
         QUIT
      ENDIF
      USE CLIENTES
      IF lastrec() < 75
         EXPAND_DBF()
      ENDIF
      IF ! FILE("SUBDEMO.NTX")
         //msgrun("WAIT. Creating file SUBDEMO.NTX...")
         MsgMeter( { |oMeter,oText,oDlg,lEnd| ;
                           MakeIndex( oMeter, oText, oDlg, @lEnd, "CLIENTES->NOME+CLIENTES->ESTADO", "SUBDEMO.NTX", "" ) },;
                           "Creating index SUBDEMO.NTX..." )
      ENDIF
          
      msgwait("Primeiro. Mostro todo database...")
      browse()                                          

      msgwait("Agora. Usando um simples SEEK...")
      set index to SUBDEMO
      go top
      seek "5VOLUTION"
      browse()                                          

      msgwait("Agora. Usando um simples SET FILTER...")
      go top
      seek "5vol"
      msgwait("Observacao. Quando mover o cursor alem do browse o cursor se perde por muito tempo...")
      msgwait("((provavelmente mais de um minuto)")
      cTempo1 := time()
      set filter to CLIENTES->NOME = "5VOLUTION"
      go top
      cTempo2 := time()
      MsgAlert("Tempo de Operacao: "+tempo( cTempo1,cTempo2 )+" segundo(s)" )
      browse()                                                                        
      set filter to

      msgwait("E AGORA. Usando SUBNTX...")

      nString := 1
      do while .t. //cName <> "exit"
         if MsgGet( "Digite uma frase:",;          // Title
                 "Nome:",;                     // Label
                 @cName )                           // A variable by reference
            set index to
            cTempo1 := time()
            //
            num = subntx( "SUBDEMO.NTX", "_SUB.NTX", cName )
            //
            cTempo2 := time()
            if ! FILE("_SUB.NTX")
               msgwait("Nenhum filtro foi gerador...")
            else
               set index to _sub
               //MsgAlert("Tempo de Operacao: "+tempo( cTempo1,cTempo2 )+" segundo(s)" )
               browse()
            endif
            nString := nString + 1
            do case
               case nString = 2
                    cName := "SA"
               case nString = 3
                    cName := "JOS"
               case nString = 4
                    cName := "W"
               case nString = 5
                    cName := "BE"
               case nString = 6
                    cName := "PANI"
               otherwise
                    msgwait("Eu gosto disto. Obrigado...")
                    quit // exit
            endcase
            set index to
            erase _sub.ntx
         else
            exit
         endif
      enddo
      close databases
   return nil

//----------------------------------------------------------------------------//
function EXPAND_DBF
   msgrun("STAND BY while expanding CLIENTES.DBF...")
   ERASE SUBDEMO.NTX
   COPY TO _SUBTMP
   FOR i = 1 to 49
       APPEND FROM _SUBTMP
   NEXT
   ERASE _SUBTMP.DBF
   REPLACE ALL REC WITH RECNO()
   return nil

//----------------------------------------------------------------------------//
function tempo( inicio, final )
   return str(val(strtran(substr(final,4,5),":",""))-val(strtran(substr(inicio,4,5),":","")),6)

//----------------------------------------------------------------------------//
function MakeIndex( oMeter, oText, oDlg, lEnd, cChave, cIndex, cFor )
   FIELD Last
   oMeter:nTotal = RecCount()
   IF EMPTY( cFor )
      INDEX ON &(cChave) TO &(cIndex) ;
            EVAL ( oMeter:Set( RecNo() ), SysRefresh(), ! lEnd )
   ELSE
      INDEX ON &(cChave) TO &(cIndex) FOR &(cFor) ;
            EVAL ( oMeter:Set( RecNo() ), SysRefresh(), ! lEnd )
   ENDIF
return nil

Re: Filtrar com Subntx

Enviado: 04 Abr 2011 18:15
por rubens
Caro Rochinha... vc devia ser escritor !!! Como sempre... ganhamos mais do que pedimos...

Quando comecei usar o subntx, os exemplos que tinha era para filtrar por um item ou no caso por data e por item...
Mas nesse caso especifico preciso filtrar por codigo do cliente e por data...
Como aplicar a subntx num indice composto tipo CODIGO + DTOC(DATA_) ou CODIGO + DTOS(DATA_)

Assim:

Código: Selecionar todos

Use CTRECEB.DBF
Index on codigo+dtoc(data_) to indcod.ntx
Set index to 
If File("indtmp.ntx")
      Ferase("indtmp.ntx")
Endif
cCodigo := "000005"
subntx( "indcod.ntx","indtmp.ntx", "","", "*"+cCodigo+"*")
Browse()
Nesse exemplo ele traz informações que não pertencem ao codigo 000005

Se eu usar no indice só o código funciona mas daí o browse não fica em ordem de data...

Rubens

Re: Filtrar com Subntx

Enviado: 05 Abr 2011 00:58
por rochinha
Amiguinho,

Eu sempre frisei aos meus alunos(não de programação) que a prática é a melhor maneira de se entender a teoria.

E minha frase preferida é:

"...uma código fonte vale mais que mil palavras...". Desde que o codigo fonte [n]não[/b] tenha tantas palavras.

Mas quanto ao seu código. A SUBNTX necessita de alguns parametros, sendo:

- Nome do arquivo de indice que será manipulado.
- Nome do arquivo de indice resultante da manipulação.
- Chave/Variável inicial que será passada para a manipulação(geralmente só usamos até aqui).
- Chave/Variável final que será passada para a manipulação(só usamos se queremos um range de dados).
- Caracteres coringa.
- Função definida pelo usuário.
- Numero de tentativa de lock.

Finalizando sem mais delongas:

Seu comando ficaria assim:

Código: Selecionar todos

...
subntx( "indcod.ntx","indtmp.ntx", CODIGO + DTOC(DATA_INICIAL), CODIGO + DTOC(DATA_FINAL), "*"+cCodigo+"*" )
...
O trecho "*"+cCodigo+"*" nem seria necessário.