按樹型顯示BOM的結構


在制造企業中,生產的每一個產品都由一道或多道工序組成,在組成成品之前,每一道工序經由物料--物料組成半成品,或物料--半成品組成新的半成品,亦或由半成品--半成品組成新的半成品。復雜的成品經由多道工序最終形成。在這一過程中,某一物料或半成品可能出現在多道工序這中。而每一道工序又涉及損耗(包括調機損耗和加工損耗等)等一系列問題都是需要在實際的生產系統中考慮到。在從事ERP與MES開發多年,目前系統設計的結構已滿足了這些方方面的要求。今天,趁着閑暇的時候記錄一下,一來是自己對整個結構做一個回顧,另一方面也希望給新人一丁點啟發。

首先,我們的BOM結構主要分為三層。其基本表是 Bom, BomDTL, BomDTL2

其各表的關鍵字如下圖:

 

 

Ancestor --產品型號(當前工序完成后的型號),Ver--版本

SpecNum -- 生產規格

ProVer   -- 當前工序所需的型號(物料或半成品), ProVer 版本

 

其對應在畫面中的體現,如下圖。

而又把其中的半成品,第三層中的BA***, 放到產品型號中去查詢。得出下圖

如此往復,直到達到最初的一道工序為止。

而做為技術或生產來說,做錄入完資料之后,其是非常需要一個報表或者圖形來直觀反映所輸的內容是否正確。

打印以上設計卡,得出相應的報表結構。

 

 

看最后的兩道工序,與之前畫面中的匹配。

現在我們要實現以上層層嵌套的的樹狀結構。貼出效果圖和關鍵代碼。

下圖中紅色的方框的數據是在實際的生產過程中,同一個型號有可能多個顏色。而這個顏色的這部分BOM是可由系統自動產生。

下面是關鍵的代碼。

 private void btnSearch_Click(object sender, EventArgs e)
        {
            if (txtDrawFrom.Text == "" && txtDrawTo.Text == "")
            {
                MessageBox.Show("請輸入設計卡查詢條件", "信息提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }
            string strSQL = String.Format("exec frmBomMap_List '{0}','{1}'", txtDrawFrom.Text, txtDrawTo.Text);

            this.treeView1.Nodes.Clear();//先清空
            this.listView1.Items.Clear();//先清空
            try
            {
                datasource = W1.DS(strSQL, "Sys");
                TreeNode node = new TreeNode() { Text = "Root", ToolTipText = "Root" };
                this.treeView1.Nodes.Add(node);
                node.ImageIndex = 2;
                node.SelectedImageIndex = 2;

                C_BomOP.CreateTreeViewRecursive(treeView1.Nodes[0].Nodes, datasource.Tables[0], "Root", "Root", -1);//第一個節點下

                //treeView1不展開,listView清空數據
                this.treeView1.ExpandAll();
                this.listView1.Items.Clear();
            }
            catch(Exception ex)
            {
               // throw new Exception(ex.Message);
               //  MessageBox.Show( ex.Message, "信息提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                
            }
        }

 public void CreateTreeViewRecursive(TreeNodeCollection nodes, DataTable dataSourse, string parentId, string topAncestor,int level)
        {
            string topmodel = "";
            string filter = string.Format("Ancestor='{0}'and ( Ancestor='Root' or TOPLEVEL='{1}') and BOMLEVEL = {2}", parentId, topAncestor, level);   //  AND ( ProType='03' or ProType='02')
            //查詢子節點
            DataRow[] drArr = dataSourse.Select(filter);
            level++; // 需放到外層來。不然並行的一道工序就會導致相加了。以致結果不正確,這里要特別留意一下
            TreeNode node;
            foreach (DataRow dr in drArr)
            {
                node = new TreeNode();
                nodes.Add(node);
                node.Text = (string)dr["ProNum"];
                node.ToolTipText = String.Format("{0}\n{1}", (string)dr["TOPLEVEL"], level);
                topmodel = (string)dr["TOPLEVEL"];                
                //遞歸創建子節點
                CreateTreeViewRecursive(node.Nodes, dataSourse, dr["ProNum"].ToString(),topmodel,level);
            }
        }
View Code

 

ALTER PROCEDURE [dbo].[frmBomMap_List]    
@sknum1 VARCHAR(50),    
@sknum2 VARCHAR(50)    
    
AS    
CREATE TABLE #TEMP      
(TOPLEVEL VARCHAR(50)  COLLATE Chinese_PRC_BIN,      
Ancestor VARCHAR(50) COLLATE Chinese_PRC_BIN,    
ProNum VARCHAR(50)  COLLATE Chinese_PRC_BIN,  
[SETS] INT,      
QTY FLOAT,      
BOMLEVEL INT)      
    
SELECT TOPLEVEL=Ancestor,Ancestor='Root',ProNum=Ancestor,Ver INTO #t1  FROM dbo.Bom     
WHERE DrawNum between @sknum1 AND @sknum2    
AND IsEffect=1 --AND IsOrigin=1   -- 非原型也要取
 
IF (SELECT COUNT(1) FROM #t1) >200
BEGIN
     RAISERROR('數據過多,請縮小設計卡的范圍',11,-1)    
     RETURN    
END

     
SELECT * INTO #t2 FROM #t1    
      
declare @ancestor varchar(50),@version VARCHAR(5)      
while (select count(*) from #t1)>0      
BEGIN      
select TOP 1 @ancestor=TOPLEVEL,@version=Ver FROM #t1      
delete #t1 where TOPLEVEL=@ancestor AND Ver=@version      
      
 ;WITH BOMList(TOPLEVEL, Ancestor, ProNum,[SETS], QTY,BOMLEVEL) AS         
 (        
  SELECT TOPLEVEL=Ancestor, Ancestor,ProNum,Sets, Qty AS QTY, 0 AS BOMLEVEL    -- Sets*Qty AS QTY    
  FROM dbo.BomDTL2        
  WHERE Ancestor=@ancestor AND Ver=@version        
  UNION ALL        
  SELECT TOPLEVEL, B2.Ancestor, B2.ProNum, B2.Sets,B2.Qty AS QTY,BOMLEVEL + 1        
  FROM BomDTL2 B2, BOMList BB        
  WHERE B2.Ancestor=BB.ProNum       
 )       
 INSERT #TEMP      
 SELECT TOPLEVEL, Ancestor, ProNum,[SETS],QTY,BOMLEVEL         
 FROM BOMList        
END      
     
--delete #TEMP where ProNum in (select Ancestor from #TEMP)     
    
    
SELECT DISTINCT #TEMP.*,p.ProType FROM #TEMP,dbo.Product p     
WHERE #TEMP.ProNum = p.ProNum     
UNION ALL  SELECT TOPLEVEL,Ancestor,ProNum,1,1,-1,'02' FROM #t2  -- 02是成品    
    
ORDER BY  TOPLEVEL ASC,BOMLEVEL ASC,ProType DESC,ProNum ASC    
    
DROP TABLE #t1,#t2,#TEMP  
View Code

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM