Página 1 de 1

Um problema "daqueles"

Enviado: 25 Abr 2005 21:02
por Anderson J. Freitas
Tenho um arquivo, com índice primário = loja+produto, onde são gravados os seguintes dados : loja, produto, somatório das entradas do produto e somatório das saídas do produto. Os dados ficam assim no arquivo :

Código: Selecionar todos

 
loja produto entrada saida
  01 000001       100     50
  01 000002         50     25
  02 000002         75     75
  02 000003       200    150
  03 000001       125      25
Até aqui tudo bem. Porém o meu chefe teve a brilhante idéia de querer que o arquivo seja exibido (com direito a navegar pelos produtos, semelhante navegação com achoice) com filtro, ou seja :

Filtrar pela loja = 02

Código: Selecionar todos

loja produto entrada saida
  02 000001         75     75
  02 000002       200    150

Filtrar pela loja = 99, neste caso será exibido o somatório dos produtos deste arquivo :

Código: Selecionar todos

loja produto entrada saida
  99 000001       225     75
  99 000002       125    100
  99 000003       200    100
Eu até consegui fazer, mas ficou "monstruoso", e o pior é que ele quer isso em outros arquivos do programa, então não pode ser nada deste tipo, pois o programa é bem grande (15 prg´s). Isso está esquentando tanto minha cabeça que estou até pensando em pedir demissão. Teria que ser algo milagroso, como foi o sx_setscope. Como esse comando revolucionou minha vida.

Se alguém puder salvar o meu emprego, vou ficar eternamente grato.

Enviado: 26 Abr 2005 00:46
por vagucs
Pode usar indice temporario com a clausula WHEN ou mesmo no seu caso, que vc está usando SIX, verifique o manual dela que tem uma rotina que vc pode demarcar os limites do indice como se fosse um filtro.

Eu não uso drive six, mas não é complicado de achar que rotinas são estas.

Enviado: 26 Abr 2005 08:27
por Spitzer
Como você está exibindo os dados deste arquivo? Com DBEdit(), TBrowse...?
Se for com um dos modos acima, dá pra usar o sx_setscope() no arquivo que possui os dados e que está selecionado!

Não lembro bem onde colocar o filtro sx_... no DBEdit() ou no TBrowse, e agora estou no trabalho.
Mas confirme minha primeira pergunta e, se for o caso, à noite dou uma olhada nos meus fontes de Clipper em casa e te passo como faço isto.

Enviado: 26 Abr 2005 11:45
por Anderson J. Freitas
Em resposta ao amigo Spitzer, utilizo uma função que desenvolvi semelhante ao DBEdit/Achoice. Ela permite navegar pelo arquivo, além de permitir que se programem teclas para ações.

Em resposta ao amigo vagucs, no caso de ser uma loja apenas, até que funcionaria a indexação. Porém no caso de exibir o somatório dos itens iguais, desprezando a loja é que a coisa complica. Não estava querendo usar arquivo temporário. Pois no problema apresentado seria apenas um, mas tem outros arquivos com o mesmo problema. Também não estava querendo montar rotina muito longas [do while !eof()] para não causar um delay no programa.

Espero não estar sendo chato! Mas é que o negócio é sério : O patrão quer velocidade também. Tipo assim : pressionou uma tecla, filtra loja "01", pressionou outra, exibe somando itens iguais.

Grato

Fico aguardando...

Enviado: 26 Abr 2005 12:50
por Spitzer
Não uso achoice(), portanto, não conheço-a.

Em casa, à noite, darei uma olhada como funciona a função achoice() e vejo se consigo montar alguma coisa para você usando as funções achoice() e sx_setscope().
Ou então, monto em DBEdit(), pois lembro-me que na função DBEdit(), em alguns casos, na função de usuário executada pelo DBEdit(), uso o sx_setscope(). Daí você repassa a idéia para a função achoice() (desde que a função achoice() execute uma função de usuário).

Sobre como selecionar os dados da loja "01", loja "02"...
Não creio que pressionar uma tecla e filtrar os dados da loja "01", outra tecla e filtrar os dados da loja "02"... seja a melhor solução!
Sugiro que ao pressionar uma tecla (F2, por exemplo), seja exibido uma janela com um campo na tela, tipo "Informe a Loja [ ]", com um get no campo "[ ]", onde ele digitará a loja que quer e a partir daí você refaz o filtro.
Da forma como você sugeriu, no caso de uma nova loja, você terá que reprogramar outra tecla de função para tal.

Até mais à noite...

Enviado: 26 Abr 2005 21:41
por Mário Isa
q tal postar pelo menos a rotina q faz a exibição?
envie p mim no msg particular ou coloque aki para todos verem.

como disse Spitzer não é bom colocar uma tecla para cada loja pq assim vc fica limitado ao numero de teclas. Temos de F1 a F10 se ultrapassa 10 lj terá que utilizar Ctrl+F1 Shift +F1.

