Página 1 de 2

Progresso com PACK e COPY FIELDS

Enviado: 22 Set 2007 18:57
por carlos_dornelas
Pessoal, é possível implementar uma barra de progressão quando da utilização dos comandos PACK e COPY FIELDS?

Antonio Carlos

Enviado: 22 Set 2007 19:10
por Maligno
Não. Mas o ideal é não usar PACK. O melhor seria reaproveitar os registros, pra economizar tempo.

Enviado: 23 Set 2007 09:11
por Eolo

Código: Selecionar todos

use arquivo.dbf
arq=0
totalrec=lastrec()
conta=0
x_arecop()
quit

Código: Selecionar todos

FUNCTION X_ARECOP
dbeval( {|| x_arecop2() } )
retu

Código: Selecionar todos

FUNCTION X_ARECOP2
conta=conta+iif((totalrec/30)<30,30,int(totalrec/30))
conta=iif(conta>totalrec,totalrec,conta)
?tran(conta/totalrec*100,"@E 999.9%") // -> mostra evolução
arq=arq+1
c="lixo"+strzero(arq,2,0)
copy to &c next iif((totalrec/30)<30,30,int(totalrec/30))
retu
Antonio Carlos, eu tb procurei muito por isso e não achei. Acabei montando essa função meio capenga aí em cima... Funciona, mas de repente alguém melhora ela... O que eu faço é copiar os registros não deletados para 30 arquivos temporários, depois trago-os de volta com uma outra função semelhante.

Maligno, isso de reaproveitar registros não pode tornar (em determinados casos) o arquivo "fragmentado"?

Enviado: 23 Set 2007 09:14
por Eolo
Ah, um detalhe importante: meus arquivos são normalmente "pequenos", porque eu mando informação antiga pro arquivo morto... Então essa operação de "pack" não toma muito tempo.

Enviado: 23 Set 2007 09:58
por Maligno
isso de reaproveitar registros não pode tornar (em determinados casos) o arquivo "fragmentado"?
Claro. Isso é bem possível de acontecer. Mas é realmente em uma pequena parte dos casos. Pra maioria, reaproveitar é uma opção muito melhor que o PACK.

GasPro - Barra rolagem

Enviado: 23 Set 2007 13:52
por clodoaldomonteiro
Carlos!
Vai ai um exemplo da LIB do GASpro.
Hoje o GAS DOS é gratuito, então voce deve pegar a LIB dela no site da GAS informática.
Eu postei um exemplo ha uns dois dias atrás que tem um link com a lib do GASpro, voce pode baixar se quiser.

Código: Selecionar todos

// PROGRAMA EXEMPLO PARA MOSTRAR BARRA DE ROLAGEM NA TELA QUANDO ESTIVER
// COPIANDO, INDEXANDO OU QUALQUER OUTRA OPERAۂO EM ARQUIVO
// PROGRAMADOR: CLODOALDO MONTEIRO
// DIREITOS...: GAS INFORMATICA
// LIB........: GASP52PM.LIB
// FUNۂO.....: POE_GAUGE(MENSAGEM,TITULO1,TITULO2)
//              A FUNۂO PODE MOSTRAR UMA BARRA DE ROLAGEM OU UM CONTADOR DE REGISTROS

#include "INKEY.CH"

drvmenucen=.f.                            // vari vel para a funcao DBOX
drvcorpad="W+/RB"  ; drvcorbox="W+/B"     // cores default
drvcormsg="W+/N*"  ; drvcorenf="W+/R"
drvcorget="W+/BG"  ; drvcortel="W+/B"
drvcorhlp="GR+/G"  ; drvcortna="GR/N"
drvtitpad="GR+/RB" ; drvtitbox="GR+/B"    // cores dos titulos default
drvtitmsg="GR+/N*" ; drvtitenf="GR+/R"
drvtitget="GR+/BG" ; drvtittel="GR+/B"
drvtithlp="W+/G"   ; drvtittna="W/N"

use EMP new excl                          // ABRE O ARQUIVO EMP PARA TESTAR OS COMANDOS COM A FUNۂO POE_GAUGE

