VBA Excel单元格中的单独日期范围

时间:2013-12-06 15:57:48

标签: excel vba date

这让我很头疼。我试图做以下事情:

这是我拥有的数据,我有元素的名称,开始日期和结束日期。 我想在白天获得这些数据,而不是在范围内(所以我可以将它上传到我所拥有的数据库中。)

我不知道我是否可以在不使用VBA的情况下做到这一点,但我想快速将是VBA。

当前数据:

╔═══════╦════════════╦════════════╗
║ name  ║ start date ║  end date  ║
╠═══════╬════════════╬════════════╣
║ foo1  ║ 25-11-2013 ║ 28-11-2013 ║
║ foo2  ║ 25-11-2013 ║ 28-11-2013 ║
║ foo3  ║ 25-11-2013 ║ 28-11-2013 ║
║ foo4  ║ 25-11-2013 ║ 28-11-2013 ║
║ foo5  ║ 25-11-2013 ║ 28-11-2013 ║
║ foo6  ║ 28-11-2013 ║ 28-11-2013 ║
║ foo7  ║ 28-11-2013 ║ 28-11-2013 ║
║ foo8  ║ 28-11-2013 ║ 28-11-2013 ║
║ foo9  ║ 28-11-2013 ║ 28-11-2013 ║
║ foo10 ║ 28-11-2013 ║ 28-11-2013 ║
║ foo11 ║ 29-11-2013 ║ 30-11-2013 ║
║ foo12 ║ 29-11-2013 ║ 30-11-2013 ║
║ foo13 ║ 29-11-2013 ║ 30-11-2013 ║
║ foo14 ║ 29-11-2013 ║ 30-11-2013 ║
║ foo15 ║ 29-11-2013 ║ 30-11-2013 ║
╚═══════╩════════════╩════════════╝

我想在白天分开名字,以获得这个:

╔═══════╦════════════╗
║ name  ║    date    ║
╠═══════╬════════════╣
║ foo1  ║ 25-11-2013 ║
║ foo2  ║ 25-11-2013 ║
║ foo3  ║ 25-11-2013 ║
║ foo4  ║ 25-11-2013 ║
║ foo5  ║ 25-11-2013 ║
║ foo1  ║ 26-11-2013 ║
║ foo2  ║ 26-11-2013 ║
║ foo3  ║ 26-11-2013 ║
║ foo4  ║ 26-11-2013 ║
║ foo5  ║ 26-11-2013 ║
║ foo1  ║ 27-11-2013 ║
║ foo2  ║ 27-11-2013 ║
║ foo3  ║ 27-11-2013 ║
║ foo4  ║ 27-11-2013 ║
║ foo5  ║ 27-11-2013 ║
║ foo6  ║ 28-11-2013 ║
║ foo7  ║ 28-11-2013 ║
║ foo8  ║ 28-11-2013 ║
║ foo9  ║ 28-11-2013 ║
║ foo10 ║ 28-11-2013 ║
║ foo11 ║ 29-11-2013 ║
║ foo12 ║ 29-11-2013 ║
║ foo13 ║ 29-11-2013 ║
║ foo14 ║ 29-11-2013 ║
║ foo15 ║ 29-11-2013 ║
║ foo11 ║ 30-11-2013 ║
║ foo12 ║ 30-11-2013 ║
║ foo13 ║ 30-11-2013 ║
║ foo14 ║ 30-11-2013 ║
║ foo15 ║ 30-11-2013 ║
╚═══════╩════════════╝

提前谢谢。

2 个答案:

答案 0 :(得分:1)

结合@ SorenHoltenHansen的回答,这应该可以让你到达目的地。此类将接受开始日期和结束日期范围,它将计算您可以在代码中使用的完整日期范围。

创建一个新类,将其命名为“clsDateRange”,并添加以下代码:

Option Compare Database
Option Explicit

Private m_colDates As Collection

Public Sub InitStartEnd(ByVal dtStart As Date, ByVal dtEnd As Date)
    Set m_colDates = New Collection
    Dim tempDate As Date
    For tempDate = dtStart To dtEnd Step 1
        m_colDates.Add DateValue(tempDate)
    Next
End Sub

Public Property Get Dates() As Collection
    Set Dates = m_colDates
End Property

您可以全力以赴并实施收集界面,但这应该足以满足您的需求。如果您要拥有非常大的日期范围并且想要明智,那么您可以只存储开始日期和结束日期,并仅在需要时生成中间日期,但我希望能够使用For ...每个都不需要定义[_NewEnum]和Collection的所有子属性。

以下是模块“mdlMain”中的一些测试,因此您可以看到如何使用它:

Public Sub Main()
    Dim oDateRange As New clsDateRange
    Dim varDate As Variant

    oDateRange.InitStartEnd "25-11-2013", "27-11-2013"
    For Each varDate In oDateRange.Dates()
        MsgBox varDate
    Next

    oDateRange.InitStartEnd "28-11-2013", "28-11-2013"
    For Each varDate In oDateRange.Dates()
        MsgBox varDate
    Next

    oDateRange.InitStartEnd "29-11-2013", "30-11-2013"
    For Each varDate In oDateRange.Dates()
        MsgBox varDate
    Next

End Sub

顺便提一下,dates are actually just 64-bit floating point numbersDoubles。它们代表the range January 1, 100 to December 31, 9999。每天是1,因此整个范围是[-657434,2958465]。一天中的时间表示为小数部分。午夜是* .0,中午是* .5,3:30是〜* .645833333333333。目前(在我的时区),它是2013年12月6日下午1:27。根据VBA在即时窗口?CDbl(now()),这是41614.5608680556。

这就是为什么我可以在for循环中运行日期范围的原因,每次增加一个来增加一天。

答案 1 :(得分:0)

最快最简单的方法可能是使用VBA。以下代码遍历列AC中的值,将这些值写入列AB中的现有数据下方,并删除列C中的数据

Sub SeperateDateRange()
    Dim Ws As Worksheet
    Dim nCol As Integer

    'Define sheet
    Set Ws = ActiveSheet

    nCol = 1 '<~~ Defines the number of columns before the date columns

    Application.ScreenUpdating = False

    'Loops throuh cells
    For i = 1 To ActiveSheet.Cells(Rows.Count, nCol + 2).End(xlUp).Row - 1 Step 1
        For j = 0 To Ws.Cells(i + 1, nCol + 2).Value - Ws.Cells(i + 1, nCol + 1).Value Step 1

            With Ws.Cells(Ws.Cells(Rows.Count, 1).End(xlUp).Row + 1, 1)
                For k = 0 To nCol - 1 Step 1
                    .Offset(0, k).Value = Ws.Cells(i + 1, k + 1).Value
                Next k
                .Offset(0, nCol).Value = DateSerial(Year(Ws.Cells(i + 1, nCol + 1).Value), Month(Ws.Cells(i + 1, nCol + 1).Value), Day(Ws.Cells(i + 1, nCol + 1).Value) + j)
            End With
        Next j
    Next i

    'Deletes last column with dates
    Ws.Cells(1, nCol + 2).EntireColumn.Delete

    Application.ScreenUpdating = True
End Sub

更新:由于评论中存在后续问题,因此现在更改了代码,以便变量nCol定义在日期列之前具有名称的列数。如果宏应该在原始问题中显示的数据上运行,那么nCol = 1。如果在日期前的三个列中有名称,则为nCol = 3