Mas conheço uma maneira de, ao navegar pelo dbedit() quando digitar 01 ou 02 ou 03 e até 99 ele filtrar e dbeditar ali mesmo.
o q acha?

Enviado: 27 Abr 2005 03:01
por Spitzer
Aproveitando o tópico...

Mario Isa, a sugestão que lhe enviei por e-mail sobre imprimir arquivo .doc com start deu certo?

Agora, ao Anderson:

Estava esquecendo da rotina que lhe prometi! Lembrei-me agora!
E vendo o tópico, lembrei que tinha alguma coisa aqui de acordo com a sugestão do Mário.
Não é com a função achoice(), mas sim com a função dbedit().
Mas a rotina é bem fácil de ser entendida. Só tive que comentá-la bem porque não sei qual a sua familiaridade com a dita cuja!

O que deve ser feito antes de compilar e linkar:

Criar um arquivo dbf chamado "movim.dbf", com a seguinte estrutura:
- Campo "LOJA", tipo Character, tamanho 2;
- Campo "PRODUTO", tipo Character, tamanho 6;
- Campo "ENTRADA", tipo Numeric, tamanho 11, com 2 decimais;
- Campo "SAIDA", tipo Numeric, tamanho 11, com 2 decimais.
Popular o arquivo "movim.dbf" com alguns registros.

Ou, se preferir, mudar no fonte de exemplo:
- O nome do arquivo "movim.dbf";
- Os nomes dos campos do arquivo;
- As máscaras de exibição dos campos;
- Os nomes dos cabeçalhos de cada campo.
- Os campos do índice, nome do índice e nome da tag.
Se bem que acho que é mais fácil criar um DBF com a estrutura acima e populá-lo. Aí você não precisará mudar nada no fonte!

Como usar:

Compilar e linkar o fonte de exemplo com o drive SIx2.
Ao executar, será exibido o browse com os campos do arquivo dbf.
O índice é "loja+produto" e parti do princípio que seja um índice único (se bem que não vem ao caso...).

Portanto, como exemplo, com o browse em exibição, se você digitar:
"04" -> Será filtrado somente os dados da loja "04";
"04000002" -> Será filtrado a linha da loja "04" que contenha o produto "000002".

A tecla "BackSpace" apaga do filtro o último caracter digitado.
A tecla "Ctrl+BackSpace" apaga do filtro tudo que foi digitado.
As teclas "Enter" e "Esc" abortam a função dbedit().

Está aí uma forma de você usar também este exemplo como uma lista de pesquisa. Para isto, basta reprogramar o "Esc" para ir ao final do arquivo (não selecionar nada) e o "Enter" apenas para abortar a dbedit(), ficando corrente a linha em que estava posicionado.

Se preferir, diga-me e lhe envio os arquivos por e-mail.

Espero que esta solução lhe ajude com seu problema.

Código: Selecionar todos

#include "sixnsx2.ch"

REQUEST SIXNSX
RDDSETDEFAULT("SIXNSX")

SET EXACT OFF
SET SCOREBOARD OFF
SET DATE FORMAT "dd/mm/yyyy"
SET CENTURY ON
SET EPOCH TO 1950
SET DELETED ON
SET WRAP ON
SETCANCEL(.t.)

// Estas tres linhas abaixo deverao
// estar na sua rotina de indexacao
USE movim NEW
INDEX ON movim->loja+movim->produto TAG movim1
DBCLOSEALL()

// Aqui e a rotina
CLS

USE movim INDEX movim NEW
SET ORDER TO TAG "movim1"

// Chama a funcao que prepara a lista da DBEDIT()
Lista()

DBCLOSEALL()

RETURN

************************************************************

// Funcao que prepara a lista da DBEDIT()

STATIC FUNCTION Lista()

LOCAL cField  := {},;  // Campos a serem exibidos
      cMask   := {},;  // Mascara dos campos a serem exibidos
      cHeader := {}    // Cabecalho dos campos a serem exibidos

PRIVATE cFiltro := SPACE(0)

cField  := {"movim->loja","movim->produto",;
            "movim->entrada","movim->saida"}
cMask   := {"","","@E 99,999,999.99","@E 99,999,999.99"}
cHeader := {"Loja","Produto","      Entrada","        Saida"}

(ALIAS())->(DBEDIT(4,10,(MAXROW() - 4),(MAXCOL() - 10),cField,;
                   "Edicao",cMask,cHeader,CHR(196),CHR(179)))

RETURN NIL

* Fim de [Lista]

* Fim do programa

************************************************************

// A funcao "Edicao()" devera estar no seu arquivo de funcoes

/*
Funcao Edicao()
Funcao executada para tratar excessoes da DBEDIT()
Parametro: pcModo
Parametro automatico que indica o estado da DBEDIT()

PARAMETRO pcModo A SER UTILIZADO NA FUNCAO
Na chamada de uma funcao do usuario pela DBEDIT():
0 = Pressionou teclas, mas nao ha pendencias
1 = O cursor foi para o inicio do arquivo
2 = O cursor foi para o fim do arquivo
3 = Nao ha registros na area de trabalho
4 = Houve uma excessao a ser tratada

No retorno da funcao do usuario a DBEDIT()
0 = Aborta a DBEDIT()
1 = Continua a DBEDIT()
2 = Forca leitura, exibicao e continuacao da DBEDIT()
*/

