DELPHI用樹形實現BOM的三層結構!(20分)

  • 主题发起人 主题发起人 ye802808
  • 开始时间 开始时间
Y

ye802808

Unregistered / Unconfirmed
GUEST, unregistred user!
產品
|
---------半成品
|
_________________原料


產品在一個表內,半成品在一個表內,原料在一個表內,現在有三個表,相互用ID關聯,

實現這樣的樹結構,原代碼的編寫的搞了三天了,還是寫不出來,在大富瘟里查找資料,

也沒有相同的貼子,有誰能提供一點代碼給我,謝了

分散盡!
 
真不明白,这么简单的东西都要提问,不过分数比较合适。
结构都清楚了,还要什么代码,查询->生成树节点就是了。

不过我不认同这种所谓的三层BOM。如果是MRP,产品/半成品/原料应该放到一个表中,BOM资料放在另一个表中。
 
bom几层都没有关系,它的复杂程度应该不受你程序的限制。只是说层次越多管理它就越复杂。技术上看你采用什么表现方式,如果采用树的话,就是一个构造树的简单问题
 
三个表不要关联吧,我也作过,好象不要的
 
引用:

savetime:
---------------------------------------------------------------------

真不明白,这么简单的东西都要提问,不过分数比较合适。
结构都清楚了,还要什么代码,查询->生成树节点就是了。

不过我不认同这种所谓的三层BOM。如果是MRP,产品/半成品/原料应该放到一个表中,BOM资料放在另一个表中。
-------------------------------------------------------------------------
正所謂學海無涯,或許,你走在我前面,我現在也正在追趕!

大家能正確面對自己的不足,才是重要的!

你有好的經驗,可給大家不斷參考!

對于這個問題,我在DELPHI里真不知道怎樣實現的,但是我以前在FOX里做得相當精美的,現在我就是由于有一種FOX的指導思想,才寫不出代碼,你有好的見議,嗎,能提代點代碼給我嗎?
 
嘿嘿,我是偶尔喜欢吹吹牛,不过请不要介意。我绝没有评价谁的技术好或差的能力。
你的问题并没有说清楚,只是说写不出来,到底是 Delphi、SQL 或 设计结构上的困难
没有提到,所以我就随便说说。
我用过一家美国公司/一家台湾公司/一家国内公司的MRP系统,没有用这种方式组织
BOM。我自己写了个小 MRP,方法如下:
建立 物料档案表 (主要字段是物料编码,物料属性[成品/半成品/原料/虚拟件等])
建立 BOM 表
BOM表的结构是 父件编码/子件编码/需求数量/损耗率等
你看了来了吗,在BOM中子件也可以作父件,所以用一个递归算法就能实现BOM展开,
这样的 BOM 没有层数限制,当然你也可以用代码限制层数,需要注意的是不要出现
循环的 BOM,那就成了无限循环递归调用。

我不认同你提的三层 BOM 原因是:
1. 我现在 BOM 组织方法很方便,结构清晰。
2. 如果 产品 是由 半成品 和 原料 组成的,而不是只由 半成品 组成,你上面的结构
就不能完成任务,或者很难完成任务。
3. 如果 半成品 或 原料 要转销售呢?

可能还有其他问题,我只是大概说说,毕竟各人的经验不同,我只能提点建议。
 
我虛心接受你的意見!

當然,大家能相互交流,是最完美的!

沒有一個人是十全十美的!

你剛才對BOM的講述,使我對BOM又有一個新的認識,在此表示感謝!

可以,這樣的實現方法,和我當初提出來的實現方法,對于在DELPHI里用代碼來編寫,方式是差不多的,現在我最主要是想知道:

究竟,我在DELPHI里怎樣用遞歸來實現三層或更多層的樹形!

主要是代碼我不太會寫,我現在寫的一代碼,可實現這了我的要求,貼出來給你看看,請不要見笑!

