Página 1 de 1

Como gerar índices com macro?

Enviado: 16 Nov 2007 23:09
por carlos_dornelas
Pessoal, estou patinando na elaboração de uma rotina que a princípio me parecia simples. Trata-se de gerar várias indexações em cima de frações de um mesmo campo caracter. Se alguém puder me dar uma luz, ficarei muito grato. Segue abaixo o exemplo:

Antonio Carlos - Curitiba


/*/
Preciso ordenar um campo com 20 caracteres por 10 indices diferentes, sendo
que cada indice correspondera a dois caracteres desse campo. Exemplo:

dados=21122334453424263637 - primeiro indice c/digitos 21
segundo indice c/digitos 12
terceiro indice c/digitos 23
...

Se eu utilizar o formato B abaixo funciona corretamente, mas com o formato B
nao da certo.

Preciso fazer funcionar o Formato A, pois no caso real serao 300 indices

/*/



clear
set decimals to 5
aq1:={}
aadd(aq1,{'seq','N',4,0})
aadd(aq1,{'dados','C',20,0})
dbcreate('teste',aq1)
use teste
zap
for g=1 to 15
string=''
for k=1 to 10
xx=second()*k
string+=right(str(xx),2)
next
inkey(.2)
append blank
replace seq with g
replace dados with string
next
go top


**Formato A - Preciso fazer funcionar neste formato
for g=1 to 10
h='ind'+alltrim(str(g))
index on substr(dados,(g*2)-1,2) to &h for substr(dados,(g*2)-1,2)<>' '
next



**Formato B
*index on substr(dados,1,2) to ind1 for substr(dados,1,2)<>' '
*index on substr(dados,3,2) to ind2 for substr(dados,1,2)<>' '
*index on substr(dados,5,2) to ind3 for substr(dados,1,2)<>' '
*index on substr(dados,7,2) to ind4 for substr(dados,1,2)<>' '
*index on substr(dados,9,2) to ind5 for substr(dados,1,2)<>' '
*index on substr(dados,11,2) to ind6 for substr(dados,1,2)<>' '
*index on substr(dados,13,2) to ind7 for substr(dados,1,2)<>' '
*index on substr(dados,15,2) to ind8 for substr(dados,1,2)<>' '
*index on substr(dados,17,2) to ind9 for substr(dados,1,2)<>' '
*index on substr(dados,19,2) to ind10 for substr(dados,1,2)<>' '

dbedit(4,10,20,68,,'ordem')


Function ordem(modo,ponteiro)
lk:=lastkey()
do case
case modo=4
if lk==27
return(0)
elseif lk==-1
@ 2,0 say 'Indice ... 02'
set index to ind2
return(2)
elseif lk==-2
@ 2,0 say 'Indice ... 03'
set index to ind3
return(2)
elseif lk==-3
@ 2,0 say 'Indice ... 04'
set index to ind4
return(2)
elseif lk==-4
@ 2,0 say 'Indice ... 05'
set index to ind5
return(2)
elseif lk==-5
@ 2,0 say 'Indice ... 06'
set index to ind6
return(2)
elseif lk==-6
@ 2,0 say 'Indice ... 07'
set index to ind7
return(2)
elseif lk==-7
@ 2,0 say 'Indice ... 08'
set index to ind8
return(2)
elseif lk==-8
@ 2,0 say 'Indice ... 09'
set index to ind9
return(2)
elseif lk==-9
@ 2,0 say 'Indice ... 10'
set index to ind10
return(2)
elseif lk==13
**o Enter apaga os digitos referentes ao indice 02 - Tecla F2
xdados=left(dados,2)+' '+right(dados,16)
replace dados with xdados
return(2)
endif
endcase

Enviado: 17 Nov 2007 00:00
por clodoaldomonteiro
Carlos!
Testei a tua rotina e deu tudo certo, qual seria o erro que dá ai com você?

Enviado: 17 Nov 2007 00:43
por rochinha
Amiguinho

300, só os de Sparta, contra o todo poderoso Rodrigo Santoro...

Mas o que me fascinou foi a criação de tantos indices e gostaria de saber a finalidade de tal operação e quem sabe dar algumas dicas, quem sabe até pra simplificar.