FUNCTION Edicao(pcModo)

LOCAL nRetModo := 1 // Forca a continuacao da DBEDIT()

@23,00 SAY SPACE(80)  // Limpa a linha de mensagens
// Havendo caracteres digitados na variavel [cFiltro], exibe-os
IF !EMPTY(cFiltro)
   @23,30 SAY cFiltro
// Nao havendo caracteres digitados na variavel [cFiltro],
// exibe, para o usuario, as teclas de navegacao
ELSE
   @23,06 SAY "Use "+CHR(25)+CHR(24)+CHR(26)+CHR(27)+" End Home "+;
              "PgDn PgUp Ctrl+End Ctrl+Home Ctrl+PgDn Ctrl+PgUp"
ENDIF

IF pcModo = 4 // Trata uma excessao da DBEDIT()
   // Se pressionou uma tecla (espaco, A...Z, a...z, 0...9
   // e alguns caracteres especiais, como +, -, (, ), etc),
   // monta a variavel [cFiltro] que sera o filtro da SIx2
   // OBS.: Nao trata o pressionamento das letras acentuadas
   IF LASTKEY() >= 32 .AND. ;
      LASTKEY() <= 126 // (espaco, A...Z, a...z, 0...9, etc.)
      cFiltro := LTRIM(cFiltro)+CHR(LASTKEY())
      IF (ALIAS())->(!DBSEEK(cFiltro))
         TONE(900,1)
         cFiltro := SUBSTR(cFiltro,1,LEN(ALLTRIM(cFiltro)) - 1)
      ENDIF
      (ALIAS())->(SX_SETSCOPE(0,cFiltro)) // Ativa o filtro
      (ALIAS())->(SX_SETSCOPE(1,cFiltro))
      (ALIAS())->(DBGOTOP())
      nRetModo := 2 // Forca a leitura e continua a DBEDIT()
   // Se pressionou <BackSpace>, apaga da variavel [cFiltro]
   // o ultimo caracter digitado, refazendo ou desativando o
   // filtro, coforme o caso
   ELSEIF LASTKEY() = 8 // <BackSpace>
      cFiltro := SUBSTR(cFiltro,1,LEN(ALLTRIM(cFiltro)) - 1)
      // Enquanto ha caracteres na variavel [cFiltro] para
      // serem filtrados, refaz o filtro
      IF !EMPTY(cFiltro)
         (ALIAS())->(SX_SETSCOPE(0,cFiltro))
         (ALIAS())->(SX_SETSCOPE(1,cFiltro))
      // Quando nao ha mais caracteres na variavel [cFiltro]
      // (apagou tudo com <BackSpace>), desativa o filtro
      ELSE
         (ALIAS())->(SX_CLRSCOPE(0))
         (ALIAS())->(SX_CLRSCOPE(1))
      ENDIF
      (ALIAS())->(DBGOTOP())
      nRetModo := 2 // Forca a leitura e continua a DBEDIT()
   // Se pressionou <CtrlBackSpace>, limpa todos os caracteres
   // da variavel [cFiltro] e desativa o filtro
   ELSEIF LASTKEY() = 127 // <CtrlBackSpace>
      cFiltro := SPACE(0)
      (ALIAS())->(SX_CLRSCOPE(0))
      (ALIAS())->(SX_CLRSCOPE(1))
      (ALIAS())->(DBGOTOP())
      nRetModo := 2 // Forca a leitura e continua a DBEDIT()
   // Se pressionou <Enter> ou <Esc>, limpa os caracteres da
   // variavel [cFiltro], desativa o filtro e aborta a DBEDIT()
   ELSEIF LASTKEY() = 13 .OR. ;
          LASTKEY() = 27 // <Enter> ou <Esc>
      cFiltro := SPACE(0)
      (ALIAS())->(SX_CLRSCOPE(0))
      (ALIAS())->(SX_CLRSCOPE(1))
      (ALIAS())->(DBGOTOP())
      nRetModo := 0 // Aborta a DBEDIT()
   ENDIF
ENDIF

RETURN nRetModo

* Fim de [Edicao]

Enviado: 27 Abr 2005 09:57
por Mário Isa
:D
ok. ainda não testei a rotina com comando start.
o q percebi é q com os acessórios do windows eu posso fazer:
start notepad mario.txt /p
start wordpad mario.doc /p

mas se fizer start winword mario.doc /p não imprime
porém se start winword mario.doc ele abre o word com o mario.doc normal.

no xp sei q é diferente porém ainda não testei.

mas se abrir o word prá mim já está muito bom. é o q preciso.

Abraços