Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Conexión con bases de datos (https://www.clubdelphi.com/foros/forumdisplay.php?f=2)
-   -   no logro enviar .xml a bd usando el server (https://www.clubdelphi.com/foros/showthread.php?t=87956)

giulichajari 22-03-2015 14:57:42

Recorrer directorio y trabajar con archivos
 
Buenas amigos, tengo una aplicacion cliente servidor en datasnap con delphi.

Del lado del cliente cuando no hay conexion los tickets y presupuestos se guardan en xml, con el metodo savetofile del clientdataset, ya que trabajo con este componente.

Entonces cuando retorna la conexion, necesito recorrer el directorio tickets por ejemplo y cargar los mismo en la base de datos, para lo mismo se usa el procedimiento del server que se usa siempre.

Código Delphi [-]
function cantticket():integer;
var
  rec: TSearchRec;
  carpeta:string;
  cant:integer;

begin
    carpeta :=ExtractFilePath(Application.ExeName)+'tickets';
    cant:=0;
    if FindFirst(carpeta, faAnyFile,rec) = 0 then
      begin
        try
        repeat

          if (rec.Attr and faDirectory = 0)
            or (rec.Name <> '.')
              and (rec.Name <> '..') then
                inc(cant);
        until FindNext(rec) <> 0;
     except
        FindClose(rec);
      end;
      FindClose(rec);
    end;
Result:=cant;
ShowMessage(inttostr(cant));
end;

Pense contar la cantidad de archivos primero, pero me identifica 1(uno solo), y por ende no envia nada.

Código Delphi [-]
procedure LeerDirectorio();
var
  rec: TSearchRec;
  carpeta:string;
  t,x:integer;
  nombrearchivo,nombrecopia:string;
  a:TServerMethods1Client;
l:integer;
fechae,horae:string;
cantidad,importe,preciou,efectivo,vuelto:Double;
idc,ids,idprodu,numero:Integer;
nuevoticket:string;
begin
    if ClientModule1.SQLConnection1.Connected then
    begin
       a:=TServerMethods1Client.Create(ClientModule1.SQLConnection1.DBXConnection);

        if (cantticket(carpeta)>0) then
            begin
              t:=cantticket(carpeta);


              carpeta := ExtractFilePath(Application.ExeName)+'tickets';
              SetCurrentDir(carpeta);
            for x := 0 to t do

                begin

                  if FindFirst(carpeta,FaAnyfile,rec)=0 then
                  begin
                  nombrearchivo:=rec.Name;
                  ShowMessage(nombrearchivo);
                  ClientModule1.cdsticketpendiente.LoadFromFile(nombrearchivo);
                  nombrecopia:=ExtractFileName(Application.ExeName) + 'ticketscopia\' + nombrearchivo;
                  CopyFile(Pchar(nombrearchivo),Pchar(nombrecopia),True);
                  idc:=1;
                  ids:=1;
                  numero:=1;
                  importe:=ClientModule1.cdsticketpendiente.FieldByName('total').Value;
                  fechae:=ClientModule1.cdsticketpendientefechae.AsString;
                  horae:=ClientModule1.cdsticketpendientehorae.AsString;
                  efectivo:=ClientModule1.cdsticketpendienteefectivo.AsFloat;
                  vuelto:=efectivo - importe;
                   a.nuevoticket(numero,ids,idc,importe,efectivo,vuelto,fechae,horae);

                end;
                end;

      end
      else
      begin
       ShowMessage('no quedan transacciones pendientes');
      end;
        end
        else
        begin
          ShowMessage('no hay conexion para enviar los datos');
        end;
end;

Lo que hice lo saque de ejemplos del foro y de la web, pero me esta costando.
Saludos

bitbow 22-03-2015 17:24:31

Busqueda recursiva
 
Debes realizar la busqueda recursiva de archivos, hay muchos ejemplos de esto.

Enalces foro:
http://www.clubdelphi.com/foros/showthread.php?t=7181
http://www.clubdelphi.com/foros/showthread.php?t=86325

Saludos.

giulichajari 22-03-2015 20:50:47

Bueno pues use la funcion de neftali:

Código Delphi [-]
 procedure FindFiles(StartDir, FileMask: string; recursively: boolean; var FilesList: TStringList);
  const
    MASK_ALL_FILES = '*.*';
    CHAR_POINT = '.';
  var
    SR: TSearchRec;
    DirList: TStringList;
    IsFound: Boolean;
    i: integer;
  begin
    if (StartDir[length(StartDir)] <> '\') then begin
      StartDir := StartDir + '\';
    end;
  
    // Crear la lista de ficheos en el directorio StartDir (no directorios!)
    IsFound := FindFirst(StartDir + FileMask, faAnyFile - faDirectory, SR) = 0;
    // MIentras encuentre
    while IsFound do  begin
      FilesList.Add(StartDir + SR.Name);
      IsFound := FindNext(SR) = 0;
    end;
  
    FindClose(SR);
  
    // Recursivo?
    if (recursively) then begin
      // Build a list of subdirectories
      DirList := TStringList.Create;
      // proteccion
      try
        IsFound := FindFirst(StartDir + MASK_ALL_FILES, faAnyFile, SR) = 0;
        while IsFound do
        begin
          if ((SR.Attr and faDirectory) <> 0) and
            (SR.Name[1] <> CHAR_POINT) then
            DirList.Add(StartDir + SR.Name);
          IsFound := FindNext(SR) = 0;
        end;
        FindClose(SR);
  
        // Scan the list of subdirectories
        for i := 0 to DirList.Count - 1 do
          FindFiles(DirList[i], FileMask, recursively, FilesList);
      finally
        DirList.Free;
      end;
    end;
  end;

Ahora bien mi aplicacion de terminal de puesto de venta tiene un modulo con un edit con la cantidad de ticket(1 por archivo) y un progress bar para programar despues.

El caso es que en el evento OnShow del form llamo a

Código Delphi [-]
procedure TForm10.FormShow(Sender: TObject);
var
StartDir, FileMask: string;
recursively: boolean;
FilesList: TStringList;
x,cant:integer;
begin

 StartDir:=ExtractFilePath(Application.ExeName) + 'tickets';

FindFiles(StartDir, FileMask, recursively, FilesList);




end;

pasandole los parametros Stardir, pero debo crear el objeto fileslist?

Luego debo agregar obviamente el codigo que quiero se ejecute al encontrar un archivo dentro del while.
Código Delphi [-]
procedure FindFiles(StartDir, FileMask: string; recursively: boolean; var FilesList: TStringList);
  const
    MASK_ALL_FILES = '*.*';
    CHAR_POINT = '.';
  var
    SR: TSearchRec;
    DirList: TStringList;
    IsFound: Boolean;
    i,x: integer;
    a:TServerMethods1Client;
    l:integer;
    fechae,horae,nombrearchivo,nombrecopia:string;
    cantidad,importe,preciou,efectivo,vuelto:Double;
    idc,ids,idprodu,numero:Integer;
    nuevoticket:string;
  begin

    if (StartDir[length(StartDir)] <> '\') then begin
      StartDir := StartDir + '\';
    end;
    FilesList.Create;
 //    FileMask:='.xml'
    // Crear la lista de ficheos en el directorio StartDir (no directorios!)
    IsFound := FindFirst(StartDir + FileMask, faAnyFile - faDirectory, SR) = 0;
    // MIentras encuentre

    while IsFound do  begin

      FilesList.Add(StartDir + SR.Name);

      IsFound := FindNext(SR) = 0;

    end;

     if FilesList.Count<>0 then
      begin
         for  x:=FilesList.Count - 1 downto 0 do
           begin

                  Form10.Etick.Text:=IntToStr(FilesList.Count);
                  nombrearchivo:=SR.Name;
                  ShowMessage(nombrearchivo);
                  ClientModule1.cdsticketpendiente.LoadFromFile(nombrearchivo);
                  nombrecopia:=ExtractFileName(Application.ExeName) + 'ticketscopia\' + nombrearchivo;
                  CopyFile(Pchar(nombrearchivo),Pchar(nombrecopia),True);
                  idc:=1;
                  ids:=1;
                  numero:=1;
                  importe:=ClientModule1.cdsticketpendiente.FieldByName('total').Value;
                  fechae:=ClientModule1.cdsticketpendientefechae.AsString;
                  horae:=ClientModule1.cdsticketpendientehorae.AsString;
                  efectivo:=ClientModule1.cdsticketpendienteefectivo.AsFloat;
                  vuelto:=efectivo - importe;
                  a.nuevoticket(numero,ids,idc,importe,efectivo,vuelto,fechae,horae);

           end;
      end;
      FilesList.Destroy;

    // Recursivo?
    if (recursively) then begin
      // Build a list of subdirectories
      DirList := TStringList.Create;
      // proteccion
      try
        IsFound := FindFirst(StartDir + MASK_ALL_FILES, faAnyFile, SR) = 0;
        while IsFound do
        begin
          if ((SR.Attr and faDirectory) <> 0) and
            (SR.Name[1] <> CHAR_POINT) then
            DirList.Add(StartDir + SR.Name);
          IsFound := FindNext(SR) = 0;
        end;
        FindClose(SR);

        // Scan the list of subdirectories
        for i := 0 to DirList.Count - 1 do
          FindFiles(DirList[i], FileMask, recursively, FilesList);
      finally
        DirList.Free;
      end;
    end;
  end;

Neftali [Germán.Estévez] 23-03-2015 10:31:34

Hola.
No entiendo muy bien lo que estás haciendo con el procedimiento.

Justo está hecho en un procedimiento para que puedas utilizarlo donde quieras y reaprovecharlo. Si modificas el procedimiento y le añades cosas como estas ya no será "reaprovechable":

Código Delphi [-]
    Form10.Etick.Text:=IntToStr(FilesList.Count);
    nombrearchivo:=SR.Name;
    ShowMessage(nombrearchivo);
    ClientModule1.cdsticketpendiente.LoadFromFile(nombrearchivo);
    nombrecopia:=ExtractFileName(Application.ExeName) + 'ticketscopia\' + nombrearchivo;
    ...

Utiliza el procedimiento para buscar todos los ficheros que hay en el directorio que cumplen unas condiciones. Una vez realizada la búsqueda, utiliza un bucle para hacer el trabajo que necesites... (y coloca tu código ahí)

Código Delphi [-]
  // Crear la lista que vamos a utilizar
  TS := TStringList.Create();
  // Buscar ficheros en disco.
  FindFiles(pathDeBusqueda, '*.xml', False, TS); 
  // Para cada fichero encontrado, realizamos el trabajo necesario...
  for i := 0 to (TS.Count - 1) do begin
    // Extraer nombre del fichero. en TS[i] está el path completo  
    fName := ExtractFileName(TS[i]);
    ....
    
    AQUI HAZ LO QUE QUIERAS CON EL FICHERO....
    
    
  end;
  // liberar la lista
  TS.Free;

giulichajari 23-03-2015 18:37:16

Te comento que logre cargar los ficheros xml en el dataset, pero en el xml el metodo savetofile no guarda los internalCalc y los Aggregates, por lo que el dataset ticketspendientes por ej debe contener los mismos campos que el de ticket que se usa a diario.

con la diferencia de que el subtotal de cada registro de compra: precio * cantidad debe ser recalculado, luego mi total si es aggregate.:

Código Delphi [-]
FindFiles(pathDeBusqueda, '*.xml', False, TS);
  Etick.Text:=IntToStr(TS.Count);
  // Para cada fichero encontrado, realizamos el trabajo necesario...
  for i := 0 to (TS.Count - 1) do begin
    // Extraer nombre del fichero. en TS[i] está el path completo
    fName := pathDeBusqueda + ExtractFileName(TS[i]);
    if (ClientModule1.SQLConnection1.Connected) then
     begin

          
          with ClientModule1.cdsticketpendiente do
            begin

              LoadFromFile(fname);
              Open;

              First;
              while not Eof do

                begin
                Edit;
                FieldByName('subtotal').AsFloat:=FieldByName('precio').AsFloat * FieldByName('cantidad').AsFloat;
                 Post;
                 Next;
                end;

              end;

          importe:=ClientModule1.cdsticketpendientetotal.Value;
          fechae:=ClientModule1.cdsticketpendientefechae.AsString;

          horae:=ClientModule1.cdsticketpendientehorae.AsString;

          efectivo:=ClientModule1.cdsticketpendienteefectivo.AsFloat;
          vuelto:=efectivo - importe;


          a:=TServerMethods1Client.Create(ClientModule1.SQLConnection1.DBXConnection);
          a.nuevoticket(numero,ids,idc,importe,efectivo,vuelto,fechae,horae);
          ClientModule1.cdsticketpendiente.EmptyDataSet;

           ClientModule1.cdsticketpendiente.Close;
     TS.Free;

  end
Me dice : list index of bounds(1)
Debo cargar los otros campos?

giulichajari 24-03-2015 14:59:39

no logro enviar .xml a bd usando el server
 
Hola amigos! abro un nuevo hilo porque hice una pregunta en otro creo fuera de lugar:

Cuando no hay conexion guardo los tickets de mi terminal de puesto de venta en un fichero xml.

Y tengo un form donde de haber conexion voy recorriendo el directiorio de los tickets y quiero cargarlos en la base de datos.

Primero que los campos que no son Data no se guardan en xml, por lo tanto hay que recalcularlos.
Y luego que no veo los cambios en la base de datos.
Ademas, no me convendria tener otro tclientdataset distinto para poder hacer tickets mientras vienen clientes en vez de usar el mismo?

Código Delphi [-]
procedure TForm8.FormShow(Sender: TObject);
var
TS:TStringList;
pathDeBusqueda,fname:string;
i:integer;
a:TServerMethods1Client;
x:integer;
fechae,horae:string;
cantidad,importe,preciou,efectivo,vuelto:Double;
idc,ids,idprodu,numero:Integer;
nuevoticket:string;
tot:Double;
begin
// Crear la lista que vamos a utilizar
  TS := TStringList.Create();
  pathDeBusqueda:=ExtractFilePath(Application.ExeName) + 'tickets\';

  // Buscar ficheros en disco.
  FindFiles(pathDeBusqueda, '*.xml', False, TS);
  Etick.Text:=IntToStr(TS.Count);
  // Para cada fichero encontrado, realizamos el trabajo necesario...
  for i := 0 to (TS.Count - 1) do begin
    // Extraer nombre del fichero. en TS[i] está el path completo
    fName := pathDeBusqueda + ExtractFileName(TS[i]);
    // si hay conexion al server
    if (ClientModule1.SQLConnection1.Connected) then
     begin
     a:=TServerMethods1Client.Create(ClientModule1.SQLConnection1.DBXConnection);
      //cargo dataset
              with ClientModule1.cdsticket do
                 begin

              LoadFromFile(fname);
              Open;
                for x := 0 to ClientModule1.cdsticket.RecordCount do

                begin
                Edit;
                FieldByName('subtotal').AsFloat:=FieldByName('precio').AsFloat * FieldByName('cantidad').AsFloat;

                 Post;

                end;

                 end;
                 //cargo variables y llamo al server
                      importe:=ClientModule1.cdsticket.FieldByName('total').Value;
                fechae:=ClientModule1.cdsticketfechae.AsString;

                horae:=ClientModule1.cdstickethorae.AsString;

                efectivo:=ClientModule1.cdsticketefectivo.AsFloat;

                vuelto:=efectivo - importe;
                 idc:=1;
                 ids:=1;
                 numero:=1;
              a.nuevoticket(numero,ids,idc,importe,efectivo,vuelto,fechae,horae);
              a.Free;
         ClientModule1.cdsticket.EmptyDataSet;
     end;

  end;



end;

lo primero que hago es buscar los ficheros, luego compruebo si hay conexion, si hay para cada archivo hago subtotal y total, y llamo al servidor datasnap. vacio el dataset.

Alguien me puede ayudar

Casimiro Notevi 24-03-2015 18:05:43

Cita:

Empezado por giulichajari (Mensaje 490372)
Hola amigos! abro un nuevo hilo porque hice una pregunta en otro creo fuera de lugar:

Es el mismo asunto y ya te han respondido, no abras otro hilo para lo mismo, sigue con el que habías abierto.
Los he unido.


La franja horaria es GMT +2. Ahora son las 05:55:43.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi