怎样做客户-年月日定单数据的树型结构(100分)

  • 主题发起人 主题发起人 wdsu
  • 开始时间 开始时间
W

wdsu

Unregistered / Unconfirmed
GUEST, unregistred user!
请教各位高手:
我现在做一个家庭用的小型定单进帐系统,输入部分已经完成,现在我想在主窗口
中添加一个viewtree控件,此控件的第一个节点是客户名,第二个节点是日期(如2002
年5月19日)接下去单击该日期节点,则在右边的GDbrid中显示该客户数据。
现在数据库里的数据已经存在了,我想在程序启动时,首先扫描数据库了的数据,
然后自动创建上面的树结构,因为我的数据是每天更新的,所以每天打开程序程序里
的数据都有更新的。 wdsu@htc.net.cn
我是初学者,分数不多,还要留着以后再用,所以每次提问时给分不多,请谅解。
谢谢!静候佳音。
 
表的结构如下:
ID 递增
客户 char(10)
定单日期 datatime

var
node:ttreenode;
begin
adoquery1.sql.text:='select * from 表';
adoquery1.open;
while not adoquery1.eof do
begin
node:=treeview1.add(nil,adoquery1.fieldbyname('客户').value);
treeview1.add(node,adoquery1.fieldbyname('定单日期').value);
end;

显示数据在dbgrid中的方法如下:(程序写在treeview的onchange事件中)
adoquery1.close;
adoquery1.sql.text:='select * from 表 where 客户名=:kefu';
adoquery1.parameters.parambyname('kefu').value:=treeview1.selected.text;
adoquery1.open;

以上是凭印象写的没有调试,如果不行请跟我联系 1shao@soim.com
 
to 一成:
谢谢你给我的答复,但我有点疑惑,想请教。
我的数据表如下:
客户表:
customer: int char char char
customerid customername customeraddr customertel
客户编号 客户姓名 客户地址 客户电话
定单表:
orders: int int date int
ordersno customerid orderdate ordersnum
定单编号 客户编号 定货日期 定单总数量
详细记录表:
ordersdetail int int int int
ordersno itemsno partsno numbers
定单编号 子项目序号 产品代号 数量

你所说的
表的结构如下:
ID 递增
客户 char(10)
定单日期 datatime
是否还要另建一张数据表?

 
还有谁帮帮忙看一看。
 
在Item的Data里存放一个记录,记录查寻所必须有的信息
当单击Item时,取出保存的记录,按记录进行数据库查询
释放Item时,记得到相应的记录也删除

试试^_^
 
to wlmmlw:
谢谢,你所说的data是什么样的记录,我应该定义什么样的record呢我想展开两极,象
客户A-2000年-1月1日
1月2日
1月3日

。 单击1月1日后, 此处显示定单详表:
ordersdetail的内容。

1月31日
2月1日
2月2日



2月28日




2001年-1月1日



12月31日
2002年-1月1日



12月31日
客户B-2000年-1月1日



12月31日
请问根据客户名和日期来浏览定单数据,上面的树型结构是否合理,
该做什么样的改进。谢谢。请回wdsu@htc.net.cn。不胜感激拉。
 
1.在form的onshow事件里
var
node:ttreenode;
begin
query1.sql.text:='select * from customer';
query1.open;
query1.first;
while not query1.eof do
begin
node:=treeview1.add(nil,query1.fieldbyname('customerid').value+' '+query1.fieldbyname('customername').value);
query2.sql.text:='select * from orders;
query2.open;
query1.first;
while not query2.eof do
begin
treeview1.add(node,query2.fieldbyname('orderdate').value);
query2.next;
end;
query1.next;
end;
end;

2.设置客户,定单,定单明细三个表的主从关系。
在treeview的onclick事件中
var
s:string;
Adate:TDatetime;
begin
s:=trim(treeview.selected.Text);//忘了具体的属性了,获取选择的客户
s:=copy(s,1,pos(' ',s)-1);
TCustomer.locate('customerid',s,[...]);
s:=trim(treeview.selected.Text);//忘了具体的属性了,获取选择的客户
s:=copy(s,pos(' ',s)+1,length(s));
Adate:=strtodate(s);
TOrders.Locate('orderdate',adate,[...]);
end;

3.建议客户资料用dbedit控件,定单和定单明细用dbgrid
 
不必了,就用你现成的结构吧

客户表:
customer: int char char char
customerid customername customeraddr customertel
客户编号 客户姓名 客户地址 客户电话
定单表:
orders: int int date int
ordersno customerid orderdate ordersnum
定单编号 客户编号 定货日期 定单总数量
详细记录表:
ordersdetail int int int int
ordersno itemsno partsno numbers
定单编号 子项目序号 产品代号 数量

上面三个表的编号最好用自动递增类型
 
如果光是treeview的问题的话,只要了解
treeview1.Items.Add

treeview1.Items.AddChild
就ok了

在onchange 事件访问你的表的数据
前提
记得加上 seleted 不为空才访问数据的判断,否则会出现问题


 
你的问题应该比较简单,这是常用的功能,你可以这样
右边用一个notebook控件,两页,第一页显示客户资料(用dbedit),第二页显示客户
订单表(详细记录也可以在这里显示,设成主从结构,用两个dbgrid),
当用户点中客户时,则显示notebook的第一页(客户资料),把记录定位到该客户上(adodataset.locate)
当用户点中日期时,显示客户的定单资料(要传入两个参数才行,客户号,日期)
下面是我所做项目中的一个建树的例子,希望对你有帮助。如果数据量比较大,可以
开始只建一层树,当用户点击客户时,再建第二层树

procedure TFrmOperator.InitTreeView(TreeView1:TTreeView;Userid:string;has:Boolean);
var
AdoTemp,Adotemp1,adotemp2:TadoDataset;
TreeNode1,TreeNode2,TreeNode3:TTreeNode;
WhereSql,sql:string;
begin
TreeView1.Items.Clear;
if has then
WhereSql:=' and id in (select modulid from tblpower where No='''+userid+''')'
else
WhereSql:=' and id not in (select modulid from tblpower where No='''+userid+''')';
if Userid='All' then
WhereSql:='';
AdoTemp:=TadoDataset.Create(nil);
AdoTemp.Connection:=AdoConnection1;
AdoTemp.CommandText:='select * from Tblmodul where upid=''0''';
AdoTemp.Open;

if AdoTemp.IsEmpty then
begin
AdoTemp.Free;
exit;
end;
adotemp1:=Tadodataset.Create(nil);
adotemp1.Connection:=adoconnection1;

adotemp2:=Tadodataset.Create(nil);
adotemp2.Connection:=adoconnection1;


