PDA

Ver la Versión Completa : Tablas de Paradox en un TreeView - DBGrid


Goyo
27-06-2007, 17:52:47
Estoy diseñando un sistema de control de alumnos, pero tengo una duda de como hacer para que me aparezca un ARBOL con los semestres y a su vez dentro de cada semestre las materias que pertenecen a ese semestre y en un DBGrid capturar las calificaciones por alumno de la materia que este seleccionada, para ello cuento con 4 tablas en paradox:

Tabla: Alumnos
id_alumno : key
Nombre
Apellidos
id_semestre
....etc

Tabla: Semestres
id_semestre : key
Semestre

Tabla: Asignaturas
id_asignatura : key
Asignatura
id_semestre
... etc.

Tabla: Calificaciones
id_calificacion : key
id_asignatura
id_alumno
calificacion
.
.
Les explico como quiero que aparezcan los datos en el formulario:
-----------------------------------------------------------------
Nombre del Alumno: Juan Perez Matricula: 4206 Grupo: A
-----------------------------------------------------------------
----------------------------- Calificacion
->Semestre 1
------>Biologia I ________________ 10
------>Fisica I __________________ 9
------>Historia de Mexico I ________ 8
------>Matematicas I ____________ 7
------>Ingles I __________________10
->Semestre 2
------>Biologia II ________________ 10
------>Fisica II _________________ 10
------>Historia de Mexico II _______10
------>Matematicas II ___________ 10
------>Ingles II _________________10
.
.
Delante del Cuadro del Arbol (Treeview) un Dbgrid donde se pueda escribir la calificacion que corresponde al alumno y esa materia que se tiene seleccionada. Osea que si tengo seleccionado el semestre 2 y la materia Matematicas II, en el DBGrid se capture la calificacion.

anexo una imagen de lo que pretendo realizar.... de antemano muchas gracias por su ayuda.

Saludos

Neftali [Germán.Estévez]
27-06-2007, 18:12:19
Supongo que tendrás que generar el TreeView a la Izquierda de forma manual; Y los elementos seleccionados a la izquierda (asignatura) son los que te servirán de Filtro para la última consulta sobre la tabla calaficaciones (con alguna JOIN para obtener campos de las otras) que es la que debes mostrar en el Grid de la derecha.
Al cambiar la selección a la izquierda (otra asignatura) vualves a montar la SQL y la vuelves a lanzar.

¿Exactamente qué es lo que necesitas? ¿Rellenar el Tree? ¿DBGrid? ¿La consulta?
El planteamiento es claro, lo que no explicas es la duda/error que tienes.

Goyo
27-06-2007, 18:18:32
Supongo que tendrás que generar el TreeView a la Izquierda de forma manual; Y los elementos seleccionados a la izquierda (asignatura) son los que te servirán de Filtro para la última consulta sobre la tabla calaficaciones (con alguna JOIN para obtener campos de las otras) que es la que debes mostrar en el Grid de la derecha.
Al cambiar la selección a la izquierda (otra asignatura) vualves a montar la SQL y la vuelves a lanzar.

¿Exactamente qué es lo que necesitas? ¿Rellenar el Tree? ¿DBGrid? ¿La consulta?
El planteamiento es claro, lo que no explicas es la duda/error que tienes.

