VBA Excel在单元格中分隔日期范围
Posted
技术标签:
【中文标题】VBA Excel在单元格中分隔日期范围【英文标题】:VBA Excel separate range of date in cells 【发布时间】:2013-12-24 01:26:06 【问题描述】:这让我很头疼。我正在尝试执行以下操作:
这是我拥有的数据,我有元素的名称以及开始日期和结束日期。 我想按天获取这些数据,而不是在范围内(所以我可以将它上传到我拥有的数据库中)。
我不知道我是否可以不使用 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 ║
╚═══════╩════════════╝
提前谢谢你。
【问题讨论】:
+1 表示格式正确的问题!您是如何为帖子创建表格格式的?很好读:) 这些类似文本的表格应该针对需要样本的 Excel 问题进行标准化......非常好。 您可以仅使用复制/粘贴来执行此操作...但是一旦将它们分开,您如何知道日期是开始日期还是结束日期?没关系吗?这似乎应该是两个字段,而不是一个。 开始日期和结束日期是否在同一列?您只是想提取开始日期吗? @Blackhawk link 【参考方案1】:最快和最简单的方法可能是使用 VBA。以下代码循环遍历列 A
和 C
中的值,将这些值写入列 A
和 B
中现有数据的下方,并删除列 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
更新:由于 cmets 中的后续问题,现在更改了代码,以便变量 nCol
定义名称在日期列之前的列数。如果宏应该在原始问题中提供的数据上运行,那么nCol = 1
。如果在有效日期之前有三列名称,则为nCol = 3
。
【讨论】:
您错过了日期之间的天数。如果我有一行名称为“foo”,从“25-11-2013”到“27-11-2013”,那么结果将是三行名为“foo”的行,日期为“25-11-2013”,“26-” 11-2013”和“27-11-2013” 我明白了 - 我已经更新了代码。希望这能完成工作。 srrry 再次询问,但如果我在日期之前有更多列(name1、name2、name3)怎么办。我应该在代码中的哪里添加它们? 这取决于您希望他们如何在您的决赛桌中列出。你想让Name1
、Name2
和Name3
都在同一列吗?
不,不同的列..与您所做的相同,但在日期之前有更多包含信息的列,输出是相同的信息列和日期列【参考方案2】:
结合@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...Each 无需定义 [_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 numbers、Doubles。他们代表the range January 1, 100 to December 31, 9999。每一天都是 1,所以整个范围是 [-657434, 2958465]。一天中的时间表示为小数部分。午夜是 *.0,中午是 *.5,3:30 是 ~ *.645833333333333。目前(在我的时区)是 2013 年 12 月 6 日下午 1:27。根据即时窗口 ?CDbl(now())
中的 VBA,即 41614.5608680556。
这就是为什么我可以在 for 循环中遍历日期范围的原因,每次加一以增加日期。
【讨论】:
以上是关于VBA Excel在单元格中分隔日期范围的主要内容,如果未能解决你的问题,请参考以下文章