在给定标题下计算非空白单元格

时间:2014-03-27 20:53:19

标签: excel vba excel-vba

我有一个很大的类似报告列表,这些报告在第一列中都有一个“Name:”单元格,并列出了一组对象,比如同一列中的“对象”。在字符串“Name:”的两个实例和其间的一些其他行(空白和填充)之后,我们到达“Objects”字符串。在“对象”一词的每个实例之后,有一个数字列表,用于计算对象的总数。每个列表中有任意数量的对象,但它们总是位于标题“对象”之后的事实是不变的。是否有一种简单的方法可以让Excel搜索每个报告,并将名称下的名称放在某个单元格中,并在其旁边的“对象”一词后面显示所有非空白单元格的数量?由于对象列表是完整的,因此第一个空白单元格可以触发计数停止并移动到下一个列表,而大量空白单元格(例如超过300个)可以触发程序声明不再有条目退出并停止。)

示例

    A              B           C

    Name:      John Smith


    Date:       March 5th

    Name:       John Smith

   Objects
    List 
      1            Filler1     Something1
      2            Filler2     Something2
      3            Filler3     Something3
      4            Filler4     Something4
      5            Filler5     Something5
      6            Filler6     Something6

    Name:      Jane Doe


    Date:       March 8th

    Name:       Jane Doe

   Objects
    List 
      1            Filler1     Something1
      2            Filler2     Something2
      3            Filler3     Something3
      4            Filler4     Something4

结果将是:

    John Smith         6
    Jane Doe           4

1 个答案:

答案 0 :(得分:1)

修订4/3:更改对象名称;改变案例;在4/2再次修订:搜索特定类型的对象;修订4/2;首先跳过'名字';如果达到最大值则结束循环(输入格式问题!) 修订4/1;添加错误陷阱&线#找到错误。有助于看到用户输入。请参阅代码中的注释。

    Option Explicit
' Assumptions:
' (1) All data in first column - except for name.
' (2) The literal 'Name:' will be in Col A; The name (i.e. 'John Doe') will be in Col B.
' (3) The same 'Name' will appear twice, with a 'Date' row between the two.
' (4) May be blank row(s) anywhere before or after row containing 'Name'.
' (5) 'Object' row will have string starting with 'Objects' in Col A, followed by Object Name (i.e. 'Objects Cars')
' (6) 'Object' row may repeat for ONE name.
' (7) Search for user specified Object in list for a Name. Set to zero if not found
' (8) Name will be repeated many times in the column (>100,000 rows).

' For test purposes, I have used 'Sheet1' as report sheet, and 'Sheet2' as output.
' Can change to process ALL sheets in a workbook (not sure how your reports are found (.. sheets or workbooks..)

Sub Create_Summary()
Dim lLastRow    As Long
Dim lRow        As Long
Dim lOutRow     As Long
Dim lNameRow    As Long

Dim sName       As String
Dim iNameCtr    As Integer
Dim lRowCt      As Long
Dim blnSkip     As Boolean
Dim strObjName  As String
Dim strObjKey  As String
Dim strObjNameFound As String

1000  On Error GoTo Error_Trap

'Get last used row
1010  lLastRow = Cells.Find(What:="*", After:=Range("A1"), SearchOrder:=xlByRows, SearchDirection:=xlPrevious).row
1020  Debug.Print "Total Rows: " & lLastRow

1030  strObjKey = "Objects"     ' <<<<<<< Add code to obtain and set to whatever you want.
1040  strObjName = "Cars"     ' <<<<<<< Add code to obtain and set to whatever you want.

1050  lOutRow = 1
1060  blnSkip = False
1070  For lRow = 1 To lLastRow
1080      iNameCtr = 0
1090      lRowCt = 0
1100     Do Until iNameCtr = 2 Or lRow >= lLastRow    'Trim(Cells(lRow, 1)) = "Name:" Or lRow >= lLastRow      ' Find 'Name'
1110          If Trim(Cells(lRow, 1)) = "Name:" Then
1120              iNameCtr = iNameCtr + 1
1130              lNameRow = lRow
1140          End If
1150          lRow = lRow + 1
1160       Loop
1170      lRow = lRow - 1
1180      If lRow >= lLastRow - 1 Then Exit For
1190      If blnSkip = True Then
1200         sName = Cells(lRow, 2)            ' Name is in Col 2
1210         Debug.Print "Row: " & lRow & vbTab & ">> Name: " & sName
1220         Sheets("Sheet2").Range("A" & lOutRow) = sName      ' Save Name
            ' There will always be a non-blank row after 'Name' do not count that!
1230         lRow = lRow + 1
1240         Do Until LCase(Left(Cells(lRow, 1), 7)) = LCase(strObjKey) And InStr(8, LCase(Cells(lRow, 1)), LCase(strObjName)) > 0    ' Find 'Object'
1250             lRow = lRow + 1
1260             If LCase(Trim(Cells(lRow, 1))) = LCase("Name:") Then     ' Means never found desired 'Objects'
1270                 Sheets("Sheet2").Range("B" & lOutRow) = 0
1280                 lRow = lRow - 1
1290                 lOutRow = lOutRow + 1
1295                 GoTo Next_Row
1300             ElseIf lRow > lLastRow Then
1310                 Sheets("Sheet2").Range("B" & lOutRow) = lRowCt
1320                 Debug.Print "**** Exit because at end of used range!"
'134                 MsgBox "Found name: '" & sName & "' at row " & lNameRow & ", but there was no matching 'Objects'", vbOKOnly, "Sheet Format Incorrect"
1330                 Exit For
1340             End If
1350         Loop
1360         Debug.Print "Row: " & lRow & vbTab & ">> " & strObjKey & ": " & Cells(lRow, 1)
1370         strObjNameFound = Trim(Mid(Cells(lRow, 1), 8, 99))
1380         lRow = lRow + 2   ' Must skip a 'filler' line after 'Objects'

1390         Do Until Cells(lRow, 1) = "" Or LCase(Left(Cells(lRow, 1), 7)) = LCase(strObjKey) Or lRow >= lLastRow      ' Find Blank line
1400             If Cells(lRow, 1) <> "" Then
1410                 lRowCt = lRowCt + 1   ' Count Rows associated with Object
1420             End If
1430             lRow = lRow + 1
1440         Loop
1450         Debug.Print "Row: " & lRow & vbTab & "# " & strObjKey & ": " & lRowCt
1460         Sheets("Sheet2").Range("B" & lOutRow) = lRowCt
1470         Sheets("Sheet2").Range("C" & lOutRow) = strObjNameFound
1480         lOutRow = lOutRow + 1
1490     Else
1500         blnSkip = True
1510         lRow = lRow + 1
1520     End If
Next_Row:
1530  Next lRow

1540  Exit Sub

Error_Trap:
    Debug.Print Err.Number & vbTab & Err.Description & vbCrLf & _
            "At Line: " & Erl & vbCrLf & _
            "lLastRow = " & lLastRow & vbTab & "lRow = " & lRow
    MsgBox "Error: " & Err.Number & vbTab & Err.Description & vbCrLf & "At Line: " & Erl & vbCrLf & _
            "lLastRow = " & lLastRow & vbTab & "lRow = " & lRow
    Exit Sub
End Sub