Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > OOP
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Grupo de Teaming del ClubDelphi

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 16-12-2008
DANY DANY is offline
Miembro
 
Registrado: nov 2003
Posts: 145
Poder: 21
DANY Va por buen camino
Recorrer TreeView y calcular totales

Tengo un TreeView con sus propiedades pointer apuntando a objetos , cada hoja del arbol (que es una cuenta contable) contiene un valor.
Necesito sumar recursivamente los valores de las hojas. y mostralos. Es decir, que quede algo como:
Código:
1.---------100
1.1.-------------50
1.1.1.----------------20(este nodo es hoja)
1.1.2-----------------30(este nodo es hoja)
1.2--------------40
1.3--------------10.
Alguna idea? gracias.
Gracias.
Responder Con Cita
  #2  
Antiguo 17-12-2008
Avatar de javier7ar
javier7ar javier7ar is offline
Miembro
 
Registrado: abr 2006
Ubicación: Argentina
Posts: 124
Poder: 19
javier7ar Va por buen camino
En la propiedad Items estan los nodos, y en la propiedad Data de cada nodo hay un puntero a tu objeto (tenes que hacer un cast con la clase de tu objeto). Lo podes recorrer asi:

Código Delphi [-]
  
for i := 0 to miTreeView.Items.Count -1 do
  ShowMessage(TCuentaContable(miTreeView.Items[i].Data).Nombre);
Responder Con Cita
  #3  
Antiguo 17-12-2008
DANY DANY is offline
Miembro
 
Registrado: nov 2003
Posts: 145
Poder: 21
DANY Va por buen camino
Si, eso lo entiendo, el asunto es que solo poseo datos de" cada hoja" por ser las cuentas que tienen movimientos, el asunto es ir calculando y asignando la sumatoria de todos los hijos a cada padre , abuelo, etc.
Insisto, no lo debo calcular con una consulta SQL de la base para cada cuenta , por que las cuentas sumarizadoras (las que no son hojas) no tienen movimientos.
para que tengan una idea mas clara yo en mi arbol tengo esto
Código:
1.---------?
1.1.-------------?
1.1.1.----------------20(este nodo es hoja)
1.1.2-----------------30(este nodo es hoja)
1.2--------------?
1.3--------------?.
2----------------?.
2.1--------------75 (este nodo es hoja, difiere del nivel de las hojas anteriores)
Responder Con Cita
  #4  
Antiguo 17-12-2008
Avatar de Neftali [Germán.Estévez]
Neftali [Germán.Estévez] Neftali [Germán.Estévez] is offline
[becario]
 
Registrado: jul 2004
Ubicación: Barcelona - España
Posts: 18.293
Poder: 10
Neftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en bruto
Se me ocirre que podrías enmpezar el recorrido en orden inverso, desde el útimo nodo hasta el primero.
(1) Estando en el último nodo, sumas en un acumulador (acum);
(2) Pasas al nodo anterior.
(a) Si es un nivel inferior colocas el acumulador en el nodo y al acumulador le sumas el valor.
(b) Si es de un nivel superior borras el acumulador.
(c) Si es del mismo nivel sólo sumas en el acumulador el valor que haya en el nodo.

(3) Repetir el paso (2)

Algo así, aunque estoy un poco espeso...
__________________
Germán Estévez => Web/Blog
Guía de estilo, Guía alternativa
Utiliza TAG's en tus mensajes.
Contactar con el Clubdelphi

P.D: Más tiempo dedicado a la pregunta=Mejores respuestas.
Responder Con Cita
  #5  
Antiguo 17-12-2008
Avatar de Caro
*Caro* Caro is offline
Moderadora
 
Registrado: jul 2004
Ubicación: Cochabamba, Bolivia
Posts: 2.544
Poder: 22
Caro Va por buen camino
Hola, te pongo de la forma en que yo lo haría, puede que no este bien controlado y falte mas cosas. Utilizo HasChildren para ver si la hoja tiene hijos o no, si no tiene entonces significa que puedo sumar ese valor y otra cosita importante es ver si la hoja de ultimo nivel (la que tien valor) tiene padres para ir sumando hacía arriba hasta terminar con todos sus padres y lo que te dijo el amiguito Neftali recorrer desde el ultimo nodo.