procedure TForm1.Button1Click(Sender: TObject);
var
i,j,k,p,num,level:integer;
rootnodes:array[0..10] of TTreenode;
parentnode:Ttreenode;
sdeptid:string;
currentcode,tempcode:TTreenode;
begin
tree.Items.Clear;
num:=0;
with adotareaa do
begin
close;
sql.Clear;
sql.Add('select * from tareaa');
prepared;
open;

for i:=0 to adotareaa.RecordCount-1 do begin
sdeptid:=adotareaa.fieldbyname('fname').AsString;
p:=adotareaa.fieldbyname('fid').AsInteger;
rootnodes[0]:=tree.Items.Add(tree.Selected,(adotareaa.fieldbyname('fname').AsString)); //此處新增加根節點,也就是一級節點,(或說產品)
currentcode:=tree.Items.Item[num];
currentcode.SelectedIndex:=0;
with adotareab do
begin
close;
sql.Clear;
sql.Add('select * from tareab where parentid='+inttostr(p)); //從此處選出屬于一級節點以下的子節點,添加到一級節點下
prepared;
open;
while not eof do begin
rootnodes[1]:=tree.Items.AddChild(currentcode,adotareab.fieldbyname('shiname').AsString); //在此處添加,但是不能實現我要的效果,
next;
end;
end;
parentnode:=tree.Selected;
num:=num+1;
adotareaa.Next;
end;
end;
end;



現在我有一個問題不清楚,就是添加子節點時,

addchild(node:TTreenode;const s:string ):ttreenode;

這個里面的 node 是不是指上一級的根節點,比喻上一級的根點很多,如下

------5028游戲機
|
------6032手表
|
------3524計算機

現在我每次添加只能添加到"5028游戲機"下,而屬于"6032手表"和"3524計算機"下的二級節點也都添加到了"5028游戲機"下,不能添加到屬于它的上一級節點也.

但是我在
with adotareab do
begin
close;
sql.Clear;
sql.Add('select * from tareab where parentid='+inttostr(p));
prepared;
open;
while not eof do begin
rootnodes[1]:=tree.Items.AddChild(currentcode,adotareab.fieldbyname('shiname').AsString);
next;
end;
這里用SQL查出來的是屬于它的上一級下的東東,

可能就是錯在

rootnodes[1]:=tree.Items.AddChild(currentcode,adotareab.fieldbyname('shiname').AsString); //增加子節點點

這句話上!
 
一般不用 for 循环遍历数据集,因为在Client/Server 数据库设计中数据集可能是分批下载的,也就是说 RecordCount 的值可能不是全部的记录。
可以用 while 循环,还可以少定义一个变量。
ADODataSet.Open;
while not ADODataSet.Eof do
begin
// 在此处理数据;

ADODataSet.Next;
end;
当然如果是 Local Database 就无所谓了。

还有 Prepare 语句,我很少用 Prepare,好像 DataSet 一般都会自动调用,印象中手工调用 Prepare 后还要手工调用 Unprepare。我只是凭记忆,说错了请指正。(我的数据库基础不好 :)

这句看不懂: rootnodes:array[0..10] of TTreenode;

你的这种BOM结构不需要递归,只需要三层循环就可以解决了。不过我真的不知道你的半成品要用到多个成品中是否会需要两份半成品的物料清单。
很抱歉我不太能读懂你的代码,下面我简单地写了一段示例,参考一下。

var
ProdDataSet, SemiDataSet, MatDataSet: TADODataSet;
CurrNode, CurrSemiNode: TTreeNode;
begin
ProdDataSet.Open;
while not ProdDataSet.Eof do
begin
CurrNode := Tree.AddChild(nil, ProdDataSet.FieldByName('ProdName').AsString);
CurrSemiNode := CurrNode;

