用vb做erp最郁闷的是没有大量录入数据的控件,在这里我们采用mshflexgrid录入与显示数据。默认情况下mshflexgrid是不能录入数据的,所以我们得借助点东西:文本框。我们在这里称之为:浮动文本框。
原理是这样的:(模仿execel的实现)
当我们双击时进入编辑模式,这时候让浮动文本框,显示出来(调用Show_txtFloat),用户输入的数据会保存到txtfloat里面。当用户输入结束的时候会在表格其他地方单击一下,这是我们将浮动文本框隐藏起来(调用Hide_txtFloat,这个函数会将txtfloat里面的数据保存到mshflexgrid里面)。
下面看这两个函数的代码:
Public Sub Show_txtFloat() txtFloat.Visible = False txtFloat.Width = mGrid.CellWidth txtFloat.Height = mGrid.CellHeight txtFloat.Left = mGrid.Left + mGrid.CellLeft - 10 txtFloat.Top = mGrid.Top + mGrid.CellTop - 10 txtFloat.Text = mGrid.TextMatrix(mGrid.Row, mGrid.Col) txtFloat.SelStart = Len(txtFloat.Text) txtFloat.Visible = True txtFloat.SetFocus End Sub Public Sub Hide_txtFloat() If txtFloat.Visible = True Then mGrid.TextMatrix(mGrid.Row, mGrid.Col) = txtFloat.Text txtFloat.Text = "" txtFloat.Visible = False End If End Sub
那肯定有人说了,我总不能想输入数据的时候每次都双击吧,那多麻烦。对的,我们看看excel的实现,直接按普通键会有什么反应。在这里我们得在mshflexgrid的keypress做文章了。
Private Sub mGrid_KeyPress(KeyAscii As Integer) If txtFloat.Visible = False And KeyAscii <> vbKeyDown And KeyAscii <> vbKeyUp And KeyAscii <> vbKeyLeft And KeyAscii <> vbKeyRight And KeyAscii <> vbKeyReturn Then Show_txtFloat txtFloat.Text = Chr(KeyAscii) txtFloat.SelStart = Len(txtFloat) End If End Sub
我的mshflexgrid取名叫mGrid。
大家看到了,如果是下上左右以及tab,enter我都让它没反应。这些键的处理在下面。
Private Sub mGrid_KeyDown(KeyCode As Integer, Shift As Integer) Select Case KeyCode Case vbKeyTab If mGrid.Col <= mGrid.cols - 1 Then mGrid.Col = mGrid.Col + 1 ElseIf mGrid.Row < mGrid.rows - 1 Then mGrid.Row = mGrid.Row + 1 mGrid.Col = 1 End If mGrid.SetFocus Case vbKeyReturn If mGrid.Row < mGrid.rows - 1 Then mGrid.Row = mGrid.Row + 1 mGrid.SetFocus Case vbKeyBack Show_txtFloat txtFloat.Text = "" Case 46 MSGrid_Clear mGrid End Select End Sub
上下左右,默认mshflexgrid会处理的,在这里就不需要处理了。
还有一点,如果用户正在编辑模式下,按下上下左右等等怎么处理呢?
Private Sub txtFloat_KeyDown(KeyCode As Integer, Shift As Integer) Dim PageRows As Integer PageRows = mGrid.Height / mGrid.CellHeight Select Case KeyCode Case vbKeyDown, vbKeyReturn '下箭头 Hide_txtFloat If mGrid.Row < mGrid.rows - 1 Then mGrid.Row = mGrid.Row + 1 mGrid.SetFocus Case vbKeyUp '上箭头 Hide_txtFloat If mGrid.Row > 1 Then mGrid.Row = mGrid.Row - 1 mGrid.SetFocus Case vbKeyLeft '左箭头 If GetCaretPos(txtFloat) <> 0 Then Exit Sub Hide_txtFloat If mGrid.Col <> 1 Then mGrid.Col = mGrid.Col - 1 ElseIf mGrid.Row > 1 Then mGrid.Row = mGrid.Row - 1 mGrid.Col = mGrid.cols - 1 End If mGrid.SetFocus Case vbKeyRight '右箭头 If GetCaretPos(txtFloat) < Len(Trim(txtFloat)) Then Exit Sub Hide_txtFloat If mGrid.Col <= mGrid.cols - 1 Then mGrid.Col = mGrid.Col + 1 ElseIf mGrid.Row < mGrid.rows - 1 Then mGrid.Row = mGrid.Row + 1 mGrid.Col = 1 End If mGrid.SetFocus End Select End Sub
到这里,按键的处理基本上完成了。还有点东西要处理,复制、粘贴、剪切,等怎么处理呢。看我封装的函数。在菜单中调用就ok了。
Public Sub MSGrid_AddLine(mGrid As MSHFlexGrid) '#################################################################### '往mshflexgrid里面添加一行 '#################################################################### mGrid.AddItem "", mGrid.Row End Sub Public Sub MSGrid_DelLine(mGrid As MSHFlexGrid) '#################################################################### 'mshflexgrid里面删除一行 '#################################################################### Dim beginRow%, endRow% '定义起始行列 With mGrid beginRow = IIf(.Row < .RowSel, .Row, .RowSel) endRow = IIf(.Row > .RowSel, .Row, .RowSel) If .rows <= 2 Then MsgBox "只有一行数据不能删除 ", vbInformation, G_ERPWindowsName Exit Sub End If For i = endRow To beginRow Step -1 If i = 1 Then Exit Sub .RemoveItem i Next i For i = 1 To .rows - 1 .TextMatrix(i, 0) = i Next i End With End Sub Public Sub MSGrid_Copy(mGrid As MSHFlexGrid) '#################################################################### 'mshflexgrid里面复制一行 '#################################################################### Dim str As String Clipboard.clear str = mGrid.Clip & Chr(13) Clipboard.SetText str, vbCFText End Sub Public Sub MSGrid_Paste(mGrid As MSHFlexGrid) '#################################################################### 'mshflexgrid里面粘贴一行 '#################################################################### Dim temp As String Dim beginRow As Integer Dim beginCol As Integer Dim endRow As Integer Dim endCol As Integer Dim rows As Integer '选区行数 Dim cols As Integer '选区列数 Dim i As Integer Dim itab As Integer 'tab键个数 Dim ienter As Integer 'enter键个数 temp = Clipboard.GetText If (Len(temp) = 0) Then Exit Sub End If For i = 1 To Len(temp) If Mid(temp, i, 1) = Chr(vbKeyReturn) Then ienter = ienter + 1 End If If Mid(temp, i, 1) = Chr(vbKeyTab) Then itab = itab + 1 End If Next i If Mid(temp, Len(temp), 1) = Chr(10) Then rows = ienter Else rows = ienter + 1 End If cols = itab / rows beginRow = IIf(mGrid.Row < mGrid.RowSel, mGrid.Row, mGrid.RowSel) beginCol = IIf(mGrid.Col < mGrid.ColSel, mGrid.Col, mGrid.ColSel) endRow = IIf(mGrid.Row > mGrid.RowSel, mGrid.Row, mGrid.RowSel) endCol = IIf(mGrid.Col > mGrid.RowSel, mGrid.Col, mGrid.ColSel) If Abs(mGrid.RowSel - mGrid.Row) < rows Then beginRow = IIf(mGrid.Row < mGrid.RowSel, mGrid.Row, mGrid.RowSel) If mGrid.rows < beginRow + rows Then '需要增行 mGrid.rows = beginRow + rows End If endRow = beginRow + rows - 1 End If If Abs(mGrid.ColSel - mGrid.Col) < cols Then beginCol = IIf(mGrid.Col < mGrid.ColSel, mGrid.Col, mGrid.ColSel) If mGrid.cols < beginCol + cols + 1 Then '超过最大列数 endCol = mGrid.cols - 1 Else endCol = beginCol + cols End If End If mGrid.Row = beginRow mGrid.Col = beginCol mGrid.RowSel = endRow mGrid.ColSel = endCol mGrid.Clip = Clipboard.GetText End Sub Public Sub MSGrid_Cut(mGrid As MSHFlexGrid) '#################################################################### 'mshflexgrid里面剪切一行 '#################################################################### MSGrid_Copy mGrid MSGrid_Clear mGrid End Sub Public Sub MSGrid_Clear(mGrid As MSHFlexGrid) '#################################################################### 'mshflexgrid里面剪切一行 '#################################################################### With mGrid For i = IIf(.Row < .RowSel, .Row, .RowSel) To IIf(.Row > .RowSel, .Row, .RowSel) For j = IIf(.Col < .ColSel, .Col, .ColSel) To IIf(.Col > .ColSel, .Col, .ColSel) .TextMatrix(i, j) = "" Next j Next i End With End Sub Public Sub MSGrid_Repeat(mGrid As MSHFlexGrid) '#################################################################### 'mshflexgrid里面剪切一行 '#################################################################### Dim i As Integer Dim j As Integer With mGrid For i = IIf(.Row < .RowSel, .Row, .RowSel) To IIf(.Row > .RowSel, .Row, .RowSel) For j = IIf(.Col < .ColSel, .Col, .ColSel) To IIf(.Col > .ColSel, .Col, .ColSel) .TextMatrix(i, j) = .TextMatrix(IIf(.Row < .RowSel, .Row, .RowSel), IIf(.Col < .ColSel, .Col, .ColSel)) Next j Next i End With End Sub Public Sub MSGrid_Increase(mGrid As MSHFlexGrid) '#################################################################### 'mshflexgrid里面剪切一行 '#################################################################### Dim beginRow As Integer Dim beginCol As Integer Dim start As Integer Dim gap As Integer Dim j As Integer With mGrid If .Row = .RowSel And .Col = .ColSel Then Exit Sub End If If .Row <> .RowSel And .Col <> .ColSel Then Exit Sub End If beginRow = IIf(.Row < .RowSel, .Row, .RowSel) beginCol = IIf(.Col < .ColSel, .Col, .ColSel) start = Val(.TextMatrix(beginRow, beginCol)) If .Row = .RowSel Then gap = Val(.TextMatrix(beginRow, beginCol + 1)) - Val(.TextMatrix(beginRow, beginCol)) For j = IIf(.Col < .ColSel, .Col, .ColSel) + 1 To IIf(.Col > .ColSel, .Col, .ColSel) .TextMatrix(.Row, j) = Val(.TextMatrix(.Row, j - 1)) + gap Next j ElseIf .Col = .ColSel Then gap = Val(.TextMatrix(beginRow + 1, beginCol)) - Val(.TextMatrix(beginRow, beginCol)) For j = IIf(.Row < .RowSel, .Row, .RowSel) + 1 To IIf(.Row > .RowSel, .Row, .RowSel) .TextMatrix(j, .Col) = Val(.TextMatrix(j - 1, .Col)) + gap Next j End If End With End Sub Public Sub MSGrid_SelectAll(mGrid As MSHFlexGrid) '#################################################################### 'mshflexgrid里面剪切一行 '#################################################################### Dim endRow As Integer Dim endCol As Integer endRow = 1 endCol = 1 mGrid.Row = 1 mGrid.Col = 1 For i = 1 To mGrid.rows - 1 For j = 1 To mGrid.cols - 1 If mGrid.TextMatrix(i, j) <> "" Then If endRow < i Then endRow = i If endCol < j Then endCol = j End If Next j Next i mGrid.RowSel = endRow mGrid.ColSel = endCol End Sub
这个里面就粘贴代码长点。原因是excel复制出来的东西比mshflexgrid本身复制出来的东西多一个enter+shift键吧,所以得讨论下。mGrid.Clip = Clipboard.GetText 是核心代码,它能将粘贴板上的东西粘贴到mshflexgrid上,不过它只粘贴你选中的mshflexgrid单元格,超出的部分不管,我做了一点增强。
在我的程序里是不允许改变列数的,所以你要是用可能得改改。增行就是插入一行。重复就是在后面的选中的单元格中填入第一个单元格的内容。递增不用说了吧,试试。
到这里我想普通的excel应用就能完成了。