Importação de Arquivo *txt e Relatório (Ponto Eletronico)

Delphi

03/01/2015

Srs. Boa noite...

Tenho o segunte arquivo de ponto que me é gerado do relogio em *txt:

0004599883220520141328013084887674,
0004599893220520141710012337840060,
0004599903220520141720012439568688,


onde :


0004599883 22052014 1328    0 13084887674
    NADA       DATA     HORA        PIS




Tenho duas tabelas 1 = pessoa e a outra 1 = ponto...que seguem assim:


pessoa(
codigo,
matricula,
pis,
)


ponto(
id,
matricula,
pis,
hora,
dia,
)




Eu faço a importação do arquivo txt para o banco de dados, e necessito gerar o relatorio. A importação faço normalmente, mas na hora de gerar o relatorio, não me traz as informações corretas, um exemplo é se o individuo registrar duas vezes o ponto na mesma hora, ele duplica, outra é se o individuo registrar só uma vez, ele não me traz nenhum registro.

Aos que puderem me ajudar, Agradeço...
Brunno Sena

Brunno Sena

Curtidas 0

Respostas

William

William

03/01/2015

Bs um relatório nada mais é que o resultado de uma pesquisa ou cálculos muitas vezes executados em SQL, então pergunto para você!

As 2 tabelas que recebem os dados da importação estão com registros consistentes?

Essas discrepâncias que você cita, aparecem se você executar uma pesquisa SQL simples?
GOSTEI 0
Brunno Sena

Brunno Sena

03/01/2015

Bs um relatório nada mais é que o resultado de uma pesquisa ou cálculos muitas vezes executados em SQL, então pergunto para você!

As 2 tabelas que recebem os dados da importação estão com registros consistentes?

Essas discrepâncias que você cita, aparecem se você executar uma pesquisa SQL simples?




Willian, faço da seguinte forma...

TABELAS:

CREATE TABLE PESSOA (
    MATRICULA     INTEGER,
    CC            VARCHAR(8),
    MAODEOBRA     VARCHAR(2),
    NOME          VARCHAR(300),
    PIS           VARCHAR(15),
    CIDADE        VARCHAR(25),
    UF            VARCHAR(2),
    DESC_FUNCAO   VARCHAR(100),
    COD_FUNCAO    INTEGER,
    COD_LOCAL     INTEGER,
    ALOJAMENTO    VARCHAR(100),
    DATA_ENTRADA  DATE,
    DATA_SAIDA    VARCHAR(11),
    SITUACAO      CHAR(1),
    ADM           DATE,
    COD_CIDADE    INTEGER,
    PICTURE       BLOB SUB_TYPE 0 SEGMENT SIZE 80,
    COD_FOTO      INTEGER,
    NASCIMENTO    DATE,
    VENC_EXP1     DATE,
    VENC_EXP2     DATE,
    CATEGORIA     CHAR(1),
    AGENCIA       VARCHAR(9),
    CONTA         VARCHAR(10),
    BANCO         VARCHAR(3),
    NUCLEO        CHAR(1),
    TURNO         INTEGER
);


CREATE TABLE PONTO (
    PIS        VARCHAR(11),
    DATA       VARCHAR(12),
    HORA      VARCHAR(5),
    ID         INTEGER,
    NUM_REP    CHAR(2),
    ID_PESSOA  INTEGER
);





E faço o select dessa forma:



select P1.PIS, P1.DATA, P1.HORA1 as ENTRA, P2.HORA1 as SAI, 
P.MATRICULA, P.NOME as NOME_PESSOA, P.PIS, P.DESC_FUNCAO, 
P.CC, P.DATA_ENTRADA, P.MAODEOBRA, P.situacao, P.turno 
FROM PONTO P1,PONTO P2,PESSOA P 
where P1.DATA = '03012014' AND P2.DATA = P1.DATA AND P2.PIS = P1.PIS 
AND P2.ID > P1.ID AND P.PIS = P1.PIS 
and p.situacao <> 'D' 
group by p1.id, P1.PIS, P1.DATA, P1.HORA1, P2.HORA1, 
P.MATRICULA, P.NOME, P.PIS, P.DESC_FUNCAO, 
P.CC, P.DATA_ENTRADA, P.MAODEOBRA, P.situacao,P.turno 
ORDER BY P.MATRICULA





ele me traz o resultado, e sobre a duplicação te trago o exemplo...

ID	ID1	PIS   DATA	ENTRA	SAI	   MATRICULA	NOME_PESSOA
369	370	20430280194	20122014	17:02	17:02	3998	EDERSON FINKS
369	1114	20430280194	20122014	17:02	07:32	3998	EDERSON FINKS
370	1114	20430280194	20122014	17:02	07:32	3998	EDERSON FINKS