? Reset SemiDataSet's SQL property to fit with ProdID
SemiDataSet.Open;
while not SemiDataSet.Eof do
begin
CurrSemiNode := Tree.AddChild(CurrNode, SemiDataSet.FieldByName('SemiName').AsString);
? Reset MatDataSet's SQL property to fit with SemiID
MatDataSet.Open;
while not MatDataSet.Eof do begin
Tree.AddChild(CurrSemiNode, MatDataSet.FieldByName('MatName').AsString);
MatDataSet.Next;
end;
SemiDataSet.Next;
end;
end;
end;
 
这个问题很简单
 
华旗的产品-爱国者MP3很烂,才用20天,耳机就脱胶,还说是外伤,不给任何维修等,哪个龟儿子再买爱国者MP3,甚至华旗的东西

如果不属实,天洙地灭
 
to :
savetime兄!

在你的提醒下,我總算對這個問題有了一定的認識,非常謝謝你的指導!不過,對于BOM,我還有一些不明白,那你要是將BOM放在一個表內,例如:
字段1:product //產品,
字段2:parent1 //相當于產品的一個ID,也被當成父,
字段3:child1 //子,構與父的一個成員,
.
.
.
.
.

那其間怎樣分配在child1中各子節點的層次?

我在大富瘟上找到一些有關這方面的資料,用'0000000000'表示一類,
'0010000000'表示二類,'0010100000'表示二類下的一類,

這樣好像不好懂!
你有什么好的見議嗎?
 
举个例子: BOM 表的结构
父件编码 子件编码
A1 C1
A1 C2
A1 C3
C1 C4
C1 C5
那么 A1 展开以后就是 C2/C3/C4/C5,C1已被展开为C4/C5
如果 C4 也存在于 父件编码,C4也会被展开。
注意 BOM 表只是为了表示 物料A1 的组成结构,并不包含A1的其他信息
A1的其他信息要另建一基本物料表保存。
 
哎呀,大家讲一下TTreeview的常用方法和属性的使用不就行啦!
 
>>現在我有一個問題不清楚,就是添加子節點時,

addchild(node:TTreenode;const s:string ):ttreenode;

這個里面的 node 是不是指上一級的根節點,比喻上一級的根點很多,如下

------5028游戲機
|
------6032手表
|
------3524計算機

現在我每次添加只能添加到"5028游戲機"下,而屬于"6032手表"和"3524計算機"下的二級節點也都添加到了"5028游戲機"下,不能添加到屬于它的上一級節點也.
------------------------------------------------------------------------------
看來你對建樹的遞歸調用沒理解。下面是偽代碼
procedure createtree(pnode=nil,nodename)
begin
query:= tquery.create(self);//務必要動態創建
query.sql.text='select * from table where parent='''+nodename+'''';//找子
if query.recordcount > 0 then//有子
while not query.eof do
begin
newnode := addchild(pnode,query.fieldbyname('name').asstring);//把子加到樹中。
createtree(newnode,query.fieldbyname('id').asstring);//遞歸調用。對子執行相同的操作(對子建樹)。
query.next;
end;

end;

隨手寫的。提供一個思路。
如果在編碼上下功夫是可以不用遞歸的。
 
举个例子: BOM 表的结构
父件编码 子件编码
A1 C1
A1 C2
A1 C3
C1 C4
C1 C5
那么 A1 展开以后就是 C2/C3/C4/C5,C1已被展开为C4/C5
如果 C4 也存在于 父件编码,C4也会被展开。
注意 BOM 表只是为了表示 物料A1 的组成结构,并不包含A1的其他信息
A1的其他信息要另建一基本物料表保存。

-----------------
父件编码 子件编码 物料編碼
A1 C1
A1 C2
A1 C3
C1 C4 w1
C1 C5 w2


物料編碼這樣定?
 
不是,父件编码和子件编码都属于物料编码。
物料编码单独建表。BOM 只存储物料之间的包含关系。
 
to savetime
那物料编码与BOM如何關聯?
請舉一個例子!
 
当然是将物料编码直接与BOM的父件编码和子件编码直接设置一对多关系了。
看来你还没有明白为什么要物料编码表与BOM表。
 
接受答案了.
 
后退
顶部