Ordenação ClientDataSet...
Colegas..
preciso fazer uma ordenação num determinado número de registros de uma tabela, mas esta ordenação não pode ser passada via SQL, isto é, a ordenação é um campo inexistante na tabela..
assim :
Tenho um sequencial 00000001, 00000002, 0000003. (no banco)
No meio destes números pra ser mais preciso antes da segunda casa, na hora da impressão do sequencial eu adiciono três caracteres aleatórios :
007250000001, 001980000002, 009760000003.
Se eu ordenar por sequencial irá aparecer assim :
007250000001
001980000002
009760000003
mas preciso que apareça no rel assim :
001980000002
007250000001
009760000003
ordenada pelo sequencial adicionado os três caracteres..
lembrando não armazeno no banco de dados os três caracteres..
agradeço a atenção de todos
Cabelo
preciso fazer uma ordenação num determinado número de registros de uma tabela, mas esta ordenação não pode ser passada via SQL, isto é, a ordenação é um campo inexistante na tabela..
assim :
Tenho um sequencial 00000001, 00000002, 0000003. (no banco)
No meio destes números pra ser mais preciso antes da segunda casa, na hora da impressão do sequencial eu adiciono três caracteres aleatórios :
007250000001, 001980000002, 009760000003.
Se eu ordenar por sequencial irá aparecer assim :
007250000001
001980000002
009760000003
mas preciso que apareça no rel assim :
001980000002
007250000001
009760000003
ordenada pelo sequencial adicionado os três caracteres..
lembrando não armazeno no banco de dados os três caracteres..
agradeço a atenção de todos
Cabelo
Cabelo
Curtidas 0
Respostas
Rafs
26/07/2004
Caro colega,
Entendi que vc faz a inclusão destes três caracteres aleatórios imediatamente antes da impressão, sendo assim, sería necessário ter conhecimento de como vc efetua a impressão.
Porém se vc puder incluir estes três caracteres a ponto de serem visíveis pelo ClientDataSet, vc só precisará criar um índice na coluna que deseja ordenar e no ClientDataSet apontar o IndexFieldNames (ou IndexName) para o índice criado. Desta forma vc terá os seus dados ordenados como deseja.
Para qualquer dúvida, a disposição.
Entendi que vc faz a inclusão destes três caracteres aleatórios imediatamente antes da impressão, sendo assim, sería necessário ter conhecimento de como vc efetua a impressão.
Porém se vc puder incluir estes três caracteres a ponto de serem visíveis pelo ClientDataSet, vc só precisará criar um índice na coluna que deseja ordenar e no ClientDataSet apontar o IndexFieldNames (ou IndexName) para o índice criado. Desta forma vc terá os seus dados ordenados como deseja.
Para qualquer dúvida, a disposição.
GOSTEI 0
Cabelo
26/07/2004
Colega..
Não entendi o que quis dizer, vc está me dizendo que preciso incluir estes três caracteres no banco de dados?? Ou seria uma outra tabela que contivesse os valores aplicados??
Cabelo
Não entendi o que quis dizer, vc está me dizendo que preciso incluir estes três caracteres no banco de dados?? Ou seria uma outra tabela que contivesse os valores aplicados??
Cabelo
GOSTEI 0
Rafs
26/07/2004
Colega,
Não quis me referir a você alterar no banco de dados, mas sim alterar localmente.
Ao utilizar o ClientDataSet é criado um cache dos dados que foram solicitados ao banco de dados, correto. Neste caso você podería incluir estes três caracteres localmente para depois efetuar a ordenação e a impressão conforme você deseja.
Acredito que sería nestes moldes:
-Resgataría os dados do banco de dados através do ClientDataSet
-Alteraría os registros, incluindo os três caracteres no campo desejado, no ClientDataSet
-Criaría o índice para o referido campo (IndexDefs)
-Ordenaría o ClientDataSet pelo índice criado (IndexFieldNames ou IndexName)
-Emitiría o relatório.
Apesar de ser um pouco trabalhoso, acredito que resolverá o seu problema.
Se vc puder me detalhar como vc emite o relatório (se linca direto com o ClientDataSet ou conecta a outro componente), talvez possamos descobrir uma forma mais fácil e prática de inserir estes caracteres e ordená-los corretamente.
Não quis me referir a você alterar no banco de dados, mas sim alterar localmente.
Ao utilizar o ClientDataSet é criado um cache dos dados que foram solicitados ao banco de dados, correto. Neste caso você podería incluir estes três caracteres localmente para depois efetuar a ordenação e a impressão conforme você deseja.
Acredito que sería nestes moldes:
-Resgataría os dados do banco de dados através do ClientDataSet
-Alteraría os registros, incluindo os três caracteres no campo desejado, no ClientDataSet
-Criaría o índice para o referido campo (IndexDefs)
-Ordenaría o ClientDataSet pelo índice criado (IndexFieldNames ou IndexName)
-Emitiría o relatório.
Apesar de ser um pouco trabalhoso, acredito que resolverá o seu problema.
Se vc puder me detalhar como vc emite o relatório (se linca direto com o ClientDataSet ou conecta a outro componente), talvez possamos descobrir uma forma mais fácil e prática de inserir estes caracteres e ordená-los corretamente.
GOSTEI 0
Cabelo
26/07/2004
Colega..
Como faria para inserir no cache do client, os caracteres, acho que é só isso que falta..
eu tinha imaginado exatamente isso, só não sei como executar..
agradeço sua atenção..
Cabelo
Como faria para inserir no cache do client, os caracteres, acho que é só isso que falta..
eu tinha imaginado exatamente isso, só não sei como executar..
agradeço sua atenção..
Cabelo
GOSTEI 0
Rafs
26/07/2004
Para incluir estes caracteres, trabalhe com o ClientDataSet como se ele fosse uma TTable. Mas em hipótese alguma execute o ApplyUpdates, senão ele atualizará seu BD.
Um exemplo de código sería o seguinte:
Declare a variável [i:383f866247]lRegistro[/i:383f866247] para poder alterar o conteúdo do ClientDataSet.
[i:383f866247]CaracteresGerados[/i:383f866247] será os caracteres que vc deverá gerar para incluir no campo desejado
Com o comando [b:383f866247]Copy[/b:383f866247] você inserirá os caracteres na posição que deseja (após a segunda casa, conforme no seu exemplo)
Pela sua primeira mensagem, entendi que o campo seja string.
Depois de atualizar o ClientDataSet, você precisará criar o índice e indexar o ClientDataSet pelo índice criado.
Desta forma você terá a ordenação que deseja.
:)
Um exemplo de código sería o seguinte:
var lRegistro: String; begin ... ... ClientDataSet.First; while not ClientDataSet.Eof do begin lRegistro := ClientDataSet.FieldByName(´NomeCampo´).AsString; ClientDataSet.Edit; ClientDataSet.FieldByName(´NomeCampo´).AsString := Copy(lRegistro,1,2)+CaracteresGerados+Copy(lRegistro,3,6); ClientDataSet.Post; ClientDataSet.Next; end; ... ... end;
Declare a variável [i:383f866247]lRegistro[/i:383f866247] para poder alterar o conteúdo do ClientDataSet.
[i:383f866247]CaracteresGerados[/i:383f866247] será os caracteres que vc deverá gerar para incluir no campo desejado
Com o comando [b:383f866247]Copy[/b:383f866247] você inserirá os caracteres na posição que deseja (após a segunda casa, conforme no seu exemplo)
Pela sua primeira mensagem, entendi que o campo seja string.
Depois de atualizar o ClientDataSet, você precisará criar o índice e indexar o ClientDataSet pelo índice criado.
ClientDataSet.IndexDefs.Add(´NomeIndice´,´NomeCampo´,[]); ClientDataSet.IndexFieldNames := ´NomeCampo´;
Desta forma você terá a ordenação que deseja.
:)
GOSTEI 0
Cabelo
26/07/2004
Colega Rafs..
O método Post no clientdataset não irá alterar o banco de dados? Pq com a TQuery do BDE no Delphi 5, quando vc utiliza o método Post, ele altera os dados na base..
Cabelo
O método Post no clientdataset não irá alterar o banco de dados? Pq com a TQuery do BDE no Delphi 5, quando vc utiliza o método Post, ele altera os dados na base..
Cabelo
GOSTEI 0
Rafs
26/07/2004
Colega,
O método Post do ClientDataSet irá alterar somente os valores locais da máquina, mas não alterarão os dados do BD. Pois o ClientDataSet realiza um cache dos dados na máquina local. Para alterar os dados do BD, vc precisará chamar o método ApplyUpdates, por isso que coloquei para vc em [b:22869d16d2]hipótese alguma[/b:22869d16d2] chamar este método, senão o BD será alterado.
A TQuery do BDE não realiza cache dos dados, isto é, não armazena os dados na máquina local, assim, quando é chamado o método Post a TQuery se encarrega de atualizar o BD imediatamente.
O método Post do ClientDataSet irá alterar somente os valores locais da máquina, mas não alterarão os dados do BD. Pois o ClientDataSet realiza um cache dos dados na máquina local. Para alterar os dados do BD, vc precisará chamar o método ApplyUpdates, por isso que coloquei para vc em [b:22869d16d2]hipótese alguma[/b:22869d16d2] chamar este método, senão o BD será alterado.
A TQuery do BDE não realiza cache dos dados, isto é, não armazena os dados na máquina local, assim, quando é chamado o método Post a TQuery se encarrega de atualizar o BD imediatamente.
GOSTEI 0
Cabelo
26/07/2004
Obrigado pela ajuda..
Vou tentar aqui..
Cabelo
Vou tentar aqui..
Cabelo
GOSTEI 0
Cabelo
26/07/2004
Colega..
Fiz exatamente o quê vc sugeriu, mas não funcionou..
Ainda não resolvi o problema..
Cabelo
Fiz exatamente o quê vc sugeriu, mas não funcionou..
Ainda não resolvi o problema..
Cabelo
GOSTEI 0
Rafs
26/07/2004
Colega,
Você podería detalhar o que aconteceu? Se não ordenou corretamente ou se houve algum erro.
Fiz um teste rápido aqui, porém funcionou..
Você podería detalhar o que aconteceu? Se não ordenou corretamente ou se houve algum erro.
Fiz um teste rápido aqui, porém funcionou..
GOSTEI 0
Uildenei
26/07/2004
se for somente em ordem ascendente assim eh mais facil e eh certo que funciona:
cds.IndexFieldNames:=´CAMPO´;
desde que esse campo nao seja calculado
Uildenei
cds.IndexFieldNames:=´CAMPO´;
desde que esse campo nao seja calculado
Uildenei
GOSTEI 0
Cabelo
26/07/2004
Ocorreu o seguinte :
Ele simplesmente não fez a ordenação corretamente..
O problema é que o campo é string..
e pela ordenação a partir de uma string, a ordenação acaba saindo errada..
se fosse integer, ordenaria corretamente..
Cabelo
Ele simplesmente não fez a ordenação corretamente..
O problema é que o campo é string..
e pela ordenação a partir de uma string, a ordenação acaba saindo errada..
se fosse integer, ordenaria corretamente..
Cabelo
GOSTEI 0
Rafs
26/07/2004
Eu refiz o teste agora e ordenou corretamente.
Primeiro vc deverá atualizar a tabela com os caracteres desejados para depois indexar
Se vc quiser eu lhe mando o teste que fiz.
Um detalhe que esqueci de mencionar, o tamanho do campo no BD deve permitir receber os três caracteres a mais que você irá inserir, pois o ClientDataSet respeita este aspecto. Isto é, o campo deve ter 11 caracteres de tamanho, senão quando vc inserir os três caracteres o sistema irá ´capar´ os três últimos.
Primeiro vc deverá atualizar a tabela com os caracteres desejados para depois indexar
Se vc quiser eu lhe mando o teste que fiz.
Um detalhe que esqueci de mencionar, o tamanho do campo no BD deve permitir receber os três caracteres a mais que você irá inserir, pois o ClientDataSet respeita este aspecto. Isto é, o campo deve ter 11 caracteres de tamanho, senão quando vc inserir os três caracteres o sistema irá ´capar´ os três últimos.
GOSTEI 0
Cabelo
26/07/2004
Colega rafs
Exatamente o quê eu havia imaginado..
O problema é o seguinte..
Além de inserir os três caracteres, eu devo ainda inserir alguns caracteres em braco, para separar o código, para facilitar a digitação caso seja necessário..
Aí eu teria que ter uma campo com 25 caracteres, e meu sequancial seria de somente 15..
Além do mais.. não posso mudar o banco de dados, pois esta tabela é usada mais adiante no sistema, e é necessário que tenha somente 15 caracteres..
Eu tive uma idéia de criar um campo calculado, mas não deu certo, e como o colega uildinei mencionou não é possível realizar este evento em campos calculados..
Não sei o quê eu faço..
Como vou resolver este problema, sendo que além de tudo não posso usar uma tabela temporária..
Cabelo
Exatamente o quê eu havia imaginado..
O problema é o seguinte..
Além de inserir os três caracteres, eu devo ainda inserir alguns caracteres em braco, para separar o código, para facilitar a digitação caso seja necessário..
Aí eu teria que ter uma campo com 25 caracteres, e meu sequancial seria de somente 15..
Além do mais.. não posso mudar o banco de dados, pois esta tabela é usada mais adiante no sistema, e é necessário que tenha somente 15 caracteres..
Eu tive uma idéia de criar um campo calculado, mas não deu certo, e como o colega uildinei mencionou não é possível realizar este evento em campos calculados..
Não sei o quê eu faço..
Como vou resolver este problema, sendo que além de tudo não posso usar uma tabela temporária..
Cabelo
GOSTEI 0
Rafs
26/07/2004
Camarada, agora vc apertou sem abraçar... :(
Vou dar uma pensada em casa e vejo se consigo alguma idéia para ajudar com seu ´probleminha´.
Mas para me ajudar, detalhe como vc faz desde a seleção na tabela até a apresentação no relatório. Quem sabe possa surgir alguma idéia que supra as suas necessidades, diferente do que estamos trabalhando. :)
Vou dar uma pensada em casa e vejo se consigo alguma idéia para ajudar com seu ´probleminha´.
Mas para me ajudar, detalhe como vc faz desde a seleção na tabela até a apresentação no relatório. Quem sabe possa surgir alguma idéia que supra as suas necessidades, diferente do que estamos trabalhando. :)
GOSTEI 0
Cabelo
26/07/2004
esta é a rotina para inserir os registros do sequencial :
v_sequencial := F_Max_Cod(´C_SEQUENCIAL´, ´VT0100´, 15, MD.QGERAL2, MD.cdsGeral2);
//esta função gera o sequencial de 15 dígitos
v_sql := ´insert into VT0100 (C_SEQUENCIAL, C_BAIXA, C_COD_SERVICO, C_IMPRESSO, ´+
´C_DATA_IMP, C_LOGIN_IMPRESSAO, C_COD_COLABORADOR, C_STATUS, ´+
´C_COD_EMPRESA, C_DATA_ENTREGA, C_LOGIN_ENTREGA) values ´+
´(´´´+v_sequencial+´´´, ´´N´´, ´´´+
cdsCA0400.fieldbyname(´C_COD_SERVICO´).asstring+´´´, ´´N´´, ´´´+
formatdatetime(´mm/dd/yyyy´, now)+´´´, ´´´+F_Le_Usuario+´´+
´´´, ´´´+s_cod_vendedor+´´´, ´´I´´, ´´´+v_empresa+´´´, ´´´+
formatdatetime(´mm/dd/yyyy´, now)+´´´, ´´´+F_Le_Usuario+´´´)´;
F_Grava(MD.sqlEngestrauss, MD.QGERAL, MD.cdsGeral, v_sql);
//esta função manda o SQL abrindo uma transaction, e dando um commit ou rollback
no evento beforePrint do detail do report :
v_seguranca := F_strzero(v_i + 1, 3);
rlBarCode.Caption := copy(cdsVT0100.fieldbyname(´C_SEQUENCIAL´).asstring, 1, 1)+
´ ´+
copy(cdsVT0100.fieldbyname(´C_SEQUENCIAL´).asstring, 2, 3)+
´ ´+
copy(cdsVT0100.fieldbyname(´C_SEQUENCIAL´).asstring, 5, 2)+
´ ´+
copy(cdsVT0100.fieldbyname(´C_SEQUENCIAL´).asstring, 7, 3)+
´ ´+
copy(cdsVT0100.fieldbyname(´C_SEQUENCIAL´).asstring, 10, 2)+
´ ´+
copy(cdsVT0100.fieldbyname(´C_SEQUENCIAL´).asstring, 12, 2)+
copy(v_seguranca, 1, 2) +
´ ´+
copy(v_seguranca, 3, 1) +
copy(cdsVT0100.fieldbyname(´C_SEQUENCIAL´).asstring, 14, 2);
Agradeço sua atenção..
Cabelo
v_sequencial := F_Max_Cod(´C_SEQUENCIAL´, ´VT0100´, 15, MD.QGERAL2, MD.cdsGeral2);
//esta função gera o sequencial de 15 dígitos
v_sql := ´insert into VT0100 (C_SEQUENCIAL, C_BAIXA, C_COD_SERVICO, C_IMPRESSO, ´+
´C_DATA_IMP, C_LOGIN_IMPRESSAO, C_COD_COLABORADOR, C_STATUS, ´+
´C_COD_EMPRESA, C_DATA_ENTREGA, C_LOGIN_ENTREGA) values ´+
´(´´´+v_sequencial+´´´, ´´N´´, ´´´+
cdsCA0400.fieldbyname(´C_COD_SERVICO´).asstring+´´´, ´´N´´, ´´´+
formatdatetime(´mm/dd/yyyy´, now)+´´´, ´´´+F_Le_Usuario+´´+
´´´, ´´´+s_cod_vendedor+´´´, ´´I´´, ´´´+v_empresa+´´´, ´´´+
formatdatetime(´mm/dd/yyyy´, now)+´´´, ´´´+F_Le_Usuario+´´´)´;
F_Grava(MD.sqlEngestrauss, MD.QGERAL, MD.cdsGeral, v_sql);
//esta função manda o SQL abrindo uma transaction, e dando um commit ou rollback
no evento beforePrint do detail do report :
v_seguranca := F_strzero(v_i + 1, 3);
rlBarCode.Caption := copy(cdsVT0100.fieldbyname(´C_SEQUENCIAL´).asstring, 1, 1)+
´ ´+
copy(cdsVT0100.fieldbyname(´C_SEQUENCIAL´).asstring, 2, 3)+
´ ´+
copy(cdsVT0100.fieldbyname(´C_SEQUENCIAL´).asstring, 5, 2)+
´ ´+
copy(cdsVT0100.fieldbyname(´C_SEQUENCIAL´).asstring, 7, 3)+
´ ´+
copy(cdsVT0100.fieldbyname(´C_SEQUENCIAL´).asstring, 10, 2)+
´ ´+
copy(cdsVT0100.fieldbyname(´C_SEQUENCIAL´).asstring, 12, 2)+
copy(v_seguranca, 1, 2) +
´ ´+
copy(v_seguranca, 3, 1) +
copy(cdsVT0100.fieldbyname(´C_SEQUENCIAL´).asstring, 14, 2);
Agradeço sua atenção..
Cabelo
GOSTEI 0
Rafs
26/07/2004
Colega,
Hoje estive super enrolado no trampo e não consegui olhar direito o que vc me passou. Vou dar uma olhada com calma em casa e assim que tiver alguma idéia lhe passo.
Hoje estive super enrolado no trampo e não consegui olhar direito o que vc me passou. Vou dar uma olhada com calma em casa e assim que tiver alguma idéia lhe passo.
GOSTEI 0
Cabelo
26/07/2004
Cara muito obrigado pela atenção, se precisar de alguma coisa tô aqui..
Cabelo
Cabelo
GOSTEI 0
Rafs
26/07/2004
Caro cabelo_uni,
Consegui fazer da seguinte forma, espero que lhe ajude...
Abaixo segue o código comentado.
Crie um campo tipo InternalCalc no FieldsEditor do CDS
Declare uma variável na seção private para verificar se os registros já foram adicionados ao campo tipo InternalCalc
PS.: A função GeraCaracter eu utilizo para gerar os caracteres aleatóriamente.
Na criação do form eu abro o CDS e adiciono o índice que desejo utilizar para ordenar os registros
No evento OnCalcFields insira o código para que o campo tipo InternalCalc seja atualizado.
É aqui que virá a rotina para você incluir os caracteres que deseja
Caso deseje posso lhe enviar o programinha que fiz para testar.
Havendo alguma dúvida estarei à disposição. :D
Consegui fazer da seguinte forma, espero que lhe ajude...
Abaixo segue o código comentado.
Crie um campo tipo InternalCalc no FieldsEditor do CDS
Declare uma variável na seção private para verificar se os registros já foram adicionados ao campo tipo InternalCalc
PS.: A função GeraCaracter eu utilizo para gerar os caracteres aleatóriamente.
private
{ Private declarations }
// Informará se já foram carregados os valores para o campo tipo InternalCal
pvCarregou: Boolean;
function GeraCaracter: String;
// função para criar os caracteres randomicamente function TForm1.GeraCaracter: String; var I: Integer; begin Randomize; I := Random(999); Result := FormatFloat(´000´,I); end;
Na criação do form eu abro o CDS e adiciono o índice que desejo utilizar para ordenar os registros
procedure TForm1.FormCreate(Sender: TObject); begin cds.Open; // Crio um índice no CDS para ordenar pelo campo tipo InternalCalc cds.IndexDefs.Add(´idxOrdem´,´Teste´,[]); // Ao abrir o CDS, automaticamente é executado o evento OnCalcFields, por isso // após a abertura do CDS eu mudo o status da variável pvCarregou para True, // para que quando alterar o índice não reexecute o evento OnCalcFields pvCarregou := True; end;
No evento OnCalcFields insira o código para que o campo tipo InternalCalc seja atualizado.
É aqui que virá a rotina para você incluir os caracteres que deseja
procedure TForm1.cdsCalcFields(DataSet: TDataSet); var Primeiro, Segundo: String; lRegistro: String; begin // Verifica se a variável é false para poder carregar o campo tipo InternalCalc // com os caracteres necessários if not pvCarregou then begin lRegistro := cds.FieldByName(´CPOSTRING´).AsString; Primeiro := Copy(lRegistro,1,2); Segundo := Copy(lRegistro,3,6); cds.FieldByName(´Teste´).AsString := Primeiro+GeraCaracter+Segundo; end; end;
Caso deseje posso lhe enviar o programinha que fiz para testar.
Havendo alguma dúvida estarei à disposição. :D
GOSTEI 0
Cabelo
26/07/2004
Cara não consegui fazer isso aki..
vc poderia então me mandar o programa??
talvez eu consiga fazer..
Obrigado pela atanção..
cabelo.uni@uol.com.br
Valew
Cabelo
vc poderia então me mandar o programa??
talvez eu consiga fazer..
Obrigado pela atanção..
cabelo.uni@uol.com.br
Valew
Cabelo
GOSTEI 0
Rafs
26/07/2004
Acabei de enviar o arquivo para o email que vc me passou.
Este está lendo os dados de um arquivo xml, mas funciona perfeitamente igual ao acessar um BD.
Espero que lhe ajude.
Este está lendo os dados de um arquivo xml, mas funciona perfeitamente igual ao acessar um BD.
Espero que lhe ajude.
GOSTEI 0
Cabelo
26/07/2004
Muito obrigado pela sua ajuda..
Assim que conseguir te dou um toque..
Valew mesmo..
Cabelo
Assim que conseguir te dou um toque..
Valew mesmo..
Cabelo
GOSTEI 0