• 按树型显示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}
    {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
  • 相关阅读:
    手机Web开发框架
    HTML5内置邮箱验证属性
    HTML4 和 HTML5 的10个关键区别
    wampserver 2.5 首页链接问题
    sublime text 2 配置php调试环境
    Github在Windows下使用流程介绍
    PHP中echo()、print()、print_r()、var_dump()的区别
    Web前端开发神器 Intellij IDEA
    【转】Java内存管理
    Android学习记录
  • 原文地址:https://www.cnblogs.com/Geton/p/5442979.html
Copyright © 2020-2023  润新知