modificar nome de campo em dbf

Fórum sobre a linguagem CA-Clipper.

Moderador: Moderadores

Glauco Cruz Costa
Usuário Nível 3
Usuário Nível 3
Mensagens: 102
Registrado em: 15 Dez 2005 22:02
Localização: Brasília/DF
Contato:

modificar nome de campo em dbf

Mensagem por Glauco Cruz Costa »

Procurei muito, mas não encontrei.
Alguém sabe de algum comando ou função que altera o nome de um campo em um dbf?
Exemplo: Meu dbf tem os campos PRONTUARIO, CLINICA, MEDICO, DATA, LOCAL, COD
Gostaria de mudar o nome do campo COD para ATIVIDADE, mas tem que ser na execução.

É que eu quero mandar os campos para um outro dbf. E neste outro dbf o campo COD se chama ATIVIDADE.
E eu to apanhando muito pra passar. De repente se eu alterasse o campo durante o processo, facilitaria. Depois, eu renomearia novamente.
Nossa!!!! Eu ainda sou iniciante nisso. O pior é que desde 1997 eu ainda sou iniciante em Clipper.
Mas, ainda bem que existe esse fórum.
alxsts
Colaborador
Colaborador
Mensagens: 3092
Registrado em: 12 Ago 2008 15:50
Localização: São Paulo-SP-Brasil

Re: modificar nome de campo em dbf

Mensagem por alxsts »

Olá Glauco,

ficou meio nebulosa a tua intenção.
Não existe nenhum comando ou função do próprio Clipper que altere a estrutura em tempo de execução. Se voce precisar fazer isto, terá que montar a estrutura desejada num array e criar uma tabela nova, utilizando este array criado, via função DBCreate().
Parece que voce já tem as duas tabelas, total de campos e tipos de campos iguais, sendo que na segunda o campo COD é chamado de ATIVIDADE. Neste caso, não vejo necessidade de alteração de estrutura. É só ler a primeira tabela e gravar os dados na segunda.
De qualquer forma, preparei um exemplo que contempla os dois cenários. Segue abaixo:

Código: Selecionar todos

// PRONTUARIO, CLINICA, MEDICO, DATA, LOCAL, COD

#Include  "Dbstruct.ch"

FUNCTION AltStru()

   LOCAL aStru, nPos
   
   BEGIN SEQUENCE

      // Abrir o Arquivo com a estrutura original
      Use "Tabela1" SHARED New
      // obtem a estrutura da Tabela1
      aStru := Tabela1->( DbStruct() )
      
      // sei que o campo COD, que desejo alterar, 
      // é o sexto campo na estrutura da tabela...
      // então altero o nome de COD para ATIVIDADE:
      // Note que aStru é um Array de Arrays. Estou
      // alterando a sexta linha, coluna 1 (DBS_NAME),
      // onde é armazenado o nome do campo.
      aStru[ 6, DBS_NAME ] := "Atividade"
      
      // Se eu não soubesse que a coluna COD é a sexta
      // e soubesse apenas o nome da coluna (COD), teria 
      // que procurar em aStru qual a linha referente à
      // coluna COD. Neste caso faria assim:
      
      // procura em aStru:
      // nPos := AScan( aStru, { |e| e[ DBS_NAME ] == "COD" } )
      // se encontrou,
      // IF nPos > 0
      //    aStru[ nPos, DBS_NAME ] := "Atividade"   
      // ELSE
      //    Alert( "Erro ao gravar alterar estrutura...;Programa cancelado." ) 
      //    Break
      // ENDIF

      // Cria uma tabela com a nova estrutura:
      DBCreate( "Tabela2", aStru )
      
      // abre a nova tabela para uso...
      Use "Tabela2" EXCLUSIVE New

      // Ler os registros originais e gravar na tabela com a estrutura nova

      Tabela1->( DbGoTop() )
      
      WHILE Tabela1->( ! Eof() )
         Tabela2->( DbAppend() )
         IF ! NetErr()
            Tabela2->PRONTUARIO := Tabela1->PRONTUARIO
            Tabela2->CLINICA    := Tabela1->CLINICA 
            Tabela2->MEDICO     := Tabela1->MEDICO 
            Tabela2->DATA       := Tabela1->DATA 
            Tabela2->LOCAL      := Tabela1->LOCAL 
            Tabela2->ATIVIDADE  := Tabela1->COD      
         ELSE
            Alert( "Erro ao gravar tabela destino...;Programa cancelado." ) 
            Break
         ENDIF 
         Tabela1->( DbSkip() )
      ENDDO
      
   END SEQUENCE
   
   DbCloseAll()
    
   RETURN NIL