// indexando registros
clea
POE_GAUGE("Criando ¡ndices.",,,13,30)              // MOSTRA UM BOX NA TELA COM UMA MENSSAGEM
INDE ON EMP_COD TO EMP1 EVAL POE_GAUGE() EVERY (LASTREC()/20)     // indexando...
     // emp_cod ‚ um campo do arquivo EMP

// logalizando registros
clea
go top
POE_GAUGE("Pesquisando...|ESC interrompe","AGUARDE...","Processados:",16,28)
LOCA FOR emp_nomecr='xxmaria' WHIL INKEY()!=K_ESC .AND. POE_GAUGE() // tenta localizar registro desejado
      // emp_nomecr ‚ um campo do arquivo EMP
      // Depois do comando WHIL vocˆ pode colocar qualquer fun‡Æo e pode
      // at‚ mostrar um box com uma menssagem e esperando que o usu rio
      // fa‡a alguma a‡Æo.

// copiando arquivos
CLEA
POE_GAUGE("Compactando o arquivo EMP.DBF","AGUARDE!","Registros feitos:",15,28)      // msg de gauge
GO TOP                                             // inicio do dbf
COPY TO tmp WHILE POE_GAUGE()                      // copia reg nao excluido para tmp

RETU                                               //FIM DO PROGRAMA PRINCIPAL

FUNC POE_GAUGE(msg_,tit_,tit_reg,m_l,m_c)          // coloca gauge(BARRA DE ROLAGEM) na tela
STATIC l_g, c_g, ct_g:=0, so_conta                 // linha e coluna do inicio gauge
LOCAL x, defa_dev, i
IF msg_!=NIL                              // mensagem da dbox
   so_conta=(tit_reg!=NIL)                // vai contar ou colocar %
   ct_g=0                                 // contador de registro ja processados
   IF so_conta                            // se vai contar concatena msg que
      msg_+="|*|"+tit_reg+"       0"      // vamos mostrar qtde de reg processados
   ELSE                                   // processo em todo o arq
      msg_+="|*|"+REPL("°",20)            // concatena gauge no final
   ENDI
   x=DBOX(msg_,10,,,.f.,tit_)             // coloca msg na tela
   SETCOLOR(drvtitbox)                    // cor do titulo para gauge
   l_g = m_l                              // linha e
   c_g = m_c                              // coluna de inicio do gauge
   IF so_conta                            // vai contar registro
      c_g+=LEN(tit_reg)+1                 // posiciona cursor apos msg de proc
   ENDI
ELSE                                      // coloca o gauge
   ct_g++                                 // conta quantos ja foi feito
   IF so_conta                            // gauge em contador
      IF INT(ct_g/30)=ct_g/30             // mostra em 30 em 30
         x=RIGHT(SPACE(8)+STR(ct_g),8)    // coloca qtde na tela sem
         FOR i=1 TO 8                     // usar o SAY (pode estar imprimindo)
            POKE(-18432,(l_g*160)+((c_g+i)*2),ASC(SUBS(x,i+1,1)))
         NEXT
      ENDI
   ELSE                                   // gauge com percentual
      @ l_g,c_g SAY REPL("Û",MIN(ct_g,20))     // coloca na msg
   END IF
ENDI
RETURN .t.                              // sempre retorna verdadeiro
Espero ter ajudado, até mais.

Enviado: 23 Set 2007 14:01
por clodoaldomonteiro
Nesse link tem a lib do GAS DOS.

Link de sistema gerado em GAS usando o NODISIMP.
http://suportegas.com.br/portal/downloa ... ST_USB.ZIP

Enviado: 23 Set 2007 16:09
por Eolo
(RETIFICADO)

Clodoaldo, interessante o uso do WHILE... Não tinha pensado nisso. Testei com o COPY e funciona legal. Só não entendi por que é necessária a LIB do GAS, se o que manda é o WHILE. Resumindo o que vc postou:

Código: Selecionar todos

use arquivo.dbf
priv conta:=0
priv tudo:=lastrec()
go top
copy to temp while copia()
quit

function copia
conta++
@10,10 say conta/tudo*100 //-> mostra %
retu .t.
Só um problema: tentei rodar o PACK e não consegui. Você conseguiu com o código que vc postou?