AdoTemp.First;
while not AdoTemp.Eof do
begin
new(TreeData);
TreeData^.id:=AdoTemp.fieldbyname('id').asstring;
TreeData^.name:=AdoTemp.fieldbyname('name').AsString;
TreeData^.Subitem:=AdoTemp.fieldbyname('Subitem').AsBoolean;
TreeData^.UpId:=AdoTemp.fieldbyname('Upid').AsString;
adotemp1.Close;
adotemp1.CommandText:='select * from tblmodul where upid='''+TreeData^.id+''''+WhereSql;
adotemp1.Open;
if adotemp1.IsEmpty then
begin
if TreeData^.Subitem =False then
begin
TreeNode1:=TreeView1.Items.Add(nil,TreeData^.name);
TreeNode1.Data :=TreeData;
end;
AdoTemp.Next;
continue;
end;
TreeNode1:=TreeView1.Items.Add(nil,TreeData^.name);
TreeNode1.Data :=TreeData;
adotemp1.First;
while not adotemp1.Eof do
begin
new(TreeData);
TreeData^.id :=adotemp1.fieldbyname('id').AsString;
TreeData^.name:=adotemp1.fieldbyname('name').AsString;
TreeData^.Subitem:=AdoTemp1.fieldbyname('Subitem').AsBoolean ;
TreeData^.UpId:=AdoTemp1.fieldbyname('Upid').AsString;
adotemp2.Close;
sql:='select * from tblmodul where upid='''+TreeData^.id+''''+WhereSql;
adotemp2.CommandText:=sql;
adotemp2.Open;
if adotemp2.IsEmpty then
begin
if TreeData^.Subitem =False then
begin
TreeNode2:=TreeView1.Items.AddChild(TreeNode1,TreeData^.name);
TreeNode2.Data :=TreeData;
end;
adotemp1.Next;
continue;
end;
TreeNode2:=TreeView1.Items.AddChild(TreeNode1,TreeData^.name);
TreeNode2.Data :=TreeData;
adotemp2.First;
while not adotemp2.Eof do
begin
new(TreeData);
TreeData^.id :=adotemp2.fieldbyname('id').AsString;
TreeData^.name:=adotemp2.fieldbyname('name').AsString;
TreeData^.Subitem:=AdoTemp2.fieldbyname('Subitem').AsBoolean ;
TreeData^.UpId:=AdoTemp2.fieldbyname('Upid').AsString;
TreeNode3:=TreeView1.Items.AddChild(TreeNode2,TreeData^.name);
TreeNode3.Data :=TreeData;
adotemp2.Next;
end;
adotemp1.Next;
end;
AdoTemp.Next;
end;
adotemp.free;
adotemp1.Free;
adotemp2.Free;

end;
 
To Dephilai:
你好,首先谢谢你给我的解答,我有点疑惑想请教:
我按你的思路试了一下,代码如下:
procedure Tfm_mainxt.FormShow(Sender: TObject);
var
node:ttreenode;
begin
with datamodule2 do
begin
qrytemp.close;
qrytemp.sql.Clear;
qrytemp.sql.Add('select * from customer order by customerid');
qrytemp.open;
qrytemp.first;
while not qrytemp.eof do
begin
node:=treeview1.Items.add(nil,qrytemp.fieldbyname('customerid').AsString+'@'+qrytemp.fieldbyname('customer_name').AsString);
qryorders.Close;
qryorders.sql.Clear;
qryorders.sql.Add('select * from orders where customerid='''+qrytemp.FieldByName('customerid').AsString+'''order by orderdate''');
qryorders.open;
A:--------------- qryorders.First;//[red]在此处出错![/red]
while not qryorders.Eof do
begin
treeview1.Items.Add(node,
qryorders.fieldbyname('orderdate').AsString);
qryorders.next;
end;
qrytemp.next;
end;

end;
end;
我调试是在上面的A处出错,错误信息为:Missing right quote,缺少右引号,为什么?
既然qryorders.sql.add()的语句都已通过,为何在first中发生错误。请帮我检查一下有
和错误? 另外我自己写的代码如下,结果有很多错误,不知错在那里?
type
PMyRec=^TMyRec;
TMyRec=record
ID:string;
IsExpanded:string;
end;

