首页 > 解决方案 > 单元格不为空时的 IF 语句

问题描述

你能帮我清除这段代码吗?

我正在尝试过滤掉某些日期,如果没有可见的单元格,则不要执行代码。

由于某种原因,我无法IF正常工作。

Dim EndDate1, StartDate1 As Long
Dim todayDate1 As Long

Sheets("Macro").Select
todayDate1 = Sheets("Macro").Cells(2, 2)

Sheets("FTC").Select
StartDate1 = DateSerial(Year(todayDate1),Month(todayDate1),Day(todayDate1) + 14)
EndDate1 = DateSerial(Year(todayDate1), Month(todayDate1), Day(todayDate1) + 21)

ActiveSheet.Range("$A$1:$AP$1000").AutoFilter Field:=24, _
    Criteria1:=">=" & StartDate1, Operator:=xlAnd, Criteria2:="<" & EndDate1
Range("A2:A1000").Select
Selection.SpecialCells(xlCellTypeVisible).Select

If Selection.SpecialCells(xlCellTypeVisible).Count > 1 Then
    MsgBox "Nope"
End If
MsgBox "Yay"

标签: excelvbaif-statementcountvisible

解决方案


您的代码存在许多小问题,但您的问题写得很好,并且您所做的努力在正确的轨道上(我们都必须从某个地方开始)所以对此表示赞赏!


认为这就是你想要做的:

Sub FilterDemo()

    Const filterField = 24
    Dim ws As Worksheet: Set ws = Sheets("Macro")
    Dim filterRange As Range: Set filterRange = ws.Range("A:AP")
    Dim dtStart As Date, dtEnd As Date, visibleRows As Long

    'assuming you want to use "today's date"? (returned by function [Date])
    dtStart = Date + 14
    dtEnd = Date + 21

    filterRange.AutoFilter Field:=1 'clear existing filter

    filterRange.AutoFilter Field:=filterField, _
        Criteria1:=">=" & Format(dtStart, "yyyy-MM-dd"), _
        Criteria2:="<=" & Format(dtEnd, "yyyy-MM-dd")

    visibleRows=ws.AutoFilter.Range.Columns(1).SpecialCells(xlCellTypeVisible) _
            .Cells.Count - 1

    If visibleRows = 0 Then
        filterRange.AutoFilter Field:=1  'remove filter
        MsgBox "No data found between " & dtStart & " and " & dtEnd & ".", _
            vbExclamation, "No Data Found"
    Else
        MsgBox visibleRows &" items between" & dtStart &" and "& dtEnd & ".", _
            vbInformation, "Data found!"
    End If

End Sub

笔记:

  • 很高兴您声明了变量 - 但最好将日期声明为数据类型Date。Excel 确实在内部将日期存储为数字(尽管不是整数),但最好还是将变量声明为Date并让 Excel 找出其余的。

    由于我们使用了正确的Date日期类型,我们可以简单地相互添加天数(而不是使用DateSerial)。(有关日期的更多信息。)

  • 您声明StartDate1 As Long但未声明EndDate1:您可以在一行上声明多个变量,但如果没有指定类型,则它们默认为Variant.

  • 我假设单元格B2只保存当前日期?— 如果是Date这样,请改用 VBA函数

  • 将日期作为参数传递时,以Format我们知道AutoFilter会理解的方式对他们来说是个好主意,它也会转换为 String

    可能也可以正常工作,Criteria1:=">=" & dtStart, Criteria2:="<=" & dtEnd正确的方法是转换为字符串,因为这是AutoFilters 的标准所期望的。

  • Select如果可能,应避免使用语句(并且在使用录制的宏中的代码时应“整理” )。例如,这个

    Range("A2:A1000").Select
    Selection.SpecialCells(xlCellTypeVisible).Select
    If Selection.SpecialCells(xlCellTypeVisible).Count > 1 Then
    

    ...变成这样

    If Range("A2:A1000").SpecialCells(xlCellTypeVisible).Count > 1 Then
    

    重要相关阅读:如何避免在 Excel VBA 中使用 Select

  • 通过指定 range A1:AP1000CountProperty将对所有行数最多为 1000,仅扣除过滤器隐藏的行数。

    我没有指定任意一组行,而是指整个列。AutoFilter “创建”它正在使用的单元格范围,我们可以像这样引用这个表达式:(从这里借用)

    ws.AutoFilter.Range.Columns(1).SpecialCells(xlCellTypeVisible).Cells.Count
    

当试图找出像这样的长表达式时,从右到左阅读它会很有帮助(或者,为了说明目的,倒置!

颠倒的例子运算符或我的在自动筛选条件中不正确,具体取决于您的日期列中的值是否附加了时间

  • 您的代码示例使用>=StartDate and <EndDate

    你的不包括午夜的EndDate值。但是,如果没有附加时间,那么您的时间将不包括EndDate. 如果附有时间,那么您的时间最多11:59:59pm包括EndDate.

  • 我的代码示例使用>=StartDate and <=EndDate.

    我的在 上包括午夜的EndDate值,如果数据没有附加时间,EndDate则包括整个时间。您的方法是在查询时间多个日期范围时使用的正确方法,以防止重叠。(有关日期/时间的更多信息。)

  • 最后(主要是装饰性的),请注意MsgBox "Yay"无论是否出现,您都会MsgBox "Nope"出现。

    这可以通过Exit Sub(立即结束程序)使用ElsewithIf语句来避免。(更多关于If..Then..Else。)

  • 希望这是有道理的......祝你好运!


    推荐阅读