日期范围的UDF或标准IF函数?

时间:2016-09-23 16:32:16

标签: excel vba if-statement iteration udf

我正在尝试从列中的数字创建范围,并创建范围。例如,

column F: 
1899 
1912 
1915 
1918 
1929 
1934 
1935 
1936
... 

因此,一旦1934年,1935年,1936年的序列开始,它将捕获1934并迭代直到差异不是1.

这个例子的结果是:

1934 - 1936. 

创建这些日期范围后,我会通过“ - ”分隔符将文本用于列,以创建开始日期和结束日期列。

这方面的困难是比较另一列并确保日期基于特定标题。

所以:IF(标题1 =标题2,(IF日期2 - 日期1 = 1,增加到检查日期3 - 日期2 = 1,否则=日期1))。

我可以尝试嵌套许多IF语句,但这会变得很讨厌,而且不知道每个标题要比较多少日期。

迭代似乎通过在VBA中创建子或UDF会容易得多,但我没有在这里(或其他地方)找到任何可能有用的示例。

4 个答案:

答案 0 :(得分:1)

使用AGGREGATE function检索第一组一日序列的开始和停止并不太困难。在H2:I2作为标准公式,

'in H2
=INDEX(F$2:F$15,AGGREGATE(15,6,ROW($1:$14)/((F$3:F$16-$F$2:$F$15)=1), 1))    
'in I2
=INDEX(INDEX(F:F, MATCH(H2,F:F, 0)):F$15,AGGREGATE(15,6,ROW($1:$14)/((INDEX(F:F, MATCH(H2,F:F, 0)+1):F$16-INDEX(F:F, MATCH(H2,F:F, 0)):$F$15)<>1), 1))

first_group_one_day

如果你想组合它们,那么用第一个公式替换第二个公式中对H2的所有引用。

答案 1 :(得分:1)

我知道你需要一种方法来获取日期“范围”,而我仍然没有得到“比较另一列”的事情

关于第一个问题,您可以尝试这个(注释)代码:

Option Explicit

Sub main()
    Dim fictitiousRng As Range, area As Range
    Dim arr As Variant
    Dim iCell As Long

    With Worksheets("numbers") '<--| reference your worksheet (change "numbers" to your actual worksheet name)
        With Intersect(.UsedRange, .Columns("F")).SpecialCells(xlCellTypeConstants, xlNumbers) '<-- reference its column "F" non blank cells with numeric data only
            With .Offset(, .Parent.UsedRange.Columns.Count) '<--| reference referenced range offsetted 1 colum to the right
                .FormulaR1C1 = "=""A"" & RC6" '<--| fill its content with a "fictitiuous" range address by placing an "A" in front of corresponding number in column "F"
                Set fictitiousRng = Range("B1") ' set a initial range for 'fictitiousRng' not to bother for subsequent first call of 'Union()' method
                For Each area In .Areas '<--| loop through referenced range areas (i.e. cells "groups")
                    For iCell = 2 To area.Cells.Count '<--| loop through current area cells
                        Set fictitiousRng = Union(fictitiousRng, Range(area.Cells(iCell, 1).value)) '<--| update 'fictitiousRng' with the cell corresponding to the current fictitious range address
                    Next iCell
                Next area
                arr = Split(Replace(Replace(Intersect(fictitiousRng, Columns(1)).Address(False, False), "A", ""), ":", " - "), ",") '<--| get the fictitious range address, remove "A"s and substitute "." with "-" and then write final "numbers" into an array
                .ClearContents '<-- clear referenced range, i.e. cells with fictitious addresses
                .Cells(1, 1).Resize(UBound(arr) + 1).value = Application.Transpose(arr) '<--| write array content into referenced range cells starting from its first cell
            End With
        End With
    End With
End Sub

它在同一列“F”日期工作表的第一个未使用列中写入日期“范围”

答案 2 :(得分:1)

如果您不介意将公式分为几列,请参阅IF()语句示例,了解如何提取Begin&amp; amp; amp; amp; amp; amp; amp; amp; amp; amp;结束年份:

Find the beginning and ending year range - Excel formula example

=IF(B13>1,"",IF(B14<2,IF(C12="",A13,C12),IF(ISNUMBER(C12),C12&"-"&A14,A13&"-"&A14)))

<强>解释

B栏 - 找出年份之间的差异

C栏 - 优雅的nested IF()公式;)

D列 - Left() 4个字符,如果长度为&gt; 4

E栏 - Right() 4个字符,如果长度为&gt; 4

答案 3 :(得分:1)

这将完成这项工作,它将需要F列中的单元格并在G列中打印输出。如果有一个年份范围(例如:1934-1935-1936),它将把它放在一个单元格中作为一个字符串。

Sub range_dates()
Dim cel As Range
Dim iRow As Long, n As Long
Dim title As String, nextTitle As String
iRow = 2
n = 0
For i = 2 To 15
    Set cel = Cells(i, "F")
    title = Cells(i, "E").Value
    nextTitle = Cells(i + 1, "E").Value
    diff = Cells(i + 1, "F").Value - cel.Value

    If diff = 1 And title = nextTitle Then
        firstDate = cel.Value - n
        n = n + 1
    Else
        Cells(iRow, "H").Value = cel.Value
        Cells(iRow, "G").Value = title
        If n > 0 Then
            Cells(iRow, "H") = "'" & firstDate & " - " & cel.Value
            n = 0
        End If
        iRow = iRow + 1
    End If
Next
End Sub

我知道这段代码不是最优化的,但截至目前,这是我必须分享的代码。随意改进它:)

编辑:我添加了标题条件并更改了输出以防止excel将字符串更改为日期格式