function TFm_mainxt.BuildTree(var Node:TTreeNode;customerid:integer):TTreeNode;
var
RecPtr:PMyRec;
nodetemp:TTreenode;
begin
nodetemp:=Node;
qry_ordtree.Close;
qryorders.SQL.Clear;
qry_orders.SQL.Add('select * from orders where customerid='''+
inttostr(customerid)+'''order by orderdate');
qry_orders.Open;
if (Not qry_orders.IsEmpty) Then
while Not qryorders.Eof do
begin
new(RecPtr);
RecPtr.ID:=qry_ordTree.fieldbyname('customerid').AsString;
RecPtr.IsExpanded:='false';
nodetemp:=treeview1.Items.AddChildObjectFirst(Node,
trim(qry_ordTree.fieldbyname('customer_name').AsString),RecPtr);
nodetemp.ImageIndex:=0;
nodetemp.SelectedIndex:=1;
nodetemp.StateIndex:=0;
end;
result:=nodetemp;
end;

procedure Tfm_mainxt.FormCreate(Sender: TObject);
var
MyNode,nodetemp2:TTreeNode;
RecPtr:PMyRec;
begin
MyNode:=nil;
MyNode:=BuildTree(MyNode,0);//创建 根节点
qry_orders.Close;
new(RecPtr);
RecPtr:=MyNode.Data;
RecPtr.IsExpanded:='true';
with datamodule2.qrytemp do
begin
close;
sql.Clear;
sql.Add('select * from customer order by customerid);
prepare;
open;
first;
while not eof do
begin
new(RecPtr);
RecPtr.ID:=FieldByname('customerid').AsString;
RecPtr.IsExpanded:='true';
nodetemp2:=TreeView1.Items.AddChildObject(MyNode,
fieldbyname('customerid').AsString+'@+fieldbyname('customername'),RecPtr);
nodetemp2.ImageIndex:=2;
nodetemp2.SelectedIndex:=1;
nodetemp2.StateIndex:=2;
next;
end;
if not(nodetemp2=nil) then
nodetemp2.MakeVisible;
end;
datamodule2.qrytemp.Close;
end;
end;
我对TTreeview控件的用法不太熟悉,查了一些参考书,发现基本上没有介绍该控件的
知识,不知那位有该部分的文章,请发过来看看,to wdsu@htc.net.cn 谢谢!
 
谢谢book523:
请问:
tblpower,tblmodul的表结构或者字段是什么,我看不懂拉。
WhereSql:=' and id in (select modulid from tblpower where No='''+userid+''')'
是什么意思?
请book523给我帮助,谢谢!wdsu@htc.net.cn
 
能看看你所有的源代码吗?
 
谢谢,book523的回答,参考你提供的历程,我的问题已经解决代码如下:
qryorders.sql.Add('select * from orders where customerid='''+qrytemp.FieldByName('customerid').AsString+'''order by orderdate''')
此处去掉最后order by orderdate的两引号''即可。