lo que necesito saber es como llenar el Treeview con las tablas (Semestre, Asignaturas y como enlazaria el dbgrid (calificaciones), y como se realizaría la consulta.. creo que ademas como enlazaria la tabla alumnos con todas estas demas tablas...

un saludo y gracias

Goyo
29-06-2007, 17:26:37
me contesto yo mismo, despues de buscar por la web informacion de como llenar un TreeView, encontre un Componente gratuito VirtualTree http://www.delphi-gems.com que hace exactamente lo mismo, que el TreeView normal.

Bueno les explico de como llenarlo utilizando dos tablas (Semestre: id_semestre, Semestre, Asignatura: id_materia,materia), para ello creamos una nueva aplicacion, introducimos el componente VirtualStringTree (deben tenerlo ya instalado) y despues dos TTable1..2 y dos Dataset1..2, y dos DbGrid para visualizar las tablas (esto lo pueden omitir); ya que se tienen estos componentes: unimos el TTable1 a la tabla maestra (TbSemestres) y el DataSet1 (DsSemestres) y la activamos, ahora en el TTable2 que sera nuestra tabla detalle (TbAsignaturas) y el Dataset2 (DsAsignaturas), una vez que ya se tiene la TbAsignaturas, nos vamos a su propiedad MasterSource: y seleccionamos DsSemestres, y en su propiedad IndexName: sera el indice de tipo Case Sensitive (campo que unira ambas tablas) de la tabla Asignaturas, escribimos Id_Semestre y en la propiedad MasterField: Id_semestre (campo a ligar con la tabla Semestre) y activamos en TbAsignaturas.

aqui les pongo el codigo que hara el resto para crear el arbol con las dos tablas)... obviamente yo lo traduci al español el tutorial completo se encuentra en: http://www.keashsoft.com/ que de donde yo lo baje.


unit ejemploVirtualTree;
{
Virtualstrees and DBs
(C) 2005 Florian Köllich, www.keashsoft.com (http://www.keashsoft.com)
Available under GPL.
Este programa demuestra el uso de VirtualTree de Mike Lischke
conjuntamente con una relación maestro/detalle. Aquí, se utilizan
las bases de datos “Semestre.db” del ejemplo de los BDE y “Asinaturas.db”.
Requerimientos:
* Paquete Virtualtrees disponible en www.delphi-gems.com (http://www.delphi-gems.com)
* con ejemplos de bases de datos del BDE.
}
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, DB, DBTables, StdCtrls, ExtCtrls, Grids, DBGrids, VirtualTrees;
type
// Definicion de los datos a usar en el VirtualTree:
PMyData = ^TMyData;
TMyData = record
id_semestre: String[8];
NomSemestre:String[255];
id_materia: String[10];
materia: String[255];
end;
type
TForm1 = class(TForm)
tree: TVirtualStringTree;
Panel1: TPanel;
CheckBox1: TCheckBox;
Memo1: TMemo;
DsAsignaturas: TDataSource;
DsSemestre: TDataSource;
TbSemestres: TTable;
TbAsignaturas: TTable;
DBGrid3: TDBGrid;
DBGrid4: TDBGrid;
procedure FormCreate(Sender: TObject);
procedure treeInitNode(Sender: TBaseVirtualTree; ParentNode,
Node: PVirtualNode; var InitialStates: TVirtualNodeInitStates);
procedure treeInitChildren(Sender: TBaseVirtualTree;
Node: PVirtualNode; var ChildCount: Cardinal);
procedure treeGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
Column: TColumnIndex; TextType: TVSTTextType;
var CellText: WideString);
procedure CheckBox1Click(Sender: TObject);
procedure treeChange(Sender: TBaseVirtualTree; Node: PVirtualNode);
private
{ Private declarations }
public
{ Public declarations }
procedure RebuildTree; // llamada para construir/actualizar el arbol
end;
var
Form1: TForm1;
bAutoLocate : boolean;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
RebuildTree;
end;
procedure TForm1.RebuildTree;
begin
// sistema RootNodeCount y NodeDataSize aqui.
// Los datos se asignan para cada nodo en OnInitNode.
tree.RootNodeCount := TbSemestres.RecordCount;
tree.NodeDataSize := SizeOf(TMyData);
end;
procedure TForm1.treeInitNode(Sender: TBaseVirtualTree; ParentNode,
Node: PVirtualNode; var InitialStates: TVirtualNodeInitStates);
var data:PMyData;
begin
// llenar un nodo con las Tablas Semestre y Asignaruas. El metodo
// GetNodeLevel es utilizado sin distinguir entre el nodo maestro/detalle
// Ttable's RecNo esta característica se utiliza para recuperar los datos correctos del nodo
data := Sender.GetNodeData(Node);
if Sender.GetNodeLevel(Node) = 0 then
begin
// Nodo maestro - Semestre
TbSemestres.RecNo := node.Index + 1;
data.id_semestre := TbSemestres.fieldbyname('id_semestre').asString;
data.nomsemestre := TbSemestres.fieldbyname('NomSemestre').asString;
if TbAsignaturas.RecordCount>0 then InitialStates:=InitialStates+[ivsHasChildren];
end else
begin
// Nodo Detalle - Asignaturas
TbSemestres.RecNo := parentnode.Index + 1;
TbAsignaturas.RecNo := Node.Index + 1;
data.id_semestre := TbSemestres.fieldbyname('id_semestre').asString;
data.nomsemestre := TbSemestres.fieldbyname('nomsemestre').asString;
data.id_materia := TbAsignaturas.fieldbyname('id_materia').asString;
data.materia := TbAsignaturas.fieldbyname('Materia').AsString;
end;
end;
procedure TForm1.treeInitChildren(Sender: TBaseVirtualTree;
Node: PVirtualNode; var ChildCount: Cardinal);
begin
// establecer ChilCount al RecordCount del dataset del detalle
TbSemestres.RecNo := node.Index+1;
childcount := TbAsignaturas.RecordCount;
end;
procedure TForm1.treeGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString);
var data:PMyData;
begin
// Aqui se despliegan los datos
data := Sender.GetNodeData(node);
if Sender.GetNodeLevel(node) = 0 then
// CellText := inttostr(data.id_semestre) + ' ' + data.NomSemestre
CellText := data.id_semestre + ' ' + data.NomSemestre
else
CellText := format('%s %s',[data.id_materia,data.Materia]);
end;
procedure TForm1.CheckBox1Click(Sender: TObject);
begin
bAutoLocate := checkbox1.checked;
end;
procedure TForm1.treeChange(Sender: TBaseVirtualTree; Node: PVirtualNode);
begin
// Autolocate asegura de que la seleccion del arbol y los
// cursores de los datasets sean sync'd.
if bAutoLocate and assigned(node) then
begin
if sender.GetNodeLevel(node) = 0 then
TbSemestres.RecNo:=node.Index+1
else begin
TbSemestres.RecNo:=node.parent.Index+1;
TbAsignaturas.RecNo:=node.Index+1;
end;
end;
end;
end.