//------------------------------------------------------------------------------

// Cópia do arquivo DBStruuct.Ch presente na instalação padrão do Clipper5 em 
// C:\Clipper5\Include: 

/***
*
*  Dbstruct.ch
*
*  DBSTRUCT() function definitions
*
*  Copyright (c) 1990-1993, Computer Associates International, Inc.
*  All rights reserved.
*
*/

/*
// Subscripts for field structure array
#define DBS_NAME    1
#define DBS_TYPE    2
#define DBS_LEN     3
#define DBS_DEC     4

// Length of array
#define DBS_ALEN    4

#define _DBSTRUCT_CH

*/
//------------------------------------------------------------------------------
Por favor, poste informando se serviu ou se tiver dúvidas adicionais.

[]´s
AlxSts
[]´s
Alexandre Santos (AlxSts)
Avatar do usuário
Maligno
Membro Master
Membro Master
Mensagens: 6398
Registrado em: 06 Jul 2004 01:40
Localização: Londrina/PR

Re: modificar nome de campo em dbf

Mensagem por Maligno »

Não existe função nativa do Clipper para alterar o nome de um campo. Mas esse nome consta no cabeçalho do DBF. Com uma função de baixo nível, que o Clipper tem, e conhecendo a estrutura de um DBF, você pode criar uma função dessas. Ou, sendo um único DBF (acredito que não seja o caso), você pode usar um editor hexa pra fazer isso.

Mas quando são vários arquivos, a técnica mais comumente utilizada é a criação de um novo DBF com a nova estrutura e seu povoamento a partir do DBF antigo.
[]'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!
Glauco Cruz Costa
Usuário Nível 3
Usuário Nível 3
Mensagens: 102
Registrado em: 15 Dez 2005 22:02
Localização: Brasília/DF
Contato:

Re: modificar nome de campo em dbf

Mensagem por Glauco Cruz Costa »

Eu quero fazer isso somente uma vez. Mas não é em execução com o programa sendo trabalhado.
Eu apenas quero transportar os dados para o outro dbf com a estrutura diferente. E mais, na tabela destino, já há outros dados, portanto não se tratará de dar append, mas apenas de se fazer alteração.
E tb na tabela de origem há campos que a tabela de destino não possui:
DBF origem - campos: prontuario, clinica, medico, crm, paciente, data, atividade, turno, prof.
DBF destino - campos: prontuario, data, local, cod.

Eu quero atualizar o DBF destino com os dados do DBF origem:
prontuario, data, clinica (local), atividade (cod).

Ou seja, no dbf origem um campo é clinica; no destino é local.
No dbf origem um campo é atividade; no de destino é local.
alxsts
Colaborador
Colaborador
Mensagens: 3092
Registrado em: 12 Ago 2008 15:50
Localização: São Paulo-SP-Brasil

Re: modificar nome de campo em dbf

Mensagem por alxsts »

Olá Glauco.

Foi por isso que escrevi "ficou meio nebulosa a tua intenção".
Talvez soe esquisito mas, programação de computadores é uma arte exata...Se não soubermos o que temos que programar, o resultado certamente será aquele que não esperamos. Assim, quanto mais informação voce passar. melhor.

- O que quer dizer com "Eu quero fazer isso somente uma vez. Mas não é em execução com o programa sendo trabalhado. "?

- Considerando a frase "...Eu apenas quero transportar os dados para o outro dbf com a estrutura diferente. E mais, na tabela destino, já há outros dados, portanto não se tratará de dar append, mas apenas de se fazer alteração...." suponho:
1 - o DBF destino é indexado pelo campo Prontuário
2 - Voce quer ler o DBF origem, pesquisar o prontuário deste no DBF destino.
3 - Se o prontuário for encontrado no DBF destino, gravar neste os campos data, clinica (local), atividade (cod) do DBF origem. O que fazer se não encontrar? Ignorar?

Estou certo? Poste suas observações e ou correções. Depois te ajudo. É fácil alterar o código que postei para fazer isto. Insisto: só é preciso saber o que temos que programar.

[]´s
AlxSts
[]´s
Alexandre Santos (AlxSts)
Glauco Cruz Costa
Usuário Nível 3
Usuário Nível 3
Mensagens: 102
Registrado em: 15 Dez 2005 22:02
Localização: Brasília/DF
Contato:

Re: modificar nome de campo em dbf

Mensagem por Glauco Cruz Costa »

