查询工程定额数据并自动输入到工作表

前两天接到panpanluo的问题

  • 要求将一个名为“93定额库.xls”的工作簿中的数据,根据选取的定额类别导入到自定义用户窗体中,然后在窗体中可实现查询,能找到并选择相应的定额条目,然后输入到另一个工作簿的计算工作表中。在他提供的用户窗体中,主要的两的控件是TreeView控件和ListView控件。

花了一些时间对其需求进行了研究,根据自已的理解,初步解决了这个问题(当然,细节问题肯定还存在,再作些修改即可)。
下面,将自已解决问题过程中的一些想法和思路记录在此,以供以后参考。
一、工作表中数据结构的设计很重要,特别是对于有大量数据的工作簿,有规律的数据结构不仅有助于代码的编写和扩展,而且也便于理解。
在本例中,因为是涉及到工程定额数据,数据量肯定很大,幸好这些数据的编排和层次结构很合理,因而编写程序对其处理很方便。
建议:在编写程序对数据进行处理之前,尽量使数据规范,有规律,或者对数据进行整理,使其尽可能规范,特别是对于大量的数据,更应如此。这里说的结构规范,不仅仅是对于要处理的工作表,而且还包括接受输入数据的工作表。
二、实现目的有多种方法,尽量使用自已熟悉的方法和工具。
本例中,我在用户窗体中使用了列表框控件,而没有使用ListView控件。如图:
dejm
界面中,包含一个用于选取定额类型的组合框、一个用于搜索的文本框、一个TreeView控件、一个列表框和五个按钮。
三、程序思路
1、整理工作表中的数据,正如上面所述,规范的数据便于程序实现,也会使代码更少。本例中,将工作簿“93定额库.xls”中的各工作表中的定额数据进行整理,主要是提取父节点和相应的子节点,以方便用于TreeView控件中。
下面的程序是一个通用程序,能方便地将整理后的数据填充到TreeView控件中。稍作修改,就能用于其他情形。
Sub treeViewPopulate()
    Dim i           As Long
    Dim j           As Long
    Dim xNode       As Node
    Dim NodeKey     As String
    Dim objWks      As Worksheet
   
    Set objWks = Workbooks(”93定额库.xls”).Sheets(strWksName)
    j = objWks.Range(”A65536″).End(xlUp).Row
    With Me.TreeList
        ‘第一层次的节点
        For i = 2 To j
            Set xNode = .Nodes.Add
            NodeKey = objWks.Range(”A” & i).Text
            With xNode
                .Key = NodeKey
                .Text = NodeKey
                .Expanded = False
            End With
        Next i
        j = objWks.Range(”C65536″).End(xlUp).Row
        ‘其他节点
        For i = 2 To j
           Set xNode = .Nodes.Add(objWks.Range(”B” & i).Text, tvwChild)
            NodeKey = objWks.Range(”C” & i).Text
            With xNode
                .Key = NodeKey
                .Text = NodeKey
            End With
        Next i
    End With
   
    Set xNode = Nothing
    Set objWks = Nothing
End Sub
2、填充列表框,因为数据是一个区域,所以很方便地将数据填充到列表框中。如本例中的过程Sub listBoxPopulate()。
3、实现TreeView控件和列表框中的控件相交关联。
Private Sub TreeList_NodeClick(ByVal Node As MSComctlLib.Node)过程用于在单击TreeView控件中的相应节点后,在列表框中显示对应的节点内容。由于选中某节点后,其对应的节点内容在列表框中总会出现在列表框的最下部,因此,本过程使用了一个小小的技巧,即在列表框中先选取要选择的节点的下一个节点,再选取要选择的节点,因为列表框默认一次只能选择一项,因此将要选择的节点内容上移,使项目能看清楚。
注:在使用循环时,一定要注意最开始和最末尾的循环变量,防止超出变量的范围。
Private Sub listBoxHandle_Click()过程用于单击列表框中相应的项目后,TreeView控件中相应的节点显示。
实际上,这两个控件是独立的,在这里只是通过工作表中的相应数据进行关联,即工作表是中间人。
4、实现搜索。当然,搜索到一项很容易,但要进行连续搜索则稍复杂一些。连续搜索的目的是能找到包括搜索文本的所有项。使用了一个通用的搜索程序:
Function FindAll(SearchRange As Range, FindWhat As Variant, _
    Optional LookIn As XlFindLookIn = xlValues, Optional LookAt As XlLookAt = xlWhole, _
    Optional SearchOrder As XlSearchOrder = xlByRows, _
    Optional MatchCase As Boolean = False) As Range