espero sea de mucha utilidad a todas aquellas personas que como yo quieren ampliar mas su conocimiento en la programacion de delphi... por cierto respecto a este programa como lo dice la primer pregunta formulada, ahora no se como unir este codigo del arbol para que cuando yo seleccione un alumno, me muestre el arbol y al seleccionar una asignatura, automaticamente en un DbGrid me muestre el registro para que pueda yo capturar y/o modificar alguna calificacion de este alumno y de la materia seleccionada en el Treeview....

de antemano muchas gracias por la atencion...
saludos

Genner
05-12-2007, 18:33:52
Por que no pruebas en el evento OnDblClick del TreeView ahi puedes tomar el valor del puntero para hacer una consulta o para lo que gustes, te dejo un pedazo de codigo, espero te sirva


procedure TForm1.treeDblClick(Sender: TObject);
var
datos:PNodeData;
begin
datos:=tree.GetNodeData(Tree.FocusedNode);
showMessage(datos.Texto);
end;

PAra tu caso supongo que seria


procedure TForm1.treeDblClick(Sender:Tobject);
var
datos:PMyData;
begin
datos:=tree.GetNodeData(Tree.FocusedNode); //aqui tomas el valor del nodo seleccionado
showMessage(datos.IdSemestre);<- con esto tomas la clave del semestre
end;


Espero te sirva.

Lepe
06-12-2007, 20:02:51
Completo un poco más.

Si el VirtualTreeview tienes HideSelection a false, y te aseguras mediante código de que hay algo seleccionado, entonces no hay problema.

En caso contrario, es bueno hacer primero la comprobación:

if tree.FocusedNode <> nil then


o bien:

if Assigned(tree.FocusedNode) then


PD: El VirtualStringTree tiene el evento OnFocusChanged, con un parámetro que indica el nodo que tiene el foco y la columna. Lugar oportuno para usar el código de Genner.

El hilo es de hace 6 meses, pero al menos dejamos la respuesta para futuras búsquedas. Gracias por reavivarlo Genner.

Saludos

Saludos