Código Delphi [-]
var
 NodoPadre : TTreeNode;
 Ind, suma : Integer;
begin
 Ind := TreeView1.Items.Count-1;
 suma := 0;
 While Ind>0 Do
  begin
    If Not TreeView1.Items[Ind].HasChildren Then
     begin
      suma := suma + StrToInt(TreeView1.Items[Ind].Text);
      if TreeView1.Items[Ind].Parent=Nil then
       suma := 0
      else
       begin
        //Tiene un nodo padre
        NodoPadre := TreeView1.Items[Ind].Parent;
        While NodoPadre <> nil do
         begin
          NodoPadre.Text := IntToStr(StrToInt(NodoPadre.Text)+suma);
          suma := StrToInt(NodoPadre.Text);

          NodoPadre := NodoPadre.Parent;
         end;//While
        suma := 0;
       end;//else
      Dec(Ind);
     end
    else
     Dec(Ind);
  end;//While
end;

Has tus pruebas poniendo enteros en cada nodo de tus nodos hijos y 0 en los padres, ya despues tu ves los demas controles que tienes que aumentar.

Saluditos
__________________
Disfruten cada minuto de su vida a lado de sus seres queridos como si fuese el ultimo, uno nunca sabe lo que puede pasar.
Responder Con Cita
  #6  
Antiguo 17-12-2008
Avatar de Lepe
[Lepe] Lepe is offline
Miembro Premium
 
Registrado: may 2003
Posts: 7.424
Poder: 29
Lepe Va por buen camino
Estás mezclando la interfaz con la lógica de la aplicación... no es buena idea porque te complica todo lo demás.

En teoría, deberías tener una jerarquía de clases, o al menos varias listas unas dentro de otras formando el arbol... pero con TObject y TObjectList. Eso ya te da toda la potencia para calcular los totales y lo que quieras.

Pasarlo al Treeview, es sólo recorrer las listas y crear nodos... cosa de poca monta, vamos.

Código Delphi [-]
type 
Tcuenta = TObject;
Tcuentas = class (TObjecList)
  public 
      property items[index:integer]:Tcuenta read getItem write SetItem;
      property Total :Extended read GetTotal;
end;

Con una definición así puedes hacer todas las virguerías que quieras, sumas, eventos al modificar una cuenta y un total... etc.

Saludos
__________________
Si usted entendió mi comentario, contácteme y gustosamente,
se lo volveré a explicar hasta que no lo entienda, Gracias.
Responder Con Cita
  #7  
Antiguo 17-12-2008
Avatar de Delphius
[Delphius] Delphius is offline
Miembro Premium
 
Registrado: jul 2004
Ubicación: Salta, Argentina
Posts: 5.582
Poder: 25
Delphius Va camino a la fama
Cita:
Empezado por Lepe Ver Mensaje
Estás mezclando la interfaz con la lógica de la aplicación... no es buena idea porque te complica todo lo demás.

En teoría, deberías tener una jerarquía de clases, o al menos varias listas unas dentro de otras formando el arbol... pero con TObject y TObjectList. Eso ya te da toda la potencia para calcular los totales y lo que quieras.

Pasarlo al Treeview, es sólo recorrer las listas y crear nodos... cosa de poca monta, vamos.
Código Delphi [-]

type  
 Tcuenta = TObject; 
 Tcuentas = class (TObjecList)  
  public property items[index:integer]:Tcuenta read getItem write SetItem;
  property Total :Extended read GetTotal; end;
Con una definición así puedes hacer todas las virguerías que quieras, sumas, eventos al modificar una cuenta y un total... etc.

Saludos
Me gusta tu diseño amigo,
Si no es molestia, yo me meto también. Yo me imagino un esquemita más complicado. Si me disculpan, he aquí un Composite:

Código Delphi [-]
unit UCuentas;

interface

uses classes, Contnrs;