agora acho que pode me dizer que select melhor fazer pra isso, acredito que o problema seja no select, porque se ele me trouxer o select funcionando, pra o espelho de ponto, vai ser moleza...

Abraço...
GOSTEI 0
Marisiana Battistella

Marisiana Battistella

03/01/2015

Considerando que vc precisa retornar os dados da pessoa independente de ela ter registro de ponto ou não, você precisa usar um LEFT JOIN da tabela pessoa com a tabel ponto para atender essa necessidade. Veja um exemplo:
SELECT P1.PIS,
         P1.DATA,
         P1.HORA1 AS ENTRA,
         P2.HORA1 AS SAI, 
         P.MATRICULA,
         P.NOME as NOME_PESSOA,
         P.PIS, P.DESC_FUNCAO, 
         P.CC, P.DATA_ENTRADA,
         P.MAODEOBRA,
         P.situacao,
         P.turno 
FROM PESSOA P
LEFT JOIN PONTO P1
ON  P.PIS = P1.PIS 
LEFT JOIN PONTO P2
ON  P.PIS = P2.PIS
AND P2.DATA = P1.DATA 
WHERE P1.DATA = '03012014' 
--- AND P2.ID > P1.ID 
AND p.situacao <> 'D'
GROUP BY p1.id,
               P1.PIS,
               P1.DATA,
               P1.HORA1,
               P2.HORA1, 
               P.MATRICULA,
               P.NOME, P.PIS,
               P.DESC_FUNCAO, 
               P.CC, P.DATA_ENTRADA,
               P.MAODEOBRA,
               P.situacao,
               P.turno 
ORDER BY P.MATRICULA


Não entendi o porque de utilizar o JOIN " AND P2.ID > P1.ID "...

Não cheguei a fazer testes, mas logicamente é essa idéia q deve ser seguida.
GOSTEI 0
Brunno Sena

Brunno Sena

03/01/2015

Considerando que vc precisa retornar os dados da pessoa independente de ela ter registro de ponto ou não, você precisa usar um LEFT JOIN da tabela pessoa com a tabel ponto para atender essa necessidade. Veja um exemplo:
SELECT P1.PIS,
         P1.DATA,
         P1.HORA1 AS ENTRA,
         P2.HORA1 AS SAI, 
         P.MATRICULA,
         P.NOME as NOME_PESSOA,
         P.PIS, P.DESC_FUNCAO, 
         P.CC, P.DATA_ENTRADA,
         P.MAODEOBRA,
         P.situacao,
         P.turno 
FROM PESSOA P
LEFT JOIN PONTO P1
ON  P.PIS = P1.PIS 
LEFT JOIN PONTO P2
ON  P.PIS = P2.PIS
AND P2.DATA = P1.DATA 
WHERE P1.DATA = '03012014' 
--- AND P2.ID > P1.ID 
AND p.situacao <> 'D'
GROUP BY p1.id,
               P1.PIS,
               P1.DATA,
               P1.HORA1,
               P2.HORA1, 
               P.MATRICULA,
               P.NOME, P.PIS,
               P.DESC_FUNCAO, 
               P.CC, P.DATA_ENTRADA,
               P.MAODEOBRA,
               P.situacao,
               P.turno 
ORDER BY P.MATRICULA


Não entendi o porque de utilizar o JOIN " AND P2.ID > P1.ID "...

Não cheguei a fazer testes, mas logicamente é essa idéia q deve ser seguida.





Obrigado Marisiana, mas a utilidade do "AND P2.ID > P1.ID", é pra que não duplique, pois do modo que você me passou, me apresentou da seguinte forma:



ID	ID1	PIS	DATA	ENTRA	SAI	MATRICULA	NOME_PESSOA
402	402	12961397709	20122014	08:13	08:13	3963	DANIELE ROCHA PEREIRA
402	407	12961397709	20122014	08:13	11:53	3963	DANIELE ROCHA PEREIRA
407	402	12961397709	20122014	11:53	08:13	3963	DANIELE ROCHA PEREIRA
407	407	12961397709	20122014	11:53	11:53	3963	DANIELE ROCHA PEREIRA
424	424	12580868684	20122014	07:17	07:17	3969	JOSE VADERLI DA SILVA SUTELLO
424	434	12580868684	20122014	07:17	12:40	3969	JOSE VADERLI DA SILVA SUTELLO
434	424	12580868684	20122014	12:40	07:17	3969	JOSE VADERLI DA SILVA SUTELLO
434	434	12580868684	20122014	12:40	12:40	3969	JOSE VADERLI DA SILVA SUTELLO





O que na verdade preciso, é que não duplique, e que se o individuo registra 1 batida, me traga ainda sim.

