Como gerar índices com macro?

Fórum sobre a linguagem CA-Clipper.

Moderador: Moderadores

carlos_dornelas
Usuário Nível 3
Usuário Nível 3
Mensagens: 400
Registrado em: 25 Ago 2004 21:54

Como gerar índices com macro?

Mensagem 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
Avatar do usuário
clodoaldomonteiro
Usuário Nível 4
Usuário Nível 4
Mensagens: 821
Registrado em: 30 Dez 2006 13:17
Localização: Teresina-PI
Contato:

Mensagem por clodoaldomonteiro »

Carlos!
Testei a tua rotina e deu tudo certo, qual seria o erro que dá ai com você?
At. Clodoaldo Monteiro
Linguagens: Clipper / Harbour
Área de Atuação: Sistemas de gestão para Prefeituras Municipais
Fones: (86)3223-0653, 98859-0236
www.simplesinformatica.com.br
Avatar do usuário
rochinha
Administrador
Administrador
Mensagens: 4664
Registrado em: 18 Ago 2003 20:43
Localização: São Paulo - Brasil
Contato:

Mensagem 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.
OPS! LINK QUEBRADO? Veja ESTE TOPICO antes e caso não encontre ENVIE seu email com link do tópico para [url=mailto://fivolution@hotmail.com]fivolution@hotmail.com[/url]. Agradecido.

@braços : ? )

A justiça divina tarda mas não falha, enquanto que a justiça dos homens falha porque tarda.
Avatar do usuário
Eolo
Colaborador
Colaborador
Mensagens: 1134
Registrado em: 08 Dez 2005 18:24
Localização: São Paulo - SP

Mensagem 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
carlos_dornelas
Usuário Nível 3
Usuário Nível 3
Mensagens: 400
Registrado em: 25 Ago 2004 21:54

Mensagem 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
Avatar do usuário
Eolo
Colaborador
Colaborador
Mensagens: 1134
Registrado em: 08 Dez 2005 18:24
Localização: São Paulo - SP

Mensagem 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?
carlos_dornelas
Usuário Nível 3
Usuário Nível 3
Mensagens: 400
Registrado em: 25 Ago 2004 21:54

Mensagem 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
Avatar do usuário
Eolo
Colaborador
Colaborador
Mensagens: 1134
Registrado em: 08 Dez 2005 18:24
Localização: São Paulo - SP

Mensagem por Eolo »

Legal. Entendi.
Avatar do usuário
Maligno
Membro Master
Membro Master
Mensagens: 6398
Registrado em: 06 Jul 2004 01:40
Localização: Londrina/PR

Mensagem por Maligno »

E as inclusões e exclusões?
[]'s
Maligno
---
Não respondo questões técnicas através de MP ou eMail. Não insista.
As dúvidas devem ser postadas no fórum. Desta forma, todos poderão
se beneficiar das respostas.

---
Se um dia precisar de uma transfusão de sangue você perceberá como
é importante a figura do doador. Procure o hemocentro de sua cidade e
se informe sobre a doação de sangue, plaquetas e medula óssea. Doe!
Avatar do usuário
alaminojunior
Colaborador
Colaborador
Mensagens: 1717
Registrado em: 16 Dez 2005 21:26
Localização: Ubatuba - SP

Mensagem 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. ;)
Compilador xHarbour 1.2.3 + Embarcadero C++ 7.30
MySQL c/ SQLRDD
HwGui + GTWVG
carlos_dornelas
Usuário Nível 3
Usuário Nível 3
Mensagens: 400
Registrado em: 25 Ago 2004 21:54

Mensagem 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
Avatar do usuário
Eolo
Colaborador
Colaborador
Mensagens: 1134
Registrado em: 08 Dez 2005 18:24
Localização: São Paulo - SP

Mensagem 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
carlos_dornelas
Usuário Nível 3
Usuário Nível 3
Mensagens: 400
Registrado em: 25 Ago 2004 21:54

Mensagem por carlos_dornelas »

Ok, entendido! Muito obrigado.

Antonio Carlos
Responder