Enviado: 17 Nov 2007 09:23
por Eolo
Carlos,

Faço coro com o Rochinha... É muito índice junto! Aliás, lembre-se dos limites: com o NTX, são só 15 índices abertos ao mesmo tempo; com o CDX, 99 TAGs...

De qq forma, segue a correção ao que vc fez. Dê uma olhada na linha
b="substr(campo,"+alltrim(str((conta*2)-1))+",2)"

Código: Selecionar todos

use arquivo
priv conta,a,b
for conta=1 to 10
  a="ind"+alltrim(str(conta))
  b="substr(campo,"+alltrim(str((conta*2)-1))+",2)"
  index on &b to &a for !(substr(campo,1,2)=="  ")
next

use arquivo
for conta=1 to 10
  a="ind"+alltrim(str(conta))
  dbsetindex(a)
next

set orde to 1 // indexado por substr(campo,1,2)
set orde to 2 // indexado por substr(campo,3,2)
set orde to 3 // indexado por substr(campo,5,2)
set orde to 4 // indexado por substr(campo,7,2)
set orde to 5 // indexado por substr(campo,9,2)
* etc.
quit

Enviado: 17 Nov 2007 10:36
por carlos_dornelas
Pessoal, obrigado pelas respostas, vou testar a solução do Eolo! Quanto a quantidade de índices abertos, vou precisar usar apenas 1 de cada vez e não terei problemas com o limite de 15. Quanto a quantidade de índices não vejo problemas em se ter 300 ou 1000! Tudo depende do que você precisa realizar, o importante é que a rotina funcione da forma pretendida.

Antonio Carlos

Enviado: 17 Nov 2007 11:10
por Eolo
Carlos, aí é que pintou o alerta: se vc abrir só 1 NTX e fizer alguma alteração no DBF, vai ferrar todos os outros 299 (ops: 14). Vc vai ter que refazê-los...

Vc pode até construir cada NTX a cada hora que for usar, mas isso pode tomar bastante tempo se o DBF for grandinho, certo?

Enviado: 17 Nov 2007 14:51
por carlos_dornelas
Eolo,
Carlos, aí é que pintou o alerta: se vc abrir só 1 NTX e fizer alguma alteração no DBF, vai ferrar todos os outros 299 (ops: 14). Vc vai ter que refazê-los...
Concordo, mas nesse caso, quando estiver com o indice 2 aberto, só farei alterações na coluna 2, logo os demais índices não precisarão estar ativos e mesmo que estivessem não sofreriam qualquer modificação.

Antonio Carlos

Enviado: 17 Nov 2007 17:25
por Eolo
Legal. Entendi.

Enviado: 17 Nov 2007 17:49
por Maligno
E as inclusões e exclusões?

Enviado: 17 Nov 2007 21:45
por alaminojunior
Vai ser um show de "Corruption Detected".
Como o nosso colega Eolo explicou lá em cima, fazer alterações em um indice, e em outro não, é um tanto temerário.
Quanto a quantidade de índices não vejo problemas em se ter 300 ou 1000! Tudo depende do que você precisa realizar, o importante é que a rotina funcione da forma pretendida.
Sem querer ser chato, e parecer especulador, diga-nos um pouco mais sobre o que pretende. Assim fica muito mais facil ajuda-lo, e o que é mais importante, levando em consideração a filosofia do fórum: será muito mais proveitoso para TODOS. ;)

Enviado: 17 Nov 2007 22:55
por carlos_dornelas
Maligno,
E as inclusões e exclusões?


No caso real não há inclusões ou exclusões de registros, por isso não haverá qualquer interferência nos demais índices.


Alamino Junior
Vai ser um show de "Corruption Detected".
Como o nosso colega Eolo explicou lá em cima, fazer alterações em um indice, e em outro não, é um tanto temerário.


Como disse acima, não haverá inclusões ou exclusões de registros, portanto não haverá qualquer problema em se ter diversos índices.


Eolo, a tua solução foi totalmente eficaz!! Fico muito grato. Havia uns três dias que eu vinha tentando a solução e você matou a pau! Só não entendi por quê a tua solução funcionou e a minha não!

Eu estava usando assim:

for conta=1 to 10
h='ind'+alltrim(str(conta))
index on substr(campo,(conta*2)-1,2) to &h
next

E você corrigiu para:
for conta=1 to 10
a="ind"+alltrim(str(conta))
b="substr(campo,"+alltrim(str((conta*2)-1))+",2)"
index on &b to &a

next

Bom, o que importa é que funcionou perfeitamente!

Obrigado a todos!


Segue abaixo o código funcionando:


clear
set decimals to 5
aq1:={}
aadd(aq1,{'seq','N',4,0})
aadd(aq1,{'dados','C',20,0})
dbcreate('teste',aq1)
use teste
zap
for g=1 to 15
string=''
for k=1 to 10
xx=second()*k
string+=right(str(xx),2)
next
inkey(.2)
append blank
replace seq with g
replace dados with string
next
go top

for conta=1 to 10
a='ind'+alltrim(str(conta))
b='substr(dados,'+alltrim(str((conta*2)-1))+',2)'
index on &b to &a for !(&b==' ')
next

dbedit(4,10,20,68,,'ordem')


Function ordem(modo,ponteiro)
lk:=lastkey()
do case
case modo=4
if lk==27
return(0)
elseif lk==-1
@ 2,0 say 'Indice ... 02'
set index to ind2
@ 2,30 say indexkey()
return(2)
elseif lk==-2
@ 2,0 say 'Indice ... 03'
set index to ind3
@ 2,30 say indexkey()
return(2)
elseif lk==-3
@ 2,0 say 'Indice ... 04'
set index to ind4
@ 2,30 say indexkey()
return(2)
elseif lk==-4
@ 2,0 say 'Indice ... 05'
set index to ind5
@ 2,30 say indexkey()
return(2)
elseif lk==-5
@ 2,0 say 'Indice ... 06'
set index to ind6
@ 2,30 say indexkey()
return(2)
elseif lk==-6
@ 2,0 say 'Indice ... 07'
set index to ind7
@ 2,30 say indexkey()
return(2)
elseif lk==-7
@ 2,0 say 'Indice ... 08'
set index to ind8
@ 2,30 say indexkey()
return(2)
elseif lk==-8
@ 2,0 say 'Indice ... 09'
set index to ind9
@ 2,30 say indexkey()
return(2)
elseif lk==-9
@ 2,0 say 'Indice ... 10'
set index to ind10
@ 2,30 say indexkey()
return(2)
elseif lk==13
**o Enter apaga os digitos referentes ao indice 02 - Tecla F2
xdados=left(dados,2)+' '+right(dados,16)
replace dados with xdados
go top
return(2)
endif
endcase

Enviado: 18 Nov 2007 09:15
por Eolo
Compare a linha INDEX, em cada LOOP, na forma que vc fez e na que eu sugeri. Na segunda, primeiro é resolvido o valor de CONTA...

Código: Selecionar todos

for conta=1 to 10 
  h='ind'+alltrim(str(conta)) 
  index on substr(campo,(conta*2)-1,2) to &h 

  * Conta=1
  *   index on substr(campo,conta*2)-1,2) to ind1
  * Conta=2
  *   index on substr(campo,conta*2)-1,2) to ind2
  * Conta=3
  *   index on substr(campo,conta*2)-1,2) to ind3
  * etc.

next

Código: Selecionar todos

for conta=1 to 10 
  h="ind"+alltrim(str(conta)) 
  b="substr(campo,"+alltrim(str((conta*2)-1))+",2)" 
  index on &b to &h

  * Conta=1
  *   b="substr(campo,1,2)"
  *   index on substr(campo,1,2) to ind1
  * Conta=2
  *   b="substr(campo,3,2)"
  *   index on substr(campo,3,2) to ind2
  * Conta=3
  *   b="substr(campo,5,2)"
  *   index on substr(campo,5,2) to ind3
  * etc.

next

Enviado: 18 Nov 2007 13:44
por carlos_dornelas
Ok, entendido! Muito obrigado.

Antonio Carlos