”””””””””””””””””””””””””””””””””””””””””””””
‘ 返回SearchRange区域中含有FindWhat所代表的值的所有单元格组成的Range对象
‘ 其参数与Find方法的参数相同
‘ 如果没有找到单元格,将返回Nothing.
”””””””””””””””””””””””””””””””””””””””””””””
  Dim FoundCell As Range
  Dim FoundCells As Range
  Dim LastCell As Range
  Dim FirstAddr As String
  With SearchRange
    Set LastCell = .Cells(.Cells.Count)
  End With
  Set FoundCell = SearchRange.Find(what:=FindWhat, after:=LastCell, _
    LookIn:=LookIn, LookAt:=LookAt, SearchOrder:=SearchOrder, MatchCase:=MatchCase)
  If Not FoundCell Is Nothing Then
    Set FoundCells = FoundCell
    FirstAddr = FoundCell.Address
    Do
      Set FoundCells = Application.Union(FoundCells, FoundCell)
      Set FoundCell = SearchRange.FindNext(after:=FoundCell)
    Loop Until (FoundCell Is Nothing) Or (FoundCell.Address = FirstAddr)
  End If
  If FoundCells Is Nothing Then
    Set FindAll = Nothing
  Else
    Set FindAll = FoundCells
  End If
End Function
该程序能够在指定的区域中找到满足条件的所有单元格,因而为连续搜索提供了基础。
此时,注意搜索到相应的项目后,在列表框中选中搜索到的项目,同时TreeView控件中的节点相应扩展显示。
5、其他。选中组合框中的项目后,在TreeView控件和列表框控件中出现对应的项目。单击“展开”按钮,将展开TreeView控件中所有节点,单击“收起”按钮则折叠所有节点。“输入到计算表”将组合框和列表框中的相应数据输入到“计算表”对应的单元格中。
四、一些注意事项
1、注意,考虑在各控件中没有相应输入时的情形,如果没有输入而执行搜索或单击按钮操作,则会出现错误。
2、注意,本例是两个工作簿相互操作,最终一个工作簿获取另一个工作簿中的数据,因此两个工作簿要同时打开,并且两个工作簿都要处于同一进程中(即在同一Excel界面中打开,而不能再开启一次Excel应用程序后打开另一工作簿)。
3、何时激活相应的工作簿,应注意,否则会出现奇怪的现象─—列表框中没有数据,是空白的,但可以选择。
4、在使用附加控件时,最好也选中“引用”对话框中“Microsoft Windows Common Controls(SP6)”前的复选框。如果在“引用”对话框中找不到该选项,则应安装。
5、此外,对于循环结构,在完成(达到)目的后,即退出循环。对于对象变量,在使用完后,记得释放变量。
原问题及附件见(我的回答也在这个贴子里)http://club.excelhome.net/dispbbs.asp?boardid=2&replyid=1232490&id=302386&page=2&skin=0&Star=2
也可以在下面的链接中下载解答:点此下载

需求者根据别人的提示,并融合了各种功能,加上自已的设计,最终得出了很好的实用效果,然后拿出来与大家分享!请见:http://club.excelhome.net/dispbbs.asp?boardID=2&ID=306173&page=1&px=0


提示:您可以在评论中使用HTML标签,且任何与HTML标签相同的符号都会被理解为HTML标签并以相应的格式显示.如果您的评论中有代码,可以使用相应的标签,例如,如果有VB或VBA代码,则可以使用[vb]标签,即[vb]放置的代码[/vb],这样会很清晰地显示代码.

发表评论