Imports System.Text

Public Class form_BomManage
    Dim m_Table As New System.Data.DataTable
    Dim m_InitOver As Boolean = False
    Dim m_PartNumber As New CPartNumber

    Dim m_BomTemplateName As String = "模板"
    Dim m_CurrentBomPN As String = ""
    Dim m_BomPath As New ArrayList

    Public Enum COLS
        序号
        工艺流程
        料号PN
        物料名称
        规格描述
        单位
        用量
        使用位置
        父料号
        图片
        备注
        单价          'V2.4
        单位总价      'V2.4
        max
    End Enum

    Public Shared m_COLS_NAME(,) As String = {
        {"序号", "0"},
        {"工艺流程", "1"},
        {"料号PN", "1"},
        {"物料名称", "0"},
        {"规格描述", "0"},
        {"单位", "0"},
        {"用量", "1"},
        {"使用位置", "1"},
        {"父料号", "1"},
        {"图片", "0"},
        {"备注", "1"},
        {"单价", "1"},
        {"单位总价", "1"}
    }

    Public Shared m_ProcessRoutingTable() As String = {
        "Bonding",
        "SMT",
        "DIP",
        "成品组装",
        "成品包装",
        "线外加工",
        "其它-1",
        "其它-2",
        "其它-3",
        "其它-4",
        "其它-5"
        }

    Private Sub FillGridHeaderByDataTable()
        Grid1.NewFile()

        Grid1.AllowUserSort = False
        Grid1.DisplayFocusRect = False
        Grid1.ExtendLastCol = True
        Grid1.DisplayRowArrow = True
        Grid1.BoldFixedCell = False
        Grid1.SortIndicatorStyle = FlexCell.SortIndicatorStyleEnum.Light3D

        Grid1.Cols = COLS.max
        For col As Integer = 0 To COLS.max - 1
            Grid1.Cell(0, col).Text = m_COLS_NAME(col, 0)
        Next

        Grid1.Column(COLS.父料号).CellType = FlexCell.CellTypeEnum.CheckBox
        Grid1.Column(COLS.工艺流程).CellType = FlexCell.CellTypeEnum.ComboBox
        With Grid1.ComboBox(COLS.工艺流程)
            .DataSource = m_ProcessRoutingTable
            .Locked = False
            .AutoComplete = True
        End With

        '调整宽度
        Grid1.Column(COLS.序号).Width = My.Settings.FORM_BOM_COL_WIDTH_序号
        Grid1.Column(COLS.工艺流程).Width = My.Settings.FORM_BOM_COL_WIDTH_工艺流程
        Grid1.Column(COLS.料号PN).Width = My.Settings.FORM_BOM_COL_WIDTH_料号PN
        Grid1.Column(COLS.物料名称).Width = My.Settings.FORM_BOM_COL_WIDTH_物料名称
        Grid1.Column(COLS.规格描述).Width = My.Settings.FORM_BOM_COL_WIDTH_规格描述
        Grid1.Column(COLS.单位).Width = My.Settings.FORM_BOM_COL_WIDTH_单位
        Grid1.Column(COLS.用量).Width = My.Settings.FORM_BOM_COL_WIDTH_用量
        Grid1.Column(COLS.使用位置).Width = My.Settings.FORM_BOM_COL_WIDTH_使用位置
        Grid1.Column(COLS.父料号).Width = My.Settings.FORM_BOM_COL_WIDTH_父料号
        Grid1.Column(COLS.图片).Width = My.Settings.FORM_BOM_COL_WIDTH_图片
        Grid1.Column(COLS.备注).Width = My.Settings.FORM_BOM_COL_WIDTH_备注
        Me.Height = My.Settings.FORM_BOM_HEIGHT
        Me.Width = My.Settings.FORM_BOM_WIDTH

        ''Dim row As Integer
        'Dim col As Integer
        'If m_Table.Columns.Count > 0 Then
        '    Grid1.Cols = m_Table.Columns.Count
        '    For col = 0 To m_Table.Columns.Count - 1
        '        If m_Table.Columns(col).DataType.Name = "Boolean" Then
        '            Grid1.Column(col).CellType = FlexCell.CellTypeEnum.CheckBox
        '        End If
        '        Grid1.Cell(0, col).Text = m_Table.Columns(col).ColumnName
        '    Next
        'End If

        'For i As Integer = 1 To Grid1.Rows - 1
        '    Grid1.Cell(i, 0).Text = i
        'Next

        Grid1.AllowUserSort = True
        Grid1.Locked = False
        Grid1.Column(COLS.序号).Locked = True

        Grid1.Rows = 500

        Application.DoEvents()
    End Sub

    Private Sub FillGridByDataTable()
        Dim row As Integer
        Dim col As Integer

        'Grid1.AutoRedraw = False
        If Grid1.Rows < m_Table.Rows.Count Then
            Grid1.Rows = m_Table.Rows.Count + 100
        End If

        Dim insertRow As Integer = 0

        If m_Table.Rows.Count > 0 Then
            For row = 0 To m_Table.Rows.Count - 1
                insertRow = row + 1

                Grid1.Cell(insertRow, COLS.序号).Text = insertRow
                'Dim queryCol As Integer = 1
                Dim queryCol As Integer = 0
                For col = 0 To COLS.max - 1
                    If m_COLS_NAME(col, 1) = "1" Then
                        Try
                            Grid1.Cell(insertRow, col).Text = m_Table.Rows.Item(row).Item(queryCol)
                        Catch ex As Exception
                            Grid1.Cell(insertRow, col).Text = ""
                        End Try

                        queryCol += 1
                    End If
                Next
            Next
        End If

        'Grid1.AutoRedraw = True
        'Grid1.Refresh()
    End Sub

    Private Function QueryBom(ByVal BomName As String, ByRef dataTable As Data.DataTable) As Boolean
        Dim strSelect As String = "SELECT * FROM `" & "bom_" & BomName & "`"

        '查询入库数量
        Dim result As Boolean = False
        Dim strSQL As String = strSelect
        dataTable.Rows.Clear()
        dataTable.Columns.Clear()
        If SQL_Query(COL_RIGHTS.BOM管理, strSQL, dataTable) = True Then
            result = True
        End If

        Return result
    End Function

    Private Function CheckBomExist(ByVal bomName As String, ByRef isExist As Boolean) As Boolean
        Dim strSQL As String = "CHECK TABLE `" & "bom_" & bomName & "`" 'CHECK TABLE `BOM_U01-ATMEGA328P-TQFP32`
        Dim result As Boolean = False
        m_Table.Rows.Clear()
        m_Table.Columns.Clear()
        isExist = False
        If SQL_Query(COL_RIGHTS.BOM管理, strSQL, m_Table) = True Then
            If m_Table.Rows.Count > 0 Then
                If m_Table.Rows(0).Item(3) = "OK" Then
                    isExist = True
                End If
            End If
            result = True
        End If

        Return result
    End Function

    Private Function DropBom(ByVal bomName As String) As Boolean
        Dim strSQL As String = "DROP TABLE IF EXISTS `" & "bom_" & bomName & "`"
        Dim result As Boolean = False
        If SQL_ExeCommand(COL_RIGHTS.BOM管理, strSQL) = True Then
            result = True
        End If

        Return result
    End Function

    Private Function CreateBom(ByVal bomName As String) As Boolean
        Dim strSQL As String = "CREATE TABLE IF NOT EXISTS `" & "bom_" & bomName & "` Like `" & "bom_" & m_BomTemplateName & "`"
        Dim result As Boolean = False
        If SQL_ExeCommand(COL_RIGHTS.BOM管理, strSQL) = True Then
            result = True
        End If

        Return result
    End Function

    Private Function CreateContextBom(ByVal bomName As String) As Boolean
        Dim strSQL As String = "CREATE TABLE IF NOT EXISTS `" & "bom_" & bomName & "` Like `" & "bom_" & m_BomTemplateName & "_context`"
        Dim result As Boolean = False
        If SQL_ExeCommand(COL_RIGHTS.BOM管理, strSQL) = True Then
            result = True
        End If

        Return result
    End Function

    Private Function RenameBom(ByVal oldName As String, ByVal newName As String) As Boolean
        Dim strSQL As String = "ALTER TABLE `" & "bom_" & oldName & "`" & " RENAME TO `" & "bom_" & newName & "`"
        Dim result As Boolean = False
        If SQL_ExeCommand(COL_RIGHTS.BOM管理, strSQL) = True Then
            result = True
        End If

        Return result
    End Function

    Private Sub btNew_Click(sender As Object, e As EventArgs)
        Dim inputDlg As New dlg_Input
        inputDlg.Text = "请输入新建的料号"
        inputDlg.tb_Input.MaxLength = 32
        inputDlg.tb_Input.CharacterCasing = CharacterCasing.Upper
        If inputDlg.ShowDialog() <> Windows.Forms.DialogResult.OK Then Return

        m_CurrentBomPN = ""
        If inputDlg.tb_Input.Text.Length = 0 Then
            MsgBox("输入料号不能为空")
            Return
        End If

        Dim inputBomSn As String = inputDlg.tb_Input.Text

        '检查输入料号是否有效
        Dim isExist As Boolean = False
        If m_PartNumber.CheckPartNumber(inputBomSn, isExist) = ERROR_CODE.SUCCESS Then
            If isExist = False Then
                MsgBox("输入料号不存在!")
                Return
            End If
        Else
            MsgBox("无法查询输入料号，请检查网络连接!")
            Return
        End If

        '检测输入料号的料表是否已经存在
        If CheckBomExist(inputBomSn, isExist) = True Then
            If isExist = True Then
                MsgBox("输入料号料表已经存在")
                Return
            End If
        Else
            MsgBox("无法查询输入料号对应的料表是否存在，请检查网络连接!")
            Return
        End If

        m_CurrentBomPN = inputBomSn
        lbl_CurrentPN.Text = "当前料表料号:" & m_CurrentBomPN

        '查询料表模板
        If QueryBom(m_BomTemplateName, m_Table) = True Then
            FillGridHeaderByDataTable()
        End If
    End Sub

    'Private Sub Grid1_LeaveRow(Sender As Object, e As FlexCell.Grid.LeaveRowEventArgs) Handles Grid1.LeaveRow
    '    If e.Row > 0 Then
    '        If Grid1.Cell(e.Row, COLS.料号PN).Text.Length > 0 Then
    '            Grid1.Cell(e.Row, COLS.序号).Text = e.Row
    '        End If
    '    End If
    'End Sub


    Private Sub btSave_Click(sender As Object, e As EventArgs) Handles btSave.Click
        If m_CurrentBomPN.Length = 0 Then
            MsgBox("未指定当前BOM料号!")
            Return
        End If

        '检查输入料号是否有效
        Dim isExist As Boolean = False
        If m_PartNumber.CheckPartNumber(m_CurrentBomPN, isExist) = ERROR_CODE.SUCCESS Then
            If isExist = False Then
                MsgBox("输入料号不存在!")
                Return
            End If
        Else
            MsgBox("无法查询输入料号，请检查网络连接!")
            Return
        End If

        '检测内容中的PN字段有效性
        If CheckPNValid() = False Then
            MsgBox("输入信息存在错误，不能进行保存!")
            Return
        End If

        '创建料号表
        If SaveBom(m_CurrentBomPN) = False Then
            MsgBox("保存料表失败")
            Return
        End If

        MsgBox("保存料表:" & m_CurrentBomPN & "成功")
    End Sub


    Private Function CheckPNValid() As Boolean
        Dim row As Integer
        '清除背景颜色
        For row = 1 To Grid1.Rows - 1
            Grid1.Cell(row, COLS.料号PN).BackColor = Color.White
            Grid1.Cell(row, COLS.用量).BackColor = Color.White
            Grid1.Cell(row, COLS.序号).Text = ""
        Next


        '检测料表输入数据是否有效
        Dim strPN As String
        Dim isExist As Boolean = False
        Dim checkResult As Boolean = True
        Dim m_SN As Integer = 1
        Dim m_Number As Long
        For row = 1 To Grid1.Rows - 1
            strPN = Grid1.Cell(row, COLS.料号PN).Text
            If strPN.Length > 0 Then
                '检测料号有效性
                If m_PartNumber.CheckPartNumber(strPN, isExist) = ERROR_CODE.SUCCESS Then
                    If isExist = True Then
                        Grid1.Cell(row, COLS.料号PN).BackColor = Color.Green
                    Else
                        checkResult = False
                        Grid1.Cell(row, COLS.料号PN).BackColor = Color.Red
                    End If
                Else
                    checkResult = False
                    Grid1.Cell(row, COLS.料号PN).BackColor = Color.Red
                End If

                '检测“用量”列，是否为数据
                Try
                    m_Number = Grid1.Cell(row, COLS.用量).Text
                    Grid1.Cell(row, COLS.用量).BackColor = Color.Green
                Catch ex As Exception
                    Grid1.Cell(row, COLS.用量).BackColor = Color.Red
                    checkResult = False
                End Try

                Grid1.Cell(row, COLS.序号).Text = m_SN
                m_SN += 1
            End If
        Next

        Return checkResult
    End Function

    Private Function SaveBomItems(ByVal bomName As String) As Boolean
        Dim row As Integer
        Dim col As Integer
        Dim result As Boolean = True

        'INSERT INTO table_name(col_name,...) values(expr,...)
        Dim strInsert As String = "INSERT INTO `" & "bom_" & bomName & "` "
        Dim insertItems As String = ""
        For col = 0 To COLS.max - 3
            If m_COLS_NAME(col, 1) = "1" Then
                If insertItems.Length > 0 Then
                    insertItems &= ","
                End If
                insertItems &= "`" & m_COLS_NAME(col, 0) & "`"
            End If
        Next

        For row = 1 To Grid1.Rows - 1
            If Grid1.Cell(row, COLS.料号PN).BackColor = Color.Green Then
                Dim insertValues As String = ""

                For col = 0 To COLS.max - 3
                    If m_COLS_NAME(col, 1) = "1" Then
                        If insertValues.Length > 0 Then
                            insertValues &= ","
                        End If

                        If Grid1.Column(col).CellType = FlexCell.CellTypeEnum.CheckBox Then
                            If Grid1.Cell(row, col).BooleanValue = True Then
                                insertValues &= "'1'"
                            Else
                                insertValues &= "'0'"
                            End If
                        Else
                            insertValues &= "'" & Grid1.Cell(row, col).Text & "'"
                        End If
                    End If
                Next

                Dim strSQL As String = strInsert & "(" & insertItems & ") values(" & insertValues & ")"
                If SQL_ExeCommand(COL_RIGHTS.BOM管理, strSQL) = False Then
                    result = False
                    Exit For
                End If
            End If
        Next

        Return result
    End Function

    Private Function SaveBom(ByVal bomName As String) As Boolean
        '删除原Bom
        'If DropBom(bomName) = False Then Return False
        'MsgBox("DropBOM OK！")

        '创建新Bom
        Dim tempBom As String = bomName & "_temp"
        If CreateBom(tempBom) = False Then Return False
        'MsgBox("CreateBom OK！")

        '保存Bom内容
        If SaveBomItems(tempBom) = False Then Return False
        'MsgBox("SaveBomItems OK！")

        '删除原Bom
        If DropBom(bomName) = False Then Return False

        '重命名新BOM
        If RenameBom(tempBom, bomName) = False Then Return False

        Return True
    End Function


    Private Function SaveBomItems2(tempBom) As Boolean
        Dim result As Boolean = True

        Dim cmdText As New StringBuilder
        Dim insertStr As New StringBuilder
        insertStr.Append($"INSERT INTO `bom_{tempBom}` ")
        insertStr.Append("(")
        insertStr.Append($"`{SourceGridCols.使用位置}`,")
        insertStr.Append($"`{SourceGridCols.用量}`,")
        insertStr.Append($"`{SourceGridCols.工艺流程}`,")
        insertStr.Append($"`{SourceGridCols.料号PN}`")
        insertStr.Append(")")
        insertStr.Append(" values")

        For i = 1 To GrdSourceBom.Rows - 1
            If String.IsNullOrEmpty(GrdSourceBom.Cell(i, SourceGridCols.注释).Text) Then
                If String.IsNullOrEmpty(GrdSourceBom.Cell(i, SourceGridCols.料号PN).Text) Then
                    Continue For
                End If
            End If

            cmdText.Clear()
            cmdText.Append(insertStr.ToString)
            cmdText.Append("(")

            cmdText.Append($"'{GrdSourceBom.Cell(i, SourceGridCols.使用位置).Text}',")
            cmdText.Append($"'{GrdSourceBom.Cell(i, SourceGridCols.用量).Text}',")
            cmdText.Append($"'{GrdSourceBom.Cell(i, SourceGridCols.工艺流程).Text}',")
            cmdText.Append($"'{GrdSourceBom.Cell(i, SourceGridCols.料号PN).Text}'")

            cmdText.Append(")")

            If SQL_ExeCommand(COL_RIGHTS.BOM管理, cmdText.ToString) = False Then
                result = False
                Exit For
            End If
        Next

        Return result
    End Function


    ''' <summary>
    ''' 保存BOM临时表
    ''' </summary>
    ''' <param name="bomName"></param>
    ''' <returns></returns>
    Private Function SaveBom2(bomName As String) As Boolean

        '创建新Bom
        Dim tempBom As String = bomName & "_temp"
        If CreateBom(tempBom) = False Then Return False

        '保存Bom内容
        If SaveBomItems2(tempBom) = False Then Return False

        '删除原Bom
        If DropBom(bomName) = False Then Return False

        '重命名新BOM
        If RenameBom(tempBom, bomName) = False Then Return False

        Return True
    End Function


    Private Function SaveBomContextItems(tempBom) As Boolean
        Dim result As Boolean = True

        'INSERT INTO table_name(col_name,...) values(expr,...)
        Dim cmdText As New StringBuilder
        Dim insertStr As New StringBuilder
        insertStr.Append($"INSERT INTO `bom_{tempBom}` ")
        insertStr.Append("(")
        insertStr.Append($"`{SourceGridCols.注释}`,")
        insertStr.Append($"`{SourceGridCols.使用位置}`,")
        insertStr.Append($"`{SourceGridCols.型号}`,")
        insertStr.Append($"`{SourceGridCols.用量}`,")
        insertStr.Append($"`{SourceGridCols.校验}`,")
        insertStr.Append($"`{SourceGridCols.工艺流程}`,")
        insertStr.Append($"`{SourceGridCols.料号PN}`")
        insertStr.Append(")")
        insertStr.Append(" values")

        For i = 1 To GrdSourceBom.Rows - 1
            If String.IsNullOrEmpty(GrdSourceBom.Cell(i, SourceGridCols.注释).Text) Then
                If String.IsNullOrEmpty(GrdSourceBom.Cell(i, SourceGridCols.料号PN).Text) Then
                    Continue For
                End If
            End If

            cmdText.Clear()
            cmdText.Append(insertStr.ToString)
            cmdText.Append("(")

            cmdText.Append($"'{GrdSourceBom.Cell(i, SourceGridCols.注释).Text}',")
            cmdText.Append($"'{GrdSourceBom.Cell(i, SourceGridCols.使用位置).Text}',")
            cmdText.Append($"'{GrdSourceBom.Cell(i, SourceGridCols.型号).Text}',")
            cmdText.Append($"'{GrdSourceBom.Cell(i, SourceGridCols.用量).Text}',")
            cmdText.Append($"'{GrdSourceBom.Cell(i, SourceGridCols.校验).Text}',")
            cmdText.Append($"'{GrdSourceBom.Cell(i, SourceGridCols.工艺流程).Text}',")
            cmdText.Append($"'{GrdSourceBom.Cell(i, SourceGridCols.料号PN).Text}'")

            cmdText.Append(")")

            If SQL_ExeCommand(COL_RIGHTS.BOM管理, cmdText.ToString) = False Then
                result = False
                Exit For
            End If
        Next

        Return result
    End Function


    ''' <summary>
    ''' 保存BOM临时表
    ''' </summary>
    ''' <param name="bomName"></param>
    ''' <returns></returns>
    Private Function SaveBomContext(bomName As String) As Boolean
        '创建新Bom
        Dim oldBom As String = bomName & "_context"
        Dim tempBom As String = bomName & "_context" & "_temp"
        If CreateContextBom(tempBom) = False Then Return False

        '保存Bom内容
        If SaveBomContextItems(tempBom) = False Then Return False

        '删除原Bom
        If DropBom(oldBom) = False Then Return False

        '重命名新BOM
        If RenameBom(tempBom, oldBom) = False Then Return False

        Return True
    End Function




    Private Sub PushToBomPath(ByVal bomName As String)
        m_BomPath.Add(m_CurrentBomPN)
        RefreshBomPath()
    End Sub

    Private Function PopFromBomPath() As String
        Dim backBomName As String = ""

        If m_BomPath.Count >= 2 Then
            m_BomPath.RemoveAt(m_BomPath.Count - 1)
            backBomName = m_BomPath.Item(m_BomPath.Count - 1)
            m_BomPath.RemoveAt(m_BomPath.Count - 1)
        End If

        RefreshBomPath()

        Return backBomName
    End Function

    Private Sub RefreshBomPath()
        Dim tempPath As String = ""

        For Each pItem As String In m_BomPath
            If tempPath.Length > 0 Then
                tempPath &= "\"
            End If
            tempPath &= pItem
        Next

        lblBomPath.Text = tempPath

        If m_BomPath.Count >= 2 Then
            btOpenBack.Enabled = True
        Else
            btOpenBack.Enabled = False
        End If

        btOpenNext.Enabled = False

        Application.DoEvents()
    End Sub

    Private Function OpenBom(ByVal bomName As String) As Boolean
        Dim result As Boolean = False

        '检查输入料号是否有效
        Dim isExist As Boolean = False
        If m_PartNumber.CheckPartNumber(bomName, isExist) = ERROR_CODE.SUCCESS Then
            If isExist = False Then
                MsgBox("输入料号不存在!")
                Return False
            End If
        Else
            MsgBox("无法查询输入料号，请检查网络连接!")
            Return False
        End If

        '检测输入料号的料表是否已经存在
        If CheckBomExist(bomName, isExist) = True Then
            If isExist = True Then
                m_CurrentBomPN = bomName
                lbl_CurrentPN.Text = "当前料表料号:" & m_CurrentBomPN

                '查询料表模板
                If QueryBom(m_CurrentBomPN, m_Table) = True Then
                    PushToBomPath(m_CurrentBomPN)

                    FillGridHeaderByDataTable()
                    FillGridByDataTable()
                    If chk_ShowPnInfo.Checked = True Then
                        GetAllPNItemInfo()
                    End If

                    result = True
                End If
            Else
                If MessageBox.Show("输入料号BOM不存在,是否新建BOM?" & vbNewLine & "选择""是""新建, 否则""取消""", "新建BOM?", MessageBoxButtons.YesNo) = Windows.Forms.DialogResult.Yes Then
                    m_CurrentBomPN = bomName
                    lbl_CurrentPN.Text = "当前料表料号:" & m_CurrentBomPN

                    '查询料表模板
                    If QueryBom(m_BomTemplateName, m_Table) = True Then
                        PushToBomPath(m_CurrentBomPN)
                        FillGridHeaderByDataTable()

                        result = True
                    End If
                End If
            End If
        Else
            MsgBox("无法查询输入料号对应的BOM是否存在，请检查网络连接!")
        End If

        Return result
    End Function

    ''' <summary>
    ''' 加载临时Bom表
    ''' </summary>
    ''' <param name="bomName"></param>
    ''' <returns></returns>
    Private Function OpenBomContext(bomName As String) As Boolean
        '检查输入料号是否有效
        Dim isExist As Boolean = False
        If m_PartNumber.CheckPartNumber(bomName, isExist) = ERROR_CODE.SUCCESS Then
            If isExist = False Then
                MsgBox("输入料号不存在!")
                Return False
            End If
        Else
            MsgBox("无法查询输入料号，请检查网络连接!")
            Return False
        End If

        '检测输入料号的料表是否已经存在
        If CheckBomExist(bomName, isExist) = False Then
            MsgBox("无法查询输入料号对应的BOM是否存在，请检查网络连接!")
            Return False
        End If

        Dim tbName As String '数据表名
        If isExist = False Then
            If MessageBox.Show($"输入料号BOM不存在,是否新建BOM?{vbNewLine}选择""是""新建, 否则""取消""", "新建BOM?", MessageBoxButtons.YesNo) <> Windows.Forms.DialogResult.Yes Then
                Return False
            End If
            tbName = $"bom_模板_context"
        Else
            tbName = $"bom_{bomName}_context"
        End If

        lbl_CurrentPN.Text = "当前料表料号:" & bomName


        '查询云端数据
        Dim strSQL As String = $"Select * From `{tbName}` order by `ID` asc"
        Dim dtTable As New DataTable
        If SQL_Query(COL_RIGHTS.BOM管理, strSQL, dtTable) = False Then Return False

        '名称有所变化(不明作用)
        ' PushToBomPath(bomName) 

        '填充至表格
        InitSourceGrid() '初始化表格
        GrdSourceBom.AutoRedraw = False
        For i = 0 To dtTable.Rows.Count - 1
            GrdSourceBom.Cell(i + 1, SourceGridCols.注释).Text = dtTable(i)($"{SourceGridCols.注释}").ToString
            GrdSourceBom.Cell(i + 1, SourceGridCols.使用位置).Text = dtTable(i)($"{SourceGridCols.使用位置}").ToString
            GrdSourceBom.Cell(i + 1, SourceGridCols.型号).Text = dtTable(i)($"{SourceGridCols.型号}").ToString
            GrdSourceBom.Cell(i + 1, SourceGridCols.用量).Text = dtTable(i)($"{SourceGridCols.用量}").ToString
            GrdSourceBom.Cell(i + 1, SourceGridCols.校验).Text = dtTable(i)($"{SourceGridCols.校验}").ToString
            GrdSourceBom.Cell(i + 1, SourceGridCols.工艺流程).Text = dtTable(i)($"{SourceGridCols.工艺流程}").ToString
            GrdSourceBom.Cell(i + 1, SourceGridCols.料号PN).Text = dtTable(i)($"{SourceGridCols.料号PN}").ToString
        Next
        GrdSourceBom.AutoRedraw = True
        GrdSourceBom.Refresh()

        If chk_ShowPnInfo.Checked Then
            GetAllPnInfo()
        End If

        Return True
    End Function


    Private Sub btQueryBom_Click(sender As Object, e As EventArgs) Handles btQueryBom.Click
        m_CurrentBomPN = ""
        m_BomPath.Clear()

        If tbBomPN.Text.Length = 0 Then
            MsgBox("输入料号不能为空")
            Return
        End If

        If TabControl1.SelectedIndex = 0 Then
            OpenBom(tbBomPN.Text)
        ElseIf TabControl1.SelectedIndex = 2 Then
            OpenBomContext(tbBomPN.Text) '加载临时BOM
        End If
    End Sub

    Private Function GetPNItemInfo(ByVal gridRowIndex As Integer) As Boolean
        Dim 物料名称 As String = ""
        Dim 规格描述 As String = ""
        Dim 单位 As String = ""
        Dim 单重 As Double = 0
        Dim 图片(0) As Byte
        Dim 供应商ID As String = ""

        Dim 用量 As String = Grid1.Cell(gridRowIndex, 6).IntegerValue


        'Grid1.Cell(gridRowIndex, COLS.物料名称).Text = ""
        'Grid1.Cell(gridRowIndex, COLS.规格描述).Text = ""
        'Grid1.Cell(gridRowIndex, COLS.单位).Text = ""
        'Grid1.Cell(gridRowIndex, COLS.单价).Text = ""
        'Grid1.Cell(gridRowIndex, COLS.单位总价).Text = ""
        'Grid1.Cell(gridRowIndex, COLS.图片).Text = ""

        Dim result As Boolean = False
        Dim strPn As String = Grid1.Cell(gridRowIndex, COLS.料号PN).Text


        'If chk_ShowPnImage.Checked = True Then
        '    If m_PartNumber.QueryItem(strPn, 物料名称, 规格描述, 单位, 单重, 图片, 供应商ID) = ERROR_CODE.SUCCESS Then
        '        Grid1.Cell(gridRowIndex, COLS.物料名称).Text = 物料名称
        '        Grid1.Cell(gridRowIndex, COLS.规格描述).Text = 规格描述
        '        Grid1.Cell(gridRowIndex, COLS.单位).Text = 单位
        '        Grid1.Cell(gridRowIndex, COLS.单价).Text = 单重
        '        Grid1.Cell(gridRowIndex, COLS.单位总价).Text = 单重 * 用量

        '        Grid1.Cell(gridRowIndex, COLS.图片).Text = ""

        '        Dim mImage As System.Drawing.Image = GetImageFromBytes(图片)
        '        If Grid1.Images.Count >= gridRowIndex Then
        '            Grid1.Images.Remove(gridRowIndex.ToString)
        '        End If
        '        Grid1.Images.Add(mImage, gridRowIndex.ToString)
        '        Grid1.Cell(gridRowIndex, COLS.图片).SetImage(gridRowIndex.ToString)

        '        result = True
        '    End If
        'Else
        '    If m_PartNumber.QueryItem(strPn, 物料名称, 规格描述, 单位, 单重, 供应商ID) = ERROR_CODE.SUCCESS Then
        '        Grid1.Cell(gridRowIndex, COLS.物料名称).Text = 物料名称
        '        Grid1.Cell(gridRowIndex, COLS.规格描述).Text = 规格描述
        '        Grid1.Cell(gridRowIndex, COLS.单位).Text = 单位
        '        Grid1.Cell(gridRowIndex, COLS.单价).Text = 单重
        '        Grid1.Cell(gridRowIndex, COLS.单位总价).Text = 单重 * 用量
        '        Grid1.Cell(gridRowIndex, COLS.图片).Text = ""
        '        result = True
        '    End If
        'End If



        If chk_ShowPnImage.Checked = True Then
            If m_PartNumber.QueryItem(strPn, 物料名称, 规格描述, 单位, 单重, 图片, 供应商ID) = ERROR_CODE.SUCCESS Then
                '填充图像
                Dim mImage As System.Drawing.Image = GetImageFromBytes(图片)
                If Grid1.Images.Count >= gridRowIndex Then
                    Grid1.Images.Remove(gridRowIndex.ToString)
                End If
                Grid1.Images.Add(mImage, gridRowIndex.ToString)
                Grid1.Cell(gridRowIndex, COLS.图片).SetImage(gridRowIndex.ToString)

                result = True
            End If
        Else
            If m_PartNumber.QueryItem(strPn, 物料名称, 规格描述, 单位, 单重, 供应商ID) = ERROR_CODE.SUCCESS Then
                result = True
            End If
        End If

        Grid1.Cell(gridRowIndex, COLS.物料名称).Text = 物料名称
        Grid1.Cell(gridRowIndex, COLS.规格描述).Text = 规格描述
        Grid1.Cell(gridRowIndex, COLS.单位).Text = 单位
        Grid1.Cell(gridRowIndex, COLS.单价).Text = 单重
        Grid1.Cell(gridRowIndex, COLS.单位总价).Text = 单重 * 用量
        Grid1.Cell(gridRowIndex, COLS.图片).Text = ""

        Return result
    End Function


    Private Function GetAllPNItemInfo() As Boolean
        Dim TotalCost As Double = 0
        Dim AvailabeRows As Integer = 0

        For row As Integer = 1 To Grid1.Rows - 1
            Grid1.Cell(row, COLS.物料名称).Text = ""
            Grid1.Cell(row, COLS.规格描述).Text = ""
            Grid1.Cell(row, COLS.单位).Text = ""

            Grid1.Cell(row, COLS.单价).Text = ""
            Grid1.Cell(row, COLS.单位总价).Text = ""

            Grid1.Cell(row, COLS.图片).Text = ""
        Next

        Grid1.Images.Clear()

        Dim result As Boolean = True

        For row As Integer = 1 To Grid1.Rows - 1
            AvailabeRows = AvailabeRows + 1
            If GetPNItemInfo(row) = False Then
                result = False
                Exit For
            End If
            TotalCost = TotalCost + Grid1.Cell(row, COLS.单位总价).Text
        Next
        Grid1.Cell(AvailabeRows, COLS.单位总价 - 1).Text = "Total : "
        Grid1.Cell(AvailabeRows, COLS.单位总价).Text = TotalCost

        Return result
    End Function

    Private Sub Grid1_LeaveCell(Sender As Object, e As FlexCell.Grid.LeaveCellEventArgs) Handles Grid1.LeaveCell
        If e.Row > 1 AndAlso e.Col = COLS.料号PN Then
            If Grid1.Cell(e.Row, e.Col).Text.Length > 0 Then
                Dim inputBomPn As String = Grid1.Cell(e.Row, e.Col).Text.ToUpper
                Grid1.Cell(e.Row, e.Col).Text = inputBomPn

                Dim isExist As Boolean = False
                If m_PartNumber.CheckPartNumber(inputBomPn, isExist) = ERROR_CODE.SUCCESS Then
                    If isExist = True Then
                        If chk_ShowPnInfo.Checked = True Then
                            GetPNItemInfo(e.Row)
                        End If
                    Else
                        Grid1.Cell(e.Row, e.Col).BackColor = Color.Red
                    End If
                Else
                    MsgBox("无法查询输入料号，请检查网络连接!")
                    Return
                End If
            End If
        End If
    End Sub

    Private Sub form_BomManage_FormClosed(sender As Object, e As FormClosedEventArgs) Handles Me.FormClosed
        My.Settings.FORM_BOM_COL_WIDTH_序号 = Grid1.Column(COLS.序号).Width
        My.Settings.FORM_BOM_COL_WIDTH_工艺流程 = Grid1.Column(COLS.工艺流程).Width
        My.Settings.FORM_BOM_COL_WIDTH_料号PN = Grid1.Column(COLS.料号PN).Width
        My.Settings.FORM_BOM_COL_WIDTH_物料名称 = Grid1.Column(COLS.物料名称).Width
        My.Settings.FORM_BOM_COL_WIDTH_规格描述 = Grid1.Column(COLS.规格描述).Width
        My.Settings.FORM_BOM_COL_WIDTH_单位 = Grid1.Column(COLS.单位).Width
        My.Settings.FORM_BOM_COL_WIDTH_用量 = Grid1.Column(COLS.用量).Width
        My.Settings.FORM_BOM_COL_WIDTH_使用位置 = Grid1.Column(COLS.使用位置).Width
        My.Settings.FORM_BOM_COL_WIDTH_父料号 = Grid1.Column(COLS.父料号).Width
        My.Settings.FORM_BOM_COL_WIDTH_图片 = Grid1.Column(COLS.图片).Width
        My.Settings.FORM_BOM_COL_WIDTH_备注 = Grid1.Column(COLS.备注).Width
        My.Settings.FORM_BOM_HEIGHT = Me.Height
        My.Settings.FORM_BOM_WIDTH = Me.Width

        My.Settings.Save()
    End Sub

    Private Sub btInsertRow_Click(sender As Object, e As EventArgs) Handles btInsertRow.Click
        Grid1.Selection.InsertRows()
    End Sub

    Private Sub btDeleteRow_Click(sender As Object, e As EventArgs) Handles btDeleteRow.Click
        Grid1.Selection.DeleteByRow()
    End Sub

    Private Sub btUpdate_Click(sender As Object, e As EventArgs) Handles btUpdate.Click
        GetAllPNItemInfo()
    End Sub

    Private Sub btOpenFatherPN_Click(sender As Object, e As EventArgs) Handles btOpenNext.Click
        Dim selRow As Integer = Grid1.Selection.FirstRow
        If selRow >= 1 Then
            If Grid1.Cell(selRow, COLS.父料号).BooleanValue = True Then
                tbBomPN.Text = Grid1.Cell(Grid1.Selection.FirstRow, COLS.料号PN).Text
                OpenBom(tbBomPN.Text)
            Else
                MsgBox("选择项不是父料号，无法打开")
            End If
        End If
    End Sub

    Private Sub btOpenBack_Click(sender As Object, e As EventArgs) Handles btOpenBack.Click
        tbBomPN.Text = PopFromBomPath()
        If tbBomPN.Text.Length > 0 Then
            OpenBom(tbBomPN.Text)
        End If
    End Sub

    Private Sub form_BomManage_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        FillGridHeaderByDataTable()
        m_BomPath.Clear()
        RefreshBomPath()
        btOpenNext.Enabled = False

        InitSourceGrid()
    End Sub

    Private Sub Grid1_MouseClick(sender As Object, e As MouseEventArgs) Handles Grid1.MouseClick
        btOpenNext.Enabled = False
        If Grid1.Selection.FirstRow >= 1 Then
            If Grid1.Cell(Grid1.Selection.FirstRow, COLS.父料号).BooleanValue = True Then
                If Grid1.Cell(Grid1.Selection.FirstRow, COLS.料号PN).Text.Length > 0 Then
                    btOpenNext.Enabled = True
                End If
            End If
        End If
    End Sub

    Private Sub Grid1_MouseDoubleClick(sender As Object, e As MouseEventArgs) Handles Grid1.MouseDoubleClick
        Dim selRow As Integer = Grid1.Selection.FirstRow
        Dim selCol As Integer = Grid1.Selection.FirstCol
        If Grid1.Selection.FirstRow >= 1 Then
            If Grid1.Selection.FirstCol = COLS.图片 Then
                Dim imageKey As String = Grid1.Cell(selRow, selCol).ImageKey
                If Not imageKey Is Nothing AndAlso imageKey.Length > 0 Then
                    Dim mImage As System.Drawing.Image = Grid1.Images.Item(imageKey).Picture
                    If Not mImage Is Nothing Then
                        Dim dlgImage As New dlgImage
                        dlgImage.Text = Grid1.Cell(selRow, COLS.料号PN).Text
                        dlgImage.BackgroundImage = mImage
                        dlgImage.ShowDialog()
                    End If
                End If
            End If
        End If
    End Sub

    Private Sub tbBomPN_KeyDown(sender As Object, e As KeyEventArgs) Handles tbBomPN.KeyDown
        If e.KeyCode = Keys.Enter Then
            btQueryBom.PerformClick()
        End If
    End Sub

    Private Sub chk_ShowPnImage_CheckedChanged(sender As Object, e As EventArgs) Handles chk_ShowPnImage.CheckedChanged
        If chk_ShowPnImage.Checked = False Then
            Grid1.Images.Clear()
        End If
    End Sub

    Private Sub btDelete_Click(sender As Object, e As EventArgs) Handles btDelete.Click
        If m_CurrentBomPN.Length = 0 Then
            MsgBox("未指定当前BOM料号!")
            Return
        End If

        '检查输入料号是否有效
        Dim isExist As Boolean = False
        If m_PartNumber.CheckPartNumber(m_CurrentBomPN, isExist) = ERROR_CODE.SUCCESS Then
            If isExist = False Then
                MsgBox("输入料号不存在!")
                Return
            End If
        Else
            MsgBox("无法查询输入料号，请检查网络连接!")
            Return
        End If

        '检测Bom表是否存在
        isExist = False
        If CheckBomExist(m_CurrentBomPN, isExist) = False Then
            MsgBox("指定料号对应BOM不存在！")
            Return
        End If

        If MessageBox.Show("确认删除指定BOM:" & m_CurrentBomPN & "，删除后无法恢复！", "BOM:" & m_CurrentBomPN & "删除确认", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2) = Windows.Forms.DialogResult.OK Then
            '删除料号表
            If DropBom(m_CurrentBomPN) = False Then
                MsgBox("删除料表失败")
                Return
            End If

            MsgBox("删除料表:" & m_CurrentBomPN & "成功")
        End If
    End Sub

    Private Sub bt_Export_Click(sender As Object, e As EventArgs) Handles bt_Export.Click
        Dim dlg As New SaveFileDialog()
        dlg.DefaultExt = "xls"
        dlg.Filter = "Excel File|*.xls"
        If dlg.ShowDialog() <> Windows.Forms.DialogResult.OK Then Return

        If Grid1.ExportToExcel(dlg.FileName, True, True) Then
            MsgBox("保存为Excel成功：" & dlg.FileName)
        Else
            MsgBox("保存失败!")
        End If
    End Sub








    '2021/10/06 Qizengbiao修改
#Region "数据查询"
    Public Function GetLikeString(ByVal likestr As String) As String
        Dim rString As String = ""
        Dim ch As Char
        For i As Integer = 1 To likestr.Length
            ch = Strings.GetChar(likestr, i)
            If ch = "%" OrElse ch = "_" OrElse ch = "/" Then
                rString &= "/"
            End If
            rString &= ch
        Next

        Return rString
    End Function

    Private Sub QueryData_Quick(partNumber As String, partName As String, partDesc As String, hasInhaos As Boolean, hasJohao As Boolean)
        Dim strSQL As String = "SELECT `" &
                                CPartNumber.m_COLS_NAME(CPartNumber.COLS.料号PN) & "`,`" &
                                CPartNumber.m_COLS_NAME(CPartNumber.COLS.物料名称) & "`,`" &
                                CPartNumber.m_COLS_NAME(CPartNumber.COLS.规格描述) & "`,`" &
                                CPartNumber.m_COLS_NAME(CPartNumber.COLS.单位) & "`,`" &
                                CPartNumber.m_COLS_NAME(CPartNumber.COLS.单重) & "`,`" &
                                CPartNumber.m_COLS_NAME(CPartNumber.COLS.供应商ID) & "`, `" &
                                CPartNumber.m_COLS_NAME(CPartNumber.COLS.序号) & "`"
        strSQL &= " FROM `" & CPartNumber.cst_TABLE_NAME & "`"

        If partNumber.Length > 0 OrElse
            partName.Length > 0 OrElse
            partDesc.Length > 0 OrElse
            hasInhaos = True OrElse
            hasJohao = True Then

            strSQL &= " WHERE "

            Dim strSplit() As String
            Dim firstLike As Boolean = True
            If partNumber.Length > 0 Then
                strSplit = Split(partNumber, ",")
                For i As Integer = 0 To strSplit.Length - 1
                    If firstLike = True Then
                        firstLike = False
                    Else
                        strSQL &= " AND "
                    End If
                    strSQL &= "`" & CPartNumber.m_COLS_NAME(CPartNumber.COLS.料号PN) & "`"
                    strSQL &= " COLLATE gbk_chinese_ci "
                    strSQL &= " LIKE '%"
                    strSQL &= GetLikeString(strSplit(i)) & "%'"
                    strSQL &= " escape '/'"
                Next
            End If

            If partName.Length > 0 Then
                strSplit = Split(partName, ",")
                For i As Integer = 0 To strSplit.Length - 1
                    If firstLike = True Then
                        firstLike = False
                    Else
                        strSQL &= " AND "
                    End If
                    strSQL &= "`" & CPartNumber.m_COLS_NAME(CPartNumber.COLS.物料名称) & "`"
                    strSQL &= " COLLATE gbk_chinese_ci "
                    strSQL &= " LIKE '%"
                    strSQL &= GetLikeString(strSplit(i)) & "%'"
                    strSQL &= " escape '/'"
                Next
            End If

            If partDesc.Length > 0 Then
                strSplit = Split(partDesc, ",")
                For i As Integer = 0 To strSplit.Length - 1
                    Dim tmp As String = GetLikeString(strSplit(i))
                    If String.IsNullOrEmpty(tmp) Then Continue For

                    If firstLike = True Then
                        firstLike = False
                    Else
                        strSQL &= " AND "
                    End If

                    Select Case tmp(tmp.Length - 1)'查看是否以R或Ω结尾
                        Case "R"c
                            strSQL &= "("

                            strSQL &= "`" & CPartNumber.m_COLS_NAME(CPartNumber.COLS.规格描述) & "`"
                            strSQL &= " COLLATE gbk_chinese_ci "
                            strSQL &= " LIKE '%"
                            strSQL &= tmp & "%'"
                            strSQL &= " escape '/'"

                            strSQL &= " or "

                            strSQL &= "`" & CPartNumber.m_COLS_NAME(CPartNumber.COLS.规格描述) & "`"
                            strSQL &= " COLLATE gbk_chinese_ci "
                            strSQL &= " LIKE '%"
                            strSQL &= tmp.Replace("R"c, "Ω"c) & "%'"
                            strSQL &= " escape '/'"

                            strSQL &= ")"
                        Case "Ω"c
                            strSQL &= "("

                            strSQL &= "`" & CPartNumber.m_COLS_NAME(CPartNumber.COLS.规格描述) & "`"
                            strSQL &= " COLLATE gbk_chinese_ci "
                            strSQL &= " LIKE '%"
                            strSQL &= tmp & "%'"
                            strSQL &= " escape '/'"

                            strSQL &= " or "

                            strSQL &= "`" & CPartNumber.m_COLS_NAME(CPartNumber.COLS.规格描述) & "`"
                            strSQL &= " COLLATE gbk_chinese_ci "
                            strSQL &= " LIKE '%"
                            strSQL &= tmp.Replace("Ω"c, "R"c) & "%'"
                            strSQL &= " escape '/'"

                            strSQL &= ")"
                        Case Else
                            strSQL &= "`" & CPartNumber.m_COLS_NAME(CPartNumber.COLS.规格描述) & "`"
                            strSQL &= " COLLATE gbk_chinese_ci "
                            strSQL &= " LIKE '%"
                            strSQL &= GetLikeString(strSplit(i)) & "%'"
                            strSQL &= " escape '/'"
                    End Select
                Next
            End If

            Dim customStr As String = ""
            If hasInhaos Then
                customStr &= "`" & CPartNumber.m_COLS_NAME(CPartNumber.COLS.供应商ID) & "` = '02'"
            End If

            If hasJohao Then
                If String.IsNullOrEmpty(customStr) = False Then
                    customStr &= " OR "
                    customStr &= "`" & CPartNumber.m_COLS_NAME(CPartNumber.COLS.供应商ID) & "` ='01'"

                    customStr = $"({customStr})"
                Else
                    customStr &= "`" & CPartNumber.m_COLS_NAME(CPartNumber.COLS.供应商ID) & "` ='01'"
                End If
            End If

            If firstLike = True Then
                firstLike = False
            Else
                strSQL &= " AND "
            End If
            strSQL &= customStr
        End If

        SQL_Query(COL_RIGHTS.料号管理, strSQL, m_Table)
    End Sub



#End Region
    Enum SourceGridCols
        Sn
        注释
        使用位置
        型号
        用量
        校验
        工艺流程
        料号PN
        物料名称
        规格描述
        单位
        单价
        Max
    End Enum

    Private Sub InitSourceGrid()
        GrdSourceBom.NewFile()

        GrdSourceBom.Cols = SourceGridCols.Max
        GrdSourceBom.Rows = 500

        GrdSourceBom.AutoRedraw = False
        GrdSourceBom.DisplayRowNumber = True
        GrdSourceBom.ExtendLastCol = True

        For i = 0 To GrdSourceBom.Cols - 1
            GrdSourceBom.Cell(0, i).Text = [Enum].GetName(GetType(SourceGridCols), i)
        Next

        GrdSourceBom.Column(SourceGridCols.规格描述).Width = 200
        GrdSourceBom.Column(SourceGridCols.校验).CellType = FlexCell.CellTypeEnum.CheckBox

        GrdSourceBom.Column(SourceGridCols.工艺流程).CellType = FlexCell.CellTypeEnum.ComboBox
        With GrdSourceBom.ComboBox(SourceGridCols.工艺流程)
            .DataSource = m_ProcessRoutingTable
            .Locked = False
            .AutoComplete = True
        End With

        GrdSourceBom.Range(0, SourceGridCols.校验, GrdSourceBom.Rows - 1, SourceGridCols.校验).BackColor = Color.LightBlue

        GrdSourceBom.AutoRedraw = True
        GrdSourceBom.Refresh()
    End Sub

    Enum QueueGridCols
        Sn
        料号PN
        物料名称
        规格描述
        单位
        单重
        供应商ID
        序号
    End Enum

    Enum DestBomGridCols
        序号
        工艺流程
        料号PN
        物料名称
        规格描述
        单位
        用量
        使用位置
        单价
        单位总价
        MAX
    End Enum


    Private Sub 导出ToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles 导出ToolStripMenuItem.Click
        Using fileDialog As New SaveFileDialog
            fileDialog.Filter = "Excel文档(*.xls)|*.xls"
            fileDialog.AddExtension = True

            If String.IsNullOrEmpty(tbBomPN.Text) Then
                fileDialog.FileName = tbBomPN.Text
            Else
                fileDialog.FileName = tbBomPN.Text & "-BOM"
            End If


            If fileDialog.ShowDialog <> DialogResult.OK Then Return

            GrdSourceBom.ExportToExcel(fileDialog.FileName, True, True)

            Dim tmpGrid As New FlexCell.Grid
            tmpGrid.DisplayRowNumber = True
            tmpGrid.Cols = DestBomGridCols.MAX + 1
            tmpGrid.Rows = GrdSourceBom.Rows

            tmpGrid.BackColorFixed = tmpGrid.BackColor1

            tmpGrid.Cell(0, DestBomGridCols.序号).Text = "序号"
            tmpGrid.Cell(0, DestBomGridCols.工艺流程).Text = "工艺流程"
            tmpGrid.Cell(0, DestBomGridCols.料号PN).Text = "料号PN"
            tmpGrid.Cell(0, DestBomGridCols.物料名称).Text = "物料名称"
            tmpGrid.Cell(0, DestBomGridCols.规格描述).Text = "规格描述"
            tmpGrid.Cell(0, DestBomGridCols.单位).Text = "单位"
            tmpGrid.Cell(0, DestBomGridCols.用量).Text = "用量"
            tmpGrid.Cell(0, DestBomGridCols.使用位置).Text = "使用位置"
            tmpGrid.Cell(0, DestBomGridCols.单价).Text = "单价"
            tmpGrid.Cell(0, DestBomGridCols.单位总价).Text = "单位总价"

            tmpGrid.Cell(1, DestBomGridCols.序号 + 1).Text = "序号"
            tmpGrid.Cell(1, DestBomGridCols.工艺流程 + 1).Text = "工艺流程"
            tmpGrid.Cell(1, DestBomGridCols.料号PN + 1).Text = "料号PN"
            tmpGrid.Cell(1, DestBomGridCols.物料名称 + 1).Text = "物料名称"
            tmpGrid.Cell(1, DestBomGridCols.规格描述 + 1).Text = "规格描述"
            tmpGrid.Cell(1, DestBomGridCols.单位 + 1).Text = "单位"
            tmpGrid.Cell(1, DestBomGridCols.用量 + 1).Text = "用量"
            tmpGrid.Cell(1, DestBomGridCols.使用位置 + 1).Text = "使用位置"
            tmpGrid.Cell(1, DestBomGridCols.单价 + 1).Text = "单价"
            tmpGrid.Cell(1, DestBomGridCols.单位总价 + 1).Text = "单位总价"

            For i = 2 To tmpGrid.Rows - 1
                If String.IsNullOrEmpty(GrdSourceBom.Cell(i, SourceGridCols.料号PN).Text) Then
                    tmpGrid.Cell(i, DestBomGridCols.单价 + 1).Text = "Totel:"


                    Dim totel As Double = 0
                    For j = 2 To i - 1
                        totel += tmpGrid.Cell(j, DestBomGridCols.单位总价 + 1).DoubleValue
                    Next

                    tmpGrid.Cell(i, DestBomGridCols.单位总价 + 1).Text = totel
                    Continue For
                End If

                tmpGrid.Cell(i, DestBomGridCols.序号 + 1).Text = i - 1
                tmpGrid.Cell(i, DestBomGridCols.工艺流程 + 1).Text = GrdSourceBom.Cell(i - 1, SourceGridCols.工艺流程).Text
                tmpGrid.Cell(i, DestBomGridCols.料号PN + 1).Text = GrdSourceBom.Cell(i - 1, SourceGridCols.料号PN).Text
                tmpGrid.Cell(i, DestBomGridCols.物料名称 + 1).Text = GrdSourceBom.Cell(i - 1, SourceGridCols.物料名称).Text
                tmpGrid.Cell(i, DestBomGridCols.规格描述 + 1).Text = GrdSourceBom.Cell(i - 1, SourceGridCols.规格描述).Text
                tmpGrid.Cell(i, DestBomGridCols.单位 + 1).Text = GrdSourceBom.Cell(i - 1, SourceGridCols.单位).Text
                tmpGrid.Cell(i, DestBomGridCols.用量 + 1).Text = GrdSourceBom.Cell(i - 1, SourceGridCols.用量).Text
                tmpGrid.Cell(i, DestBomGridCols.使用位置 + 1).Text = GrdSourceBom.Cell(i - 1, SourceGridCols.使用位置).Text
                tmpGrid.Cell(i, DestBomGridCols.单价 + 1).Text = GrdSourceBom.Cell(i - 1, SourceGridCols.单价).Text
                tmpGrid.Cell(i, DestBomGridCols.单位总价 + 1).Text = GrdSourceBom.Cell(i - 1, SourceGridCols.用量).IntegerValue * GrdSourceBom.Cell(i - 1, SourceGridCols.单价).DoubleValue
            Next

            Try
                tmpGrid.ExportToExcel(fileDialog.FileName)
                MsgBox($"导出BOM至{fileDialog.FileName}完成！")
            Catch ex As Exception
                MsgBox($"导出BOM至{fileDialog.FileName}失败,{ex.Message}")
            End Try

        End Using
    End Sub

    Private Function GetPartFootPrintNum(footPrint As String) As String
        Dim result As New StringBuilder
        Dim findPoint As Boolean = False
        Dim findNum As Boolean = False

        If footPrint.Length = 0 Then Return footPrint
        For i = footPrint.Length - 1 To 0 Step -1
            Select Case footPrint(i)
                Case "0"c, "1"c, "2"c, "3"c, "4"c, "5"c, "6"c, "7"c, "8"c, "9"c
                    If findNum = False Then findNum = True
                    result.Insert(0, footPrint(i))
                Case "."c
                    If findNum = False Then Continue For '未查找到数字则忽略小数点
                    If findPoint Then Exit For '已添加小数点则退出搜索
                    If findPoint = False Then findPoint = True '变更状态为已添加小数点
                    result.Insert(0, footPrint(i))
                Case Else
                    If findNum = False Then Continue For '未查找到数字则继续寻找数字
                    Exit For '已找到数字则退出搜索
            End Select
        Next

        If findNum = False Then Return footPrint '未查找到数字则返回原字符串

        If result(0) = "."c Then result.Remove(0, 1) '小数点开头则移除小数点

        Return result.ToString
    End Function


    Private Function GetPartFootComment(footPrint As String) As String
        If footPrint.Length = 0 Then Return footPrint

        Select Case footPrint(footPrint.Length - 1)
            Case "R"c
                footPrint &= $",{footPrint.Replace("R"c, "Ω"c)}"
            Case "Ω"c
                footPrint &= $",{footPrint.Replace("Ω"c, "R"c)}"
        End Select

        Return footPrint
    End Function


    Private Sub QueuePart(partDesc As String)
        ' If String.IsNullOrWhiteSpace(partDesc) Then Return

        If partDesc.EndsWith(",") Then
            partDesc = partDesc.Remove(partDesc.Length - 1)
        End If

        QueryData_Quick(tb_PartNumber.Text, tb_Name.Text, partDesc, ckb_Pn_Inhaos.Checked, ckb_PnJohao.Checked)

        '初始化表格
        GrdQueueResult.DisplayRowNumber = True
        GrdQueueResult.AllowUserSort = True
        GrdQueueResult.DisplayFocusRect = False
        GrdQueueResult.ExtendLastCol = True
        GrdQueueResult.DisplayRowArrow = True
        GrdQueueResult.BoldFixedCell = False
        GrdQueueResult.SortIndicatorStyle = FlexCell.SortIndicatorStyleEnum.Light3D

        '将查询结果与表格绑定
        GrdQueueResult.SetDataBinding(m_Table, "", True, 1)

        GrdQueueResult.Column(QueueGridCols.规格描述).Width = 360
    End Sub

    Private Sub 查询ToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles 查询ToolStripMenuItem.Click
        If GrdSourceBom.ActiveCell Is Nothing Then Return
        Dim row As Integer = GrdSourceBom.ActiveCell.Row

        If Not m_Table Is Nothing Then
            m_Table.Dispose()
        End If
        m_Table = New DataTable

        '从数据库查询指定内容的物料信息
        Dim partComment As String = $"{GrdSourceBom.Cell(row, SourceGridCols.注释).Text.Trim}"

        Dim partFootPrint As String = $"{GrdSourceBom.Cell(row, SourceGridCols.型号).Text}"
        partFootPrint = GetPartFootPrintNum(partFootPrint)

        Dim partDesc As String = partComment

        If ChkHasPartType.Checked Then
            If partDesc.Length = 0 Then
                partDesc = partFootPrint
            Else
                If partFootPrint.Length > 0 Then partDesc &= $",{partFootPrint}"
            End If
        End If

        tb_Desc.Text = partDesc

        QueuePart(partDesc)
    End Sub

    Private Sub GrdSourceBom_DoubleClick(Sender As Object, e As EventArgs) Handles GrdSourceBom.DoubleClick
        If GrdSourceBom.ActiveCell Is Nothing Then Return
        Dim row As Integer = GrdSourceBom.ActiveCell.Row

        If Not m_Table Is Nothing Then
            m_Table.Dispose()
        End If
        m_Table = New DataTable

        '从数据库查询指定内容的物料信息
        Dim partComment As String = $"{GrdSourceBom.Cell(row, SourceGridCols.注释).Text.Trim.Replace(" "c, ","c).Replace("\", ",").Replace("/", ",")}"

        Dim partFootPrint As String = $"{GrdSourceBom.Cell(row, SourceGridCols.型号).Text}"
        partFootPrint = GetPartFootPrintNum(partFootPrint)

        Dim partDesc As String = partComment

        If ChkHasPartType.Checked Then
            If partDesc.Length = 0 Then
                partDesc = partFootPrint
            Else
                If partFootPrint.Length > 0 Then partDesc &= $",{partFootPrint}"
            End If
        End If

        tb_Desc.Text = partDesc

        QueuePart(partDesc)
    End Sub

    Private Sub bt_QueryQuick_Click(sender As Object, e As EventArgs) Handles bt_QueryQuick.Click
        QueuePart(tb_Desc.Text)
    End Sub

    Private Sub GrdQueueResult_DoubleClick(Sender As Object, e As EventArgs) Handles GrdQueueResult.DoubleClick
        If GrdSourceBom.ActiveCell Is Nothing Then Return

        If GrdSourceBom.Cell(GrdSourceBom.ActiveCell.Row, SourceGridCols.校验).BooleanValue Then Return

        GrdSourceBom.Cell(GrdSourceBom.ActiveCell.Row, SourceGridCols.校验).Text = ""
        GrdSourceBom.Cell(GrdSourceBom.ActiveCell.Row, SourceGridCols.工艺流程).Text = ""
        GrdSourceBom.Cell(GrdSourceBom.ActiveCell.Row, SourceGridCols.料号PN).Text = GrdQueueResult.Cell(GrdQueueResult.ActiveCell.Row, QueueGridCols.料号PN).Text
        GrdSourceBom.Cell(GrdSourceBom.ActiveCell.Row, SourceGridCols.物料名称).Text = GrdQueueResult.Cell(GrdQueueResult.ActiveCell.Row, QueueGridCols.物料名称).Text
        GrdSourceBom.Cell(GrdSourceBom.ActiveCell.Row, SourceGridCols.规格描述).Text = GrdQueueResult.Cell(GrdQueueResult.ActiveCell.Row, QueueGridCols.规格描述).Text
        GrdSourceBom.Cell(GrdSourceBom.ActiveCell.Row, SourceGridCols.单位).Text = GrdQueueResult.Cell(GrdQueueResult.ActiveCell.Row, QueueGridCols.单位).Text
        GrdSourceBom.Cell(GrdSourceBom.ActiveCell.Row, SourceGridCols.单价).Text = GrdQueueResult.Cell(GrdQueueResult.ActiveCell.Row, QueueGridCols.单重).Text
    End Sub

    Private Sub GrdSourceBom_CellChange(Sender As Object, e As FlexCell.Grid.CellChangeEventArgs) Handles GrdSourceBom.CellChange
        If e.Col = SourceGridCols.校验 Then
            If GrdSourceBom.Cell(e.Row, e.Col).BooleanValue = True Then
                GrdSourceBom.Range(e.Row, 1, e.Row, GrdSourceBom.Cols - 1).BackColor = Color.LightGreen

                GrdSourceBom.Range(e.Row, 1, e.Row, SourceGridCols.校验 - 1).Locked = True
                GrdSourceBom.Range(e.Row, SourceGridCols.校验 + 1, e.Row, GrdSourceBom.Cols - 1).Locked = True
            Else
                GrdSourceBom.Range(e.Row, 1, e.Row, GrdSourceBom.Cols - 1).BackColor = GrdSourceBom.BackColor1
                GrdSourceBom.Cell(e.Row, e.Col).BackColor = Color.LightBlue

                GrdSourceBom.Range(e.Row, 1, e.Row, SourceGridCols.校验 - 1).Locked = False
                GrdSourceBom.Range(e.Row, SourceGridCols.校验 + 1, e.Row, GrdSourceBom.Cols - 1).Locked = False
            End If
        End If
    End Sub

    Private Sub 保存至数据库ToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles 保存至数据库ToolStripMenuItem.Click
        If tbBomPN.Text.Length = 0 Then
            MsgBox("未指定当前BOM料号!")
            Return
        End If

        '检查输入料号是否有效
        Dim isExist As Boolean = False
        If m_PartNumber.CheckPartNumber(m_CurrentBomPN, isExist) = ERROR_CODE.SUCCESS Then
            If isExist = False Then
                MsgBox("输入料号不存在!")
                Return
            End If
        Else
            MsgBox("无法查询输入料号，请检查网络连接!")
            Return
        End If

        '检测内容中的PN字段有效性
        If CheckPNValid() = False Then
            MsgBox("输入信息存在错误，不能进行保存!")
            Return
        End If

        '创建料号表
        If SaveBomContext(tbBomPN.Text) = False Then
            MsgBox("保存料表失败")
            Return
        End If

        '保存临时表内容至XMl文件
        Try
            Dim dirPath As String = Application.StartupPath & "\" & "Context"
            IO.Directory.CreateDirectory(dirPath)
            GrdSourceBom.ExportToXML($"{dirPath}\{m_CurrentBomPN}_context_{Now:yyyyMMdd_HHmmss}.xml")
        Catch ex As Exception

        End Try

        MsgBox("保存料表:" & tbBomPN.Text & "成功")
    End Sub

    Private Sub 保存至数据库BOM表ToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles 保存至数据库BOM表ToolStripMenuItem.Click
        If tbBomPN.Text.Length = 0 Then
            MsgBox("未指定当前BOM料号!")
            Return
        End If

        '检查输入料号是否有效
        Dim isExist As Boolean = False
        If m_PartNumber.CheckPartNumber(m_CurrentBomPN, isExist) = ERROR_CODE.SUCCESS Then
            If isExist = False Then
                MsgBox("输入料号不存在!")
                Return
            End If
        Else
            MsgBox("无法查询输入料号，请检查网络连接!")
            Return
        End If

        '检测内容中的PN字段有效性
        If CheckPNValid() = False Then
            MsgBox("输入信息存在错误，不能进行保存!")
            Return
        End If

        '创建料号表
        If SaveBom2(tbBomPN.Text) = False Then
            MsgBox("保存料表失败")
            Return
        End If

        MsgBox("保存料表:" & tbBomPN.Text & "成功")
    End Sub

    Private Sub 更新当前物料ToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles 更新当前物料ToolStripMenuItem.Click
        If GrdSourceBom.ActiveCell Is Nothing Then Return

        Dim row As Integer = GrdSourceBom.ActiveCell.Row
        If row = 0 Then Return

        Dim pn As String
        '清空内容
        GrdSourceBom.Cell(row, SourceGridCols.物料名称).Text = ""
        GrdSourceBom.Cell(row, SourceGridCols.规格描述).Text = ""
        GrdSourceBom.Cell(row, SourceGridCols.单位).Text = ""
        GrdSourceBom.Cell(row, SourceGridCols.单价).Text = ""

        '查询指定pn的信息
        pn = GrdSourceBom.Cell(row, SourceGridCols.料号PN).Text
        If String.IsNullOrEmpty(pn) Then Return

        Dim pninfo As New PnInfo With {.PN = pn}

        If GetPnInfoByName(pn, pninfo) Then
            GrdSourceBom.Cell(row, SourceGridCols.物料名称).Text = pninfo.物料名称
            GrdSourceBom.Cell(row, SourceGridCols.规格描述).Text = pninfo.规格描述
            GrdSourceBom.Cell(row, SourceGridCols.单位).Text = pninfo.单位
            GrdSourceBom.Cell(row, SourceGridCols.单价).Text = pninfo.单重
        End If
    End Sub

    Private Sub 更新物料信息ToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles 更新物料信息ToolStripMenuItem.Click
        GetAllPnInfo()
    End Sub

    Private Sub GetAllPnInfo()
        Dim pn As String
        For row = 1 To GrdSourceBom.Rows - 1
            '注释为空后面则认为为无效行
            If String.IsNullOrEmpty(GrdSourceBom.Cell(row, SourceGridCols.注释).Text) Then
                If String.IsNullOrEmpty(GrdSourceBom.Cell(row, SourceGridCols.料号PN).Text) Then
                    Continue For
                End If
            End If

            '清空内容
            GrdSourceBom.Cell(row, SourceGridCols.物料名称).Text = ""
            GrdSourceBom.Cell(row, SourceGridCols.规格描述).Text = ""
            GrdSourceBom.Cell(row, SourceGridCols.单位).Text = ""
            GrdSourceBom.Cell(row, SourceGridCols.单价).Text = ""

            '查询指定pn的信息
            pn = GrdSourceBom.Cell(row, SourceGridCols.料号PN).Text
            If String.IsNullOrEmpty(pn) Then Continue For

            Dim pninfo As New PnInfo With {.PN = pn}

            If GetPnInfoByName(pn, pninfo) Then
                GrdSourceBom.Cell(row, SourceGridCols.物料名称).Text = pninfo.物料名称
                GrdSourceBom.Cell(row, SourceGridCols.规格描述).Text = pninfo.规格描述
                GrdSourceBom.Cell(row, SourceGridCols.单位).Text = pninfo.单位
                GrdSourceBom.Cell(row, SourceGridCols.单价).Text = pninfo.单重
            End If
        Next
    End Sub


    Private Function GetPnInfoByName(pn As String, ByRef pnInfo As PnInfo) As Boolean
        Return m_PartNumber.QueryItem(pn, pnInfo.物料名称, pnInfo.规格描述, pnInfo.单位, pnInfo.单重, pnInfo.供应商ID) = ERROR_CODE.SUCCESS
    End Function

    Public Class PnInfo
        Public PN As String = ""

        Public 物料名称 As String = ""
        Public 规格描述 As String = ""
        Public 单位 As String = ""
        Public 单重 As Double = 0
        Public 图片(0) As Byte
        Public 供应商ID As String = ""
    End Class

    Private Sub 插入行ToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles 插入行ToolStripMenuItem.Click
        If GrdSourceBom.Selection Is Nothing Then
            GrdSourceBom.AddItem("")
        Else
            GrdSourceBom.InsertRow(GrdSourceBom.Selection.FirstRow, 1)
        End If

    End Sub

    Private Sub 删除行ToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles 删除行ToolStripMenuItem.Click
        If MsgBox("是否删除选中行?", MsgBoxStyle.OkCancel) <> MsgBoxResult.Ok Then Return
        If GrdSourceBom.Selection IsNot Nothing Then
            GrdSourceBom.Selection.DeleteByRow()
        End If
    End Sub

    Private Sub 清空表格ToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles 清空表格ToolStripMenuItem.Click
        If MsgBox("是否清空表格?", MsgBoxStyle.OkCancel) <> MsgBoxResult.Ok Then Return

        InitSourceGrid()
    End Sub

    Private Sub 合并相同料号ToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles 合并相同料号ToolStripMenuItem.Click
        Dim snList As New Dictionary(Of String, Integer)
        Dim deleteRows As New List(Of Integer)
        ' 查询所有料号
        Dim pn As String
        For row = 1 To GrdSourceBom.Rows - 1
            pn = GrdSourceBom.Cell(row, SourceGridCols.料号PN).Text
            If String.IsNullOrEmpty(pn) Then Continue For

            If snList.ContainsKey(pn) Then
                deleteRows.Add(row)

                GrdSourceBom.Cell(snList(pn), SourceGridCols.用量).Text = GrdSourceBom.Cell(snList(pn), SourceGridCols.用量).IntegerValue + GrdSourceBom.Cell(row, SourceGridCols.用量).IntegerValue


                GrdSourceBom.Cell(snList(pn), SourceGridCols.使用位置).Text = GrdSourceBom.Cell(snList(pn), SourceGridCols.使用位置).Text & "," & GrdSourceBom.Cell(row, SourceGridCols.使用位置).Text
            Else
                snList.Add(pn, row)
            End If
        Next

        For row = 0 To deleteRows.Count - 1
            GrdSourceBom.Row(deleteRows(row) - row).Delete()
        Next
    End Sub

End Class