范围。找不到现有值

时间:2018-11-29 17:17:01

标签: excel vba

我正在尝试构建一个宏,该宏循环遍历工作簿中的每个工作表,并记录每个工作表所涉及的“帐单区域”以及每个工作簿中的一些其他信息。我的程序适用于第一个工作表,但不适用于第二个工作表。我正在搜索的是相同的标准化文本,但是Range.Find无法正常工作。这是代码:

Sub DenialsReport()

Dim heatWB, denialWB As Workbook
Dim heatWS, denialWS As Worksheet
Dim folderName, fileName, extName, wbName, billArea, postPeriod As String
Dim a, b, lastRow, countCol, volumeCol, startRow, billAreaRow, billAreaColumn, grandRow As Long
Dim postPeriodRange, billAreaRange, grandRange As Range

Set heatWB = ActiveWorkbook
Set heatWS = heatWB.Sheets("Denials")

postPeriod = InputBox("Please enter the current post period in this form: yyyymm")

Application.ScreenUpdating = False

folderName = heatWB.Sheets("Support->").Cells(19, 3).Value
fileName = heatWB.Sheets("Support->").Cells(20, 3).Value
extName = heatWB.Sheets("Support->").Cells(21, 3).Value
wbName = folderName + "\" + fileName + "." + extName

Set denialWB = Workbooks.Open(wbName)

b = 0

For Each denialWS In Worksheets

    denialWS.Cells.UnMerge

Next denialWS

For Each denialWS In Worksheets

    b = b + 1
    denialWB.Sheets(b).Cells.UnMerge
    lastRow = heatWS.Cells(Rows.Count, 1).End(xlUp).Row + 1

    ' find the bill area
    Set billAreaRange = denialWB.Sheets(b).Range("A1:G10").Find(What:="For Bill Area: ", LookIn:=xlValues, LookAt:=xlPart, MatchCase:=False)
    billAreaRow = billAreaRange.Row
    billAreaColumn = billAreaRange.Column

    ' get the bill area
    billArea = denialWB.Sheets(b).Cells(billAreaRow, billAreaColumn).Value
    billArea = Replace(billArea, "For Bill Area: ", "")
    billArea = Left(billArea, InStr(billArea, "(") - 1)
    billArea = Trim(billArea)

    ' locate the count and amount columns along with the start and end of the rejection categories
    Set postPeriodRange = d enialWB.Sheets(denialWS.Index).Range("A1:AZ15").Find(What:=postPeriod, LookIn:=xlValues, LookAt:=xlWhole)
    countCol = postPeriodRange.Column
    amountCol = countCol + 1
    startRow = postPeriodRange.Row + 2
    Set grandRange = denialWB.Sheets(denialWS.Index).Range("A:A").Find(What:="Grand Total",    LookIn:=xlValues, LookAt:=xlWhole)
    grandRow = grandRange.Row

    ' copy the information over to heatWS
    For a = startRow To grandRow - 1
        heatWS.Cells(lastRow, 1).Value = billArea
        heatWS.Cells(lastRow, 2).Value = postPeriod
        heatWS.Cells(lastRow, 3).Value = denialWS.Cells(a, 1).Value
        heatWS.Cells(lastRow, 4).Value = denialWS.Cells(a, countCol).Value
        heatWS.Cells(lastRow, 5).Value = denialWS.Cells(a, amountCol).Value
        heatWS.Cells(lastRow, 6).Value = denialWS.Cells(a, amountCol).Value /    denialWS.Cells(grandRow, amountCol).Value
        lastRow = heatWS.Cells(Rows.Count, 1).End(xlUp).Row + 1
    Next a

Next denialWS

denialWB.Close SaveChanges:=False

heatWS.Range("A:F").AutoFit

Application.ScreenUpdating = True

End Sub

此行出现问题:

Set billAreaRange = denialWB.Sheets(b).Range("A1:G10").Find(What:="For Bill Area: ", LookIn:=xlValues, LookAt:=xlPart, MatchCase:=False) 

我还尝试过像这样对程序进行硬编码(值位于单元格C7中):

billArea = denialWB.Sheets(b).Cells(7,3).Value 

我认为这意味着VBA无法识别单元格中存在值。但是,我可以实际进入单元格并进行编辑。任何帮助表示赞赏。谢谢。

1 个答案:

答案 0 :(得分:0)

您的代码中有很多东西很容易对您不利。因此,除了建议您回答问题的建议之外,还有一些我认为会引起问题的常见问题。

单个通用声明行,例如

Dim folderName, fileName, extName, wbName, billArea, postPeriod As String

将类型String分配给所有这些变量。在这种情况下,只有最后一个声明postPeriod As String会声明类型String的变量。所有其他变量默认为类型Variant。标准做法是对每个变量使用单个行声明,每个变量都具有特定的类型。另外,您的代码看起来更干净,可以在首次使用它之前立即声明该变量/类型。这样,您不必滚动到顶部就可以知道类型是什么。所以:

Dim folderName As String
Dim fileName As String
Dim extName As String
...

接下来,read this explanation ActiveWorkbookThisWorkbook之间的差异。几乎总是它是您想要的后一种形式。所以你应该

Dim heatWB As Workbook
Set heatWB = ThisWorkbook

您有两个循环使用

For Each denialWS In Worksheets
    ...
Next denialWS

我在阅读此行时的假设是,您正在ActiveWorkbook中的工作表中循环。但是变量denialWS表示您确实想遍历denialWB的工作表。如果是这样,请使用

For Each denialWS In denialWB.Worksheets
    ...
Next denialWS

此外,在下一个循环中,您进入工作簿中的每个工作表,但通过设置b变量(为什么?)并使用该变量在工作表中进行索引,也使事情变得混乱。 。因此,目前尚不清楚您要对哪张纸进行操作。 (为什么不使用denialWS呢?)

最后回答涉及Find的问题。如果您清除此处提到的问题,很容易会遇到这种情况,您的Find问题将得到解决。但是,您也应该考虑失败的情况。因此,使用类似

Set billAreaRange = denialWS.Range("A1:G10").Find(What:="For Bill Area: ", _
                                                  LookIn:=xlValues, _
                                                  LookAt:=xlPart, _
                                                  MatchCase:=False)
If not billAreaRange Is Nothing Then
    billAreaRow = billAreaRange.Row
    billAreaColumn = billAreaRange.Column
    ... <the rest of your logic here>
Else
    <raise an error or display a MsgBox here>
    Exit For
End If

修复所有这些问题后,还应该修复您尝试过的硬编码测试。