poe_gauge

Enviado: 23 Set 2007 16:55
por clodoaldomonteiro
Eolo!
É que eu montei um sistema para o Carlos ver, conforme o link acima, e nesse exemplo uso a função poe_gauge() para montar uma barra de rolagem e a função dbox(), para montar vários box.
Depois, é claro, o Carlos vai mundar o uso desse exemplo para ficar de acordo com o gosto dele.

Espero que eu tenha me explicado.[/b]

Enviado: 23 Set 2007 17:14
por Eolo
a) Ok, eu entendi. Só quis ressaltar que o que manda é o WHILE, dá pra fazer sem o GAS... :-))

b) Vc não respondeu sobre o PACK. Você conseguiu, afinal? Eu, não.


Aliás, tem um 'complicômetro' nesse jeito de trabalhar com o COPY: o percentual de evolução não fecha... Seguinte: pra mostrar esse percentual, tem que comparar um contador com o total de registros - obtido com LASTREC(), certo? Só que o LASTREC() traz o TOTAL de registros (deletados ou não), então, dependendo do número de deletados, dá um resultado sem sentido.

Exemplo: DBF com 1.000 registros, sendo 100 deletados. LASTREC() retorna 1.000. Como vc está com o SET DELETED ON (pra pegar só os não deletados), a conta vai de 1/1000 até 900/1000, ou seja, pula os deletados e o percentual pára nos 90%... Dá pra fazer COUNT TO CONTADOR FOR !DELETED(), mas isso toma muito tempo e é ruim de usar com arquivos muito grandes.

No caso do INDEX isto não acontece porque todos os registros (deletados ou não) são indexados.

Enviado: 23 Set 2007 18:11
por sygecom
Boa, essa do COPY, uso muito isso no MSYQL para DBF eu não tinha nd desse tipo...legal.

Abraços
Leonardo Machado

Enviado: 23 Set 2007 18:14
por clodoaldomonteiro
Eolo!
Eu não uso muito o lastrec() e sim o comando COUNT, que acho que é a mesma coisa e fiz um teste no FOX com um DBF qualquer e deu certo, mais ou menos assim:

Código: Selecionar todos

USE ARQ
SET DELE ON         //seleciona só os registros ativos
COUNT TO M_VAR //cria uma variável com o total de registros ativos
Eu usei o COUNT para jogar na variável M_VAR somente os registros ativos com o comando SET DELE ON.
Acho que com o LASTREC() dá certo também o comando chave aqui é o SET DELE ON.

Você pode substituir o PACK pela sequencia de comandos a seguir:

Código: Selecionar todos

USE ARQ         //abre o seu arquivo
SET DELE ON   //seleciona somente os registros ativos
GO TOP           //vai para o início do arquivo
COPY TO TEMP WHILE COPIA()  //copia para um arquivo temporário usando uma função para mostrar a progressão dos registros
CLOSE ALL      //fecha todos os arquivos
ERASE ARQ.DBF      //apaga arquivo com registros deletados
RENAME TEMP.DBF TO ARQ.DBF   //renomeia arquivo temporário
... depois você deve reconstruir os índices novamente.
Não testei a rorina acima, mais o GAS gera assim e sempre dá certo, salvo algum erro não percebido por mim.

Espero ter ajudado, até mais.

Enviado: 23 Set 2007 19:28
por Maligno
Eu não uso muito o lastrec() e sim o comando COUNT, que acho que é a mesma coisa
O comando COUNT é traduzido para uma expressão complexa utilizando DBEval() pra realizar uma contagem filtrada, enquanto que o LastRec() é uma função que só retorna a quantidade de registros.

Enviado: 23 Set 2007 20:17
por clodoaldomonteiro
Então quer dizer que a LASTREC() sempre dá a quantidade total de registros, mesmo usando o SET DELE ON?
Vou dá uma revisa nos meus fontes.

Enviado: 23 Set 2007 20:47
por Maligno
LastRec() fornece a quantidade de registros físicos do DBF, independentemente do estado do SET DELETED ou SET FILTER.