type
  TCuentaAbstracta = class(Tobject)
  public
    function GetTotal: integer; virtual; abstract; // es necesario abstracto
    // cada tipo de cuenta implementará SetTotal según a "convenir"
  end;

  TCuenta = class (TCuentaAbstracta) // una simple cuenta
  private
    FTotal: integer;
  public
    procedure SetTotal(Value: integer);
    function GetTotal: integer; override;
  end;

  TCuentaCompuesta = class (TCuentaAbstracta) // una cuenta compuesta por una o más
  private
    FListaCuentas: TObjectList; // El listado de cuentas
  public
    function GetTotal: integer; override;
    function AddCuenta(Cuenta: TCuentaAbstracta): integer;
  end;


implementation

{ TCuentaCompuesta }

function TCuentaCompuesta.AddCuenta(Cuenta: TCuentaAbstracta): integer;
begin
  result := FListaCuentas.Add(Cuenta);
end;

function TCuentaCompuesta.GetTotal: integer;
var i: integer;
begin
  result := 0;
  // calculamos el total desde la lista de cuentas
  // como se ve... se invoca al método GetTotal según la clase que lo implementa.

  // una clase compuesta en su lista puede tener tantas clases compuestas
  // como "simples" se desee. De este modo, SetTotal siempre devolverá el total
  // de las cuentas que la componen.
  for i := 0 to FListaCuentas.Count - 1 do
    inc(result,TCuentaAbstracta(FListaCuentas.Items[i]).GetTotal);
end;

{ TCuenta }

function TCuenta.GetTotal: integer;
begin
  result := FTotal;
end;

procedure TCuenta.SetTotal(Value: integer);
begin
  FTotal := Value;
end;

end.

Se que es muy simple pero creo que se entiende el principio. La clase TCuentaCompuesta tiene un lista de cuentas. Este listado puede estar formado por cuentas simples, o incluso otras cuentas compuestas.

Básicamente el método SetTotal de una clase TCuentaCompuesta iterará recursivamente por todas las TCuentaCompuesta que componen el listado, hasta llegar a las cuentas simples. Fíjese que TCuentaCompuesta posee un método AddCuenta y por tanto pueden añadirse ambos tipos de cuenta.

Bajo este patrón Composite, se puede trabajar en forma análoga al esquema "árbol".
Si bien es un diseño un tantito más complejo debido a que introduce nuevas clases, en ocasiones este diseño es útil puesta que aclara mejor como el dominio. Se ve claramente como se tratan las cuentas simples de las compuestas.

Bueno, es sólo otra opción. Desde lo lógico. Como menciona Lepe.

Saludos compuestos,
__________________
Delphius
[Guia de estilo][Buscar]
Responder Con Cita
  #8  
Antiguo 17-12-2008
Avatar de javier7ar
javier7ar javier7ar is offline
Miembro
 
Registrado: abr 2006
Ubicación: Argentina
Posts: 124
Poder: 19
javier7ar Va por buen camino
Esta como para poner en el libro jeje Iba a sugerir una funcion recursiva para calcular los totales recorriendo el TreeView, pero me parece que esto que proponen es mas elegante
Saludos
Responder Con Cita
  #9  
Antiguo 17-12-2008
DANY DANY is offline
Miembro
 
Registrado: nov 2003
Posts: 145
Poder: 21
DANY Va por buen camino
Perfecto amigo lepe, en mi objeto cuentaContable tengo asociada CuentaMadre que hace referencia por supuesto a la cuenta que la agrupa (aca la jerarquia es entre madres , abuelas, etc. las mujeres dominan ). es simple para cada cuenta voy recorriendo y obteniendo los totales con una funcion recursiva. Cuando tenga el codigo lo posteo, pero con la idea de base no tendra mucho valor.
Gracias por aclararme los tantos, estaba por "ensuciar" mi clase, encima no se me ocurría como.
Saludos.
Responder Con Cita
  #10  
Antiguo 18-12-2008
DANY DANY is offline
Miembro
 
Registrado: nov 2003
Posts: 145
Poder: 21
DANY Va por buen camino
Lo logre!!!