Eu só quero copiar de um dbf para outro, atualizando campos.
Ninguém trabalhando é ninguém usando o sistema. Assim, eu o abrirei exclusive sem problemas.
O problema é que eu quero copiar somente os campos que possuem uma data específica. E tenho que encaixá-los em dois dos campos de nomes diferentes.
Não é todos, conforme coloquei antes.
Se fosse todos, eu abria o DBU e só renomeava os campos. Deu para entender?


E um outro problema que me está enculcando agora é o seguinte:

Tenho um outro dbf em que as datas foram armazenadas sem o set epoch, ou seja, os campos foram armazenados como 1900, mas, no formato "xx/xx/xx"
Quando eu uso set epoch 2000 em uma pesquisa, os dados armazenados com a época anterior não aparecem na pesquisa. Parece lógico.
Mas, eu gostaria de poder copiá-los (atualizar os dados dele) para o outro dbf, porém eles vindo com a data e set epoch 2000. Isso pq o sistema que usa o 2º dbf, usa o set epoch 2000.
Será que se eu usar o set epoch para pesquisar, e depois usar o set epoch 2000 antes do replicate resolve?
Avatar do usuário
Maligno
Membro Master
Membro Master
Mensagens: 6398
Registrado em: 06 Jul 2004 01:40
Localização: Londrina/PR

Re: modificar nome de campo em dbf

Mensagem por Maligno »

Para o primeiro problema, que deu origem a esta thread, como há o detalhe da filtragem, não há como escapar: você terá de fazer um programa de exportação de dados, que leve em conta o filtro que você precisa ativar.

Quanto ao segundo problema, o de data, no arquivo de dados a data sempre será armazenada no formato ANSI, que é AAAAMMDD. Ou seja, você tem a informação de século. O que foi gravado na informação do século do registro vai depender do valor de SET EPOCH no momento em que os dados foram inseridos no programa.
[]'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
Pablo César
Usuário Nível 7
Usuário Nível 7
Mensagens: 5312
Registrado em: 31 Mai 2006 10:22
Localização: Curitiba - Paraná

modificar nome de campo em dbf

Mensagem por Pablo César »

O que foi gravado na informação do século do registro vai depender do valor de SET EPOCH no momento em que os dados foram inseridos no programa.
Ou seja... muito provável que as datas em que foram gravadas ficaram no século passado. Isto é, datas com ano 2004 devem ter ficado 1904. Seria bom você abrir o bd e aplicar o SET CENTURY ON para ver como estão essas datas. Se você tiver certeza de que está tudo correto, então não se preocupe quanto ao tratamento desse campo data mas se contiver "alguns", você será obrigado a passar por uma função que transforme essa data corretamente. Se quiser utilizar veja como eu usei num caso semelhante:

Código: Selecionar todos

nova_data:=MUDATA(DATA)  // chama a função

FUNCTION MUDATA(XDT)
XYD:=(RIGHT(ALLTRIM(STR(YEAR(XDT))),2))
XYA:=(RIGHT(ALLTRIM(STR(YEAR(DATE()))),2))
IF VAL(XYD)>VAL(XYA)
   IF (VAL(XYD))-(VAL(XYA))<2
      XDT:=CTOD( SUBSTR(DTOC(XDT),1,6)+"20"+XYD )
   ELSE
      XDT:=CTOD( SUBSTR(DTOC(XDT),1,6)+"19"+XYD )
   ENDIF
ELSE
   XDT:=CTOD( SUBSTR(DTOC(XDT),1,6)+"20"+XYD )
ENDIF
RETURN XDT
Quanto a primeira questão, tem duas formas. Uma é a mais elaborada, porém a mais indicada caso você precise tratar o campo DATA, que seria baseada no código que o colega alxsts indicou. Mas se não houver necessidade de tratar o campo DATA, eu acho mais prático mudar a estrutura do DBF em que encontra-se os dados e logo dar um APPEND FROM ja com os nome "reconciliados" e depois retornar os nomes como estavam. Isto pode ser feito também, copiando para um outro arquivo temporário em vez do arquivo de origem (a fim de evitar qualquer acidente inesperado). Mas claro esta opção parece meio redundante (no entanto prática) e se ainda escolher a importação registro por registro, claro que não vai fazer mal algum.
Um clip-abraço !

Pablo César Arrascaeta
Compartilhe suas dúvidas e soluções com todos os colegas aqui do fórum.
Evite enviar as dúvidas técnicas por MPs ou eMails, assim todos iremos beneficiar-nos.
Glauco Cruz Costa
Usuário Nível 3
Usuário Nível 3
Mensagens: 102
Registrado em: 15 Dez 2005 22:02
Localização: Brasília/DF
Contato:

Re: modificar nome de campo em dbf

