【问题标题】:Comparing Date Range Excel VBA比较日期范围Excel VBA
【发布时间】:2013-11-05 21:17:27
【问题描述】:

已更新答案:我找到了我的问题的答案。为了方便起见,我将在此处的原始问题下方放置一个简化版本,下面有一个更详细的版本作为接受的答案。

我正在编写一个 VBA 函数来按用户输入的日期范围过滤数据透视表。由于某种原因,它没有返回预期的结果。

所比较的日期采用两种不同的日期格式。用户输入的日期采用 mmmm yyyy 格式(2013 年 10 月)。当将此值拉入宏进行比较时,它会正确转换为 2013 年 10 月 1 日。数据透视表日期采用 mmm yy 格式(10 月 13 日)。当我使用代码PivotItem.Value 调用此日期时,它似乎将日期转换为字符串“10 月 13 日”。

我不太清楚宏在做什么,因为它的行为有些不规律。如果我在 2011 年 10 月到 2013 年 10 月运行它,它会返回每年 1 月到 9 月、2008 年、2009 年、2010 年等的所有月份。如果我在 2013 年 6 月到 2013 年 10 月运行它,它会返回每年 6 月到 9 月.此外,在每个示例中,宏继续运行超过数据透视表中的最大数据范围并出现错误。当我调试时,宏正在尝试将数据透视表中甚至不存在的日期的可见性设置为“真”(即 2014 年 1 月的 IE,当数据仅通过 2013 年 10 月时)。不知道为什么会这样。

下面是代码。任何见解将不胜感激。

更新:

所以问题肯定是日期格式。如果我将数据透视表中的字段设置更改为日期格式 mm/dd/yyyy (10/1/2013),那么宏将完全按预期工作。这将是一个简单的解决问题除了表格正在提供用户仪表板中看到的图表,我真的希望采用 mmm yy 格式,因为它看起来更干净。有没有一种简单的方法可以在宏中将格式转换为 mm/dd/yyyy 以进行比较,然后在完成后返回所需的格式?

而且我仍然想了解为什么不同的日期格式会返回如此不同的结果,当被比较的原始数据相同并且两者都被格式化为 日期,而不是日期与文本什么的。

Sub filterPivotDate(pt As PivotTable, strtDate As Date, endDate As Date)

Dim pf As PivotField
Dim pi As PivotItem

'Clear current date filter
Set pf = pt.PivotFields("Date")
pf.ClearAllFilters

'Set new date filter
For Each pi In pf.PivotItems
    If pi.Value >= strtDate And pi.Value <= endDate Then
        pi.Visible = True
    Else
        pi.Visible = False
    End If
Next pi

end sub

回答更新: 我用以下代码行替换了用于设置过滤器的循环:

pf.PivotFilters.Add Type:=xlDateBetween, Value1:=strtDate, Value2:=endDate

这解决了我在使用日期格式时遇到的问题。更多信息在下面接受的答案中,以及this website

【问题讨论】:

    标签: vba excel


    【解决方案1】:

    我可能错了,但是您的

    【讨论】:

    • 是的,我希望它显示大于或等于开始日期且小于或等于结束日期的日期。编写代码的方式与该逻辑正好相反 - 如果日期小于开始日期或大于结束日期(不在日期范围内),它将项目的可见性设置为 false。看完你的回答后,我确实意识到其中一个字符打错了,但我更正了。现在我的问题和代码一样。
    【解决方案2】:

    您可以先尝试转换字符串日期值:

    Dim dateValue as Date
    
    'Set new date filter on all pivot tables
    For Each pt In ws.PivotTables
        Set pf = pt.PivotFields("Date")
    
        For Each pi In pf.PivotItems
    
            If IsDate(pi.Value) Then
                dateValue = CDate(pi.Value)
                If dateValue < strtDate Or dateValue > endDate Then
                    pi.Visible = False
                Else
                    pi.Visible = True
                End If
            End If
        Next pi
    
    Next pt
    
    'call this function
    Function IsDate(byval thisDateString as String) As Boolean
        On Error Goto ErrorHandler
    
        Dim d as Date
        d = CDate(thisDateString)
        IsDate = true
        Exit Function
    
    ErrorHandler:
        IsDate = false
    End Function
    

    【讨论】:

    • 转换为日期值无效。 2013 年 10 月,由“CDate”转换,返回 10-13-2013,2014 年 10 月返回 10-14-2013。我认为这就是问题的根源,它将年读作日而不是年。事实证明,如果我将其转换为日期格式 mm/dd/yyyy,则比较按预期工作。但是,我想在数据透视表中显示的输出中保留 mmm-yy 格式。也许我会尝试转换一种方式进行比较,然后再转换回来,但我不希望被要求这样做。
    • 我明白你的意思。我认为您可以将日期值格式化为月-年,如果您将完整日期作为字符串值(mm/dd/yyyy),它将起作用。
    【解决方案3】:

    我发现了一些关于通过 VBA 设置数据透视表过滤器的附加信息,这些信息改进了原始代码并解决了我遇到的问题。我决定发布它,因为我发现这些信息非常有用。

    您可以使用简单的一行命令设置许多不同的过滤器,而不是像我之前所做的那样解析所有数据并根据条件手动设置可见性的复杂循环。下面是更新后的代码,它也解决了我在日期格式方面遇到的问题。

    this link to the globaliconnect website 提供了一些关于您可以使用 VBA 设置的不同数据透视表过滤器设置的非常有用的信息。

    我仍然不确定为什么在循环比较之前日期表现得很奇怪,但我猜日期有点像……

    Sub filterPivotDate(pt As PivotTable, strtDate As Date, endDate As Date)
       Dim pf As PivotField
       Application.ScreenUpdating = False
    
       'Clear date filter and set new filter
       Set pf = pt.PivotFields("Date")
       pf.ClearAllFilters
    
       'I REPLACED THE LOOP WITH A SINGLE LINE TO SET A FILTER BETWEEN TWO DATES
       pf.PivotFilters.Add Type:=xlDateBetween, Value1:=strtDate, Value2:=endDate
    
       Application.ScreenUpdating = True
    End Sub
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-12-12
      • 2010-09-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-19
      • 1970-01-01
      相关资源
      最近更新 更多