Metodos de mi clase :
Código Delphi [-]
function TCuentasContables.DevuelveSaldoCuenta: Double;
begin

  //Si la cuenta es imputable devuelvo el valor saldo cuenta cargado de la BD una vez creada la cuenta
  if CuentaImputable  then
    Result := SaldoCuenta
 //Si no lo es itero hasta llegar a cuentas imputables.
  Else
    Result := Result + DevuelveSaldoCuentasHijas ;

end;

Código Delphi [-]
function TCuentasContables.DevuelveSaldoCuentasHijas: Double;
var
  I : Integer;
begin
  if not Assigned(CuentasHijas) then
  Begin
    Result :=0;
    Exit;
  End;

  for I := 0 to CuentasHijas.Count-1 do
    Result := Result +TCuentasContables(CuentasHijas.Items[i]).DevuelveSaldoCuenta ;

end;

Luego desde el form para mostrar en el arbol:
Código Delphi [-]
  for N :=1  to tvArbol.Items.Count -1 do
    tvArbol.Items [N].Text := tvArbol.Items [N].Text +' ( '+ FormatFloat ('$0.00', TCuentasContables (tvArbol.Items [N].Data ).DevuelveSaldoCuenta )+' )';

Gracias a todos.
Mision Cumplida!!!
Responder Con Cita
  #11  
Antiguo 18-12-2008
Avatar de Lepe
[Lepe] Lepe is offline
Miembro Premium
 
Registrado: may 2003
Posts: 7.424
Poder: 29
Lepe Va por buen camino
Te voy a comentar una chapuza (con la esperanza de que alguien me de soluciones... ¿por qué no? ) para evitar los moldeos de tipos.

Desde luego el código se hace más legible y es muy muy fácil hacerlo.

En Tcuentascontables defines una función:
Código Delphi [-]

TCuentasContables = class(TObject)
public
 function AsCuentaContable:TCuentasContables;
end;

function AsCuentasContable:TCuentasContables;
begin
  result := TCuentasContables(self);
end;

De forma que tu linea:
Código Delphi [-]
TCuentasContables (tvArbol.Items [N].Data ).DevuelveSaldoCuenta
quedaría como :
Código Delphi [-]
tvArbol.Items[N].Data.AsCuentaContables.DevuelveSaldoCuenta

Este truquito lo he usado en una sóla ocasión, y la verdad el código se aclaró bastante en legibilidad. No sé si hay otra solución, espero que sí .

En mi caso, tanto Talbaran, TFactura y TCliente heredaban de TBaseObject y en TBaseObject creé esas 3 funciones asAlbaran, AsFactura, AsCliente. Por supuesto en la aplicación siempre usaba TBaseObject para crear los objetos:
Código Delphi [-]
var
  nuevo :TBaseObject;
begin
   nuevo := TAlbaran.Create(...);
end;
A partir de ahora, uso nuevo.asAlbaran y elimino todos los moldeos de tipos que usaba en la aplicación final.

Por supuesto debes saber lo que haces, porque si tienes un Talbaran y pides asCliente tendrás errores de ejecución (probablemente...).

Como ves, realmente el moldeo de tipos no hay quien lo quite, está presente en las funciones, pero en la aplicación final no tienes ninguno.

Saludos.
__________________
Si usted entendió mi comentario, contácteme y gustosamente,
se lo volveré a explicar hasta que no lo entienda, Gracias.

Última edición por Lepe fecha: 18-12-2008 a las 11:02:47.
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Recorrer Tabla, contar registro repetidos y escribir totales en otra Tabla Lucas_diaz1810 Conexión con bases de datos 1 25-12-2006 13:04:34
Como recorrer un los item de un treeview Shidalis OOP 7 03-08-2005 17:06:29
Como utilizar el Treeview, desplegar la info del arbol binario al treeview leo21 Varios 2 08-04-2004 22:47:30
Como utilizar el Treeview, desplegar la info del arbol binario al treeview leo21 OOP 1 08-04-2004 22:42:44
Recorrer un Treeview mateamargo OOP 0 11-11-2003 16:53:39


La franja horaria es GMT +2. Ahora son las 09:55:04.


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
Copyright 1996-2007 Club Delphi