Agradecido.
GOSTEI 0
Marisiana Battistella

Marisiana Battistella

03/01/2015

Na verdade ele não está duplicando, está fazendo certo pois ele está listando por ID. Observe que as combinações de ID são diferentes, talvez você deva filtrar e agrupar sem esses IDs. Tenta remover o campo p1.id da cláusula GROUP BY...

Qual é o campo identificador (foreig key) da pessoa na tabela Ponto?
GOSTEI 0
Brunno Sena

Brunno Sena

03/01/2015

Na verdade ele não está duplicando, está fazendo certo pois ele está listando por ID. Observe que as combinações de ID são diferentes, talvez você deva filtrar e agrupar sem esses IDs. Tenta remover o campo p1.id da cláusula GROUP BY...

Qual é o campo identificador (foreig key) da pessoa na tabela Ponto?



Marisiana, São IDs diferentes porque vou salvando assim, pra ter ids diferente, à não ser que o modo em que eu esteja puxando do txt para o BD, esteja errada.

Faço desta forma:


for I := 0 to lbArquivos.Items.Count - 1 do
  begin
  try
//    lbArquivos.Selected[i];
    AssignFile(Txt,(eArquivo.Text+'\'+lbArquivos.Items[i]));{ NOME do arquivo texto}
    Reset(Txt);

  if not SQLDataSet1.Active then
      SQLDataSet1.Open;
    cdsDados.EmptyDataSet; //... zera o arquivo
  cdsDados.Open;

  While not Eoln(Txt) do
  begin
    Readln(Txt,Entrada);
//    Readln(Txt,Entrada);

    cdsDados.Insert;

    consultaID;
    novo_ID := dmDados.cdsID.FieldByName('MAX').AsInteger;
    novo_ID := novo_ID + 1;

    cdsDados.FieldByName('ID').AsInteger := novo_ID;
    cdsDados.FieldByName('PIS').Value:= Copy(Entrada,24,11);
    cdsDados.FieldByName('DATA').Value:= Copy(Entrada,11,08);
    cdsDados.FieldByName('HORA1').Value:= Copy(Entrada,19,02)+':'+Copy(Entrada,21,02);
    cdsDados.FieldByName('NUM_REP').Value:= Copy(lbArquivos.Items[i],14,2);

    cdsDados.Post;
    cdsDados.ApplyUpdates(0);
    end;
  CloseFile(Txt);
    MessageDlg('Arquivo importado com sucesso !',mtInformation,[mbOK]);
  except
    MessageDlg('Erro na importação !',mtError,[mbOK]);
  end;



Mas de qualquer forma, o indentificador é o pis. Mas ela não é Integer, é varchar!
GOSTEI 0
Marisiana Battistella

Marisiana Battistella

03/01/2015

Mas, pelo q entendi, o armazenamento da informação está correto...
A questão é q na consulta (SELECT) q vc está fazendo não precisa pedir para listar e agrupar pelo ID, senão vc não vai conseguir visualizar os dados como você precisa.
GOSTEI 0
Brunno Sena

Brunno Sena

03/01/2015

Mas, pelo q entendi, o armazenamento da informação está correto...
A questão é q na consulta (SELECT) q vc está fazendo não precisa pedir para listar e agrupar pelo ID, senão vc não vai conseguir visualizar os dados como você precisa.



Eu testei retirando o id, mas não funcionou, continuou a duplicar... alguma sugestão ?
GOSTEI 0
Marisiana Battistella

Marisiana Battistella

03/01/2015

Mais uma alteração... Não sei se vai resolver..
Se não der certo é em função da definição na cláusula WHERE...
SELECT P.MATRICULA,
       P.NOME as NOME_PESSOA,
       P.PIS,
       P.DESC_FUNCAO,
       P.DATA_ENTRADA,
       P.MAODEOBRA,
       P.SITUACAO,
       P.CC,
       P1.DATA,
       P.TURNO,
       P1.HORA1 AS ENTRA,
       P2.HORA1 AS SAI 
FROM PESSOA P
LEFT JOIN PONTO P1
ON  P1.PIS = P.PIS 
LEFT JOIN PONTO P2
ON  P2.PIS = P.PIS
WHERE P1.DATA = '03012014'
AND P2.DATA = P1.DATA 
AND P2.ID > P1.ID 
AND P.SITUACAO <> 'D'
GROUP BY P.MATRICULA,
       P.NOME,
       P.PIS,
       P.DESC_FUNCAO,
       P.DATA_ENTRADA,
       P.MAODEOBRA,
       P.SITUACAO,
       P.CC,
       P1.DATA,
       P.TURNO,
       P1.HORA1,
       P2.HORA1 
ORDER BY P.MATRICULA
GOSTEI 0
POSTAR