Mensagem por Glauco Cruz Costa »

Obruigado.
Depois de muito quebra-cabeça, consegui bolar essa rotina que deu certo:

SET EPOCH TO 2000
SET DATE BRITISH
USE RETORNO
GO TOP
DO WHILE .NOT. EOF()
IF DATA <> CTOD(" / / ")
A = DATA
B = DTOC(DATA)
REPLACE DATA WITH CTOD(B)
ENDIF
SKIP
ENDDO

Aqui eu modifiquei os campos datas para caracteres em cada registro. Depois, eu os transformei novamente em data. E como o set epoch estaava 2000, as datas foram gravadas no formato de 2000. Aí ficou mais fácil, pois eu faço uma cópia do dbf, para não atrapalhar o outro sistema, e nessa cópia eu uso a rotina acima para transformar as datas, e, após, eu posso atualizar o outro dbf, adaptando uma rotina que um outro amigo postou em uma outra dúvida minha aqui no forum, a que se segue:

use arquiv01.dbf new excl
inde on prontuario to temp
set inde to temp
use arqui01.dbf new excl
go top
do whil !eof()
sele arquiv01
seek arqui01->prontuario
if !found()
?"Erro - Prontuário não localizado"
?prontuario
else
repl data with arqui01->data
repl cod with arqui01->cod
repl local with arqui01->local
endi
sele arqui01
skip
endd


Vlw! :))
Glauco Cruz Costa
Usuário Nível 3
Usuário Nível 3
Mensagens: 102
Registrado em: 15 Dez 2005 22:02
Localização: Brasília/DF
Contato:

Re: modificar nome de campo em dbf

Mensagem por Glauco Cruz Costa »

:(
Na verdade, ainda não deu certo.
Em um dbf, as datas foram gravadas sem set epoch, ou seja, ficaram no padrão 1900.
Mesmo eu tendo transformado elas com dtoc, depois, voltado elas para o normal com ctod, estando o set epoch to 2000, não ficou gravado como 2000.
Será que há outra solução?
Vejam como fiz:

set date british
set epoch to 2000
use retorn
go top
DO WHILE .NOT. EOF()
IF DATA <> CTOD(" / / ")
A = DATA
B = DTOC(DATA)
REPLACE DATA WITH CTOD(B)
ENDIF
SKIP
ENDDO
close

// essa rotina abaixo deu certo com um um outro dbf que estava já gravado em set epoch to 2000.
// o problema mesmo está sendo transformar essas datas para seculo XXI.
use arqui01.dbf new excl // este possui seu executavel em set epoch 2000
inde on prontuario to temp
set inde to temp
use retorn.dbf new excl // este possui seu executavel sem set epoch, ou seja, set epoch to 1900, padrão do clipper. Por isso, ele gravou as datas nela como séc. XX.
go top
do whil !eof()
sele arqui01
seek retorn->prontuario
if !found()
?"Prontuário não localizado"
? prontuario
else
repl data with retorn->data
repl cod with retorn->clin // o cod em arquiv01, em retorn eh clin
repl local with retorn->CLINICA // o local em arquiv01, em retorn eh clinica
endi
sele retorn
skip
endd
Avatar do usuário
Pablo César
Usuário Nível 7
Usuário Nível 7
Mensagens: 5312
Registrado em: 31 Mai 2006 10:22
Localização: Curitiba - Paraná

modificar nome de campo em dbf

Mensagem por Pablo César »

Na verdade, ainda não deu certo.
Em um dbf, as datas foram gravadas sem set epoch, ou seja, ficaram no padrão 1900.
Mesmo eu tendo transformado elas com dtoc, depois, voltado elas para o normal com ctod, estando o set epoch to 2000, não ficou gravado como 2000.
Será que há outra solução?
Glauco, Glauco... você não leu com atenção o que eu postei e nem o que colega Maligno falou sobre a questão datas. Esse código seu não iria dar certo sem fazer alterações que tratem as datas que foram gravadas no SET EPOCH 1900 no passado. Por isso você vai ter que tratar na marra e por isso postei aquele código. Pois a data foi gravada com o ano errado e que no seu sistema passou desapercebido em virtude de não exibir os quatro dígitos do ano, mas na realidade estão lá... então ja que você viu que existem registros com ano errados, faça uso da rotina que postei. E se precisar de ajuda: poste suas dúvidas que iremos lhe atender.
Um clip-abraço !

Pablo César Arrascaeta
Compartilhe suas dúvidas e soluções com todos os colegas aqui do fórum.
Evite enviar as dúvidas técnicas por MPs ou eMails, assim todos iremos beneficiar-nos.
Responder