procedure Tfm_mainxt.initTreeView(TreeView1:TTreeview);
var
TreeNode1,TreeNode2:TTreeNode;
begin
TreeView1.Items.Clear;
with datamodule2 do
begin
qrytemp.close;
qrytemp.sql.Clear;
qrytemp.sql.Add('select * from customer order by customerid');
qrytemp.open;
if qrytemp.IsEmpty then
begin
MessageDlg('你的客户表中还没有内容,请先输入客户!', mtWarning,
[mbOK], 0);
exit;
end;
qrytemp.first;
while not qrytemp.eof do
begin
qryorders.Close;
qryorders.sql.Clear;
qryorders.sql.Add('select * from orders where customerid='''+qrytemp.FieldByName('customerid').AsString+'''order by orderdate');
qryorders.open;
if qryorders.IsEmpty then
begin
TreeNode1:=treeview1.Items.add(nil,qrytemp.fieldbyname('customerid').AsString+'@'+qrytemp.fieldbyname('customer_name').AsString);
qrytemp.Next;
continue;
end;
TreeNode1:=treeview1.Items.add(nil,qrytemp.fieldbyname('customerid').AsString+'@'+qrytemp.fieldbyname('customer_name').AsString);
qryorders.First;
while not qryorders.Eof do
begin
TreeNode2:=treeview1.Items.AddChild(TreeNode1,qryorders.fieldbyname('orderdate').AsString);
qryorders.Next;
end; // while not qryorders.eof...end
qrytemp.Next;
end; // while not qrytemp.eof do..end
end;// with datamodule2 do...end

end;

谢谢,欢迎大家提供宝贵意见来改进。wdsu@htc.net.cn
 
首先定义一个类 type TDatabase_1 = Class
FID:Intger;
:
:
end;
然后再向TreeView内加时用AddChildObject能记录一个指针;
 
Dear jrzbj:
哈哈,我笨在那里呀,不妨给我的程序提点意见拉啊。
wdsu@htc.net.cn

 
大家好,现在我的数型结构已经如下所示:
张三->2001年3月25日
->2001年4月26日
->2001年5月27日
->2002年3月25日
->2002年4月26日
->2002年5月27日
主要代码为:

TreeNode1:=treeview1.Items.add(nil,qrytemp.fieldbyname('customerid').AsString+'@'+qrytemp.fieldbyname('customer_name').AsString);
qryorders.First;
while not qryorders.Eof do
begin
TreeNode2:=treeview1.Items.AddChild(TreeNode1,qryorders.fieldbyname('orderdate').AsString);
qryorders.Next;
end; // while not qryorders.eof...end
详细的请见上面我写的"来自:wdsu, 时间:2002-5-26 12:53:00, ID:1124880"

现在我想把定单日期,如200年5月26日进一步设成数型结构,形式如下:
张三—>2001
->->4月
->->->25日
->->->26日
->->->27日
->->5月
->->->25日
->->->26日
->->->27日
->2002年
->->4月
->->->25日
->->->26日
->->->27日
->->5月
->->->25日
->->->26日
->->->27日
现在我把定单日期qryorders.fieldbyname('orderdate').asdate用
decodedate(orderdate,year,month,day)拆开年,月,日做成数型结构。
我的初步代码如下:
var y,y1,m,m1,d:string;
datestr:string;
year,month,day:word;
p_orderdate:datetime;
TreeNode1,TreeNode2,TreeNode3,TreeNode4:TTreeNode;
while not qryorders.Eof do
begin
P_orderdate:=qryorders.fieldbyname('orderdate').AsDateTime;
Decodedate(P_orderdate,year,month,day);
y:=inttostr(year);
m:=inttostr(month);
d:=inttostr(day);
TreeNode2:=treeview1.Items.AddChild(TreeNode1,y);
y1:=y;
TreeNode3:=treeview1.Items.AddChild(TreeNode2,m);
m1=m;
Treenode4:=treeview1.Items.AddChildFirst(treenode3,d);
qryorders.Next;
end; // while not qryorders.eof...end
qrytemp.Next;
后面的代码我不知怎么写,请哪为高手帮忙,提供点思路,或提供类似的代码,谢谢!
wdsu@htc.net.cn
 
上次给你回复,你说的出错,可能那是因为你query查询的客户对应的定单表记录集为空,
先用 if query.isempty then 判断一下就行了。
你说的新问提,把年月日分开来,这先要看你所用的是什么数据库,支持某些日期函数不。
先用一个query1.sql.text:='select distinct yearof(orderdate) as yy from orders
where (客户=客户) order by orderdate';然后象我上面给你示范 的一样,对query1
循环读取所有年份,对每一个‘年份’,用一个query2如query1一样查询该年份里有记录
的‘月份’,再对每一个月份用query3如前一样查询该年该月有记录的‘日’,对每一个
日就可以对该年该月该日查询定单记录了。query2的sql 语句提示一下:'select distinct
monthof(orderdate) as mm from orders where yearof(orderdate)=:yy and
(客户=客户)';parambyname('yy'):=yy;(yy就是对应节点的父亲的年份。query3的语句
也很容易写:'select distinct dayof(orderdate) as dd from orders where (客户=客
户) and yearof(orderdate)=:yy and monthof(orderdate)=:mm',对yy和mm赋值;(客
户=客户)就是定单的客户编号。
 
刚好我这几天也是在用treeview,我是写租书管理系统,对书库的所有书进行分类,
treeview的结构如下:
**书屋
01 武侠类
010001 金庸
0100010001 啸傲江湖
0100010002 路定级
0100010003 身掉下率
……
010002 古龙
0100020001 楚流香传
……
010003
010004
……
02 言情类
020001 穷摇
020002 #%*& $^
……
03 成人类
030001 璩美风^O^
……
……
好象delphi程序员不太喜欢用treeview,倒是powerbuilder程序员很喜欢用treeview,很多pb
的书对treeview控件介绍的很详细。

 
后退
顶部