概述:我基本上想编写一个MONTH函数的版本,以在13个工作年的时间内工作...
(免责声明:我是VBA的新手)将日期/月/日的日期重新格式化为周期号(1-13)和星期号(1-4)的最佳方法是什么?我已经使用WEEKNUM函数来解决这个问题,但是我似乎不太明白。我认为问题在于新年的开始(时段1,第1周)在18/30/18,在excel中,根据其衡量方式,该日期被视为第5周甚至第6周。
每周从星期日开始,一年中的每个时期(13)都有4周。到目前为止,我已经尝试过:
这是一个自写函数的基本部分,它仅使周数部分起作用,并且只给我#value,但msgbox中没有错误(如果它起作用了,我也许可以找出休息):
Function PeriodNum(serial_num As Date, number_periods As Integer, start_date As Date)
Dim first_week As Integer
Dim second_week As Integer
Dim third_week As Integer
Dim fourth_week As Integer
Dim day As Integer
first_week = 1
second_week = 2
third_week = 3
fourth_week = 4
day = serial_num
If day >= start_date Or day <= start_date + 7 Then
Selection.Value = first_week
ElseIf day > start_date + 7 Or day <= start_date + 14 Then
Selection.Value = second_week
ElseIf day > start_date + 14 Or day <= start_date + 21 Then
Selection.Value = third_week
ElseIf day > start_date + 21 Or day <= start_date + 28 Then
Selection.Value = fourth_week
Else
Selection.Value = "error"
End If
End Function
-我也尝试过使用WEEKNUM函数,但是我不知道如何获取每个透视图周期的1-4号
非常感谢您的帮助!非常感谢
答案 0 :(得分:1)
1)根据VBA的代码规则,存在一个问题:
对每个 函数PeriodNum(serial_num作为日期,number_periods作为整数,start_date作为日期) 定义,您还应该使用row:PeriodNum = ...
通过这种方式,您正在从函数中返回一个值(类似于return x;在其他语言中)
2)使用Selection对象是不可预测的,并且可以在调用方法时更改您在Excel中处于活动状态的任何单元格。如果要使用计算方法,则应使用类似的方法:
Function weekCompute(date1)
'...
weekCompute = "val1"
End Function
使用此功能,您可以使用以下单元格公式: = weekCompute(A1)
答案 1 :(得分:0)
您可以计算周数:
LngPeriod = int((day - start_date +1)/7)
If lngPeriod >4 then
PeriodNum = “error”
Else
PeriodNum = lngPeriod
End if
PeriodNum函数返回建议的变体。
答案 2 :(得分:0)
在Excel中,无论是内置函数(即SUM,COUNT)还是用户定义的函数(如PeriodNum),通常都会向其输入的单元格返回一个值。它们不会修改工作簿对象,例如{{ 1}}是的成员。过程Selection
修改对象,但没有返回值。
@VitezslavSimon在其答案中提到,您需要在代码中的某个位置-Sub
或PeriodNum = 1
中给函数名称分配一个值。
将返回类型显式添加到函数中也是一个好主意。在您的情况下,如果您不对返回值进行任何算术计算,则可以使用PeriodNum ="error"
;如果您想在进一步的计算中使用返回值,则可以使用String
。您的函数定义将为:
Variant
函数错误的迭代方法
我将您的代码复制到标准VBA模块中,并在行Function PeriodNum(serial_num As Date, number_periods As Integer, start_date As Date) As Variant
上放置了一个断点,以便在将其输入单元格后可以逐步执行该功能。为了对其进行测试,我将您的first_week = 1
放在单元格C2中,并将start_date
放在C3中。我通过在D3中输入serial_num
来调用该函数。
单步执行代码时,行=PeriodNum(C3,13,$C$2)
导致函数结束并在D3中返回day = serial_num
错误。
#VALUE!
是由UDF返回的唯一出错的错误。您不会在UDF中获得大量的运行时错误,因此调查的唯一方法是单步执行代码并查看错误原因。
我测试的日期是18/30/18,序列号为43464。您定义的#VALUE!
必须在-32,768到32,767之间。因此潜在的错误是day As Integer
,因为43464在Overflow
的允许值之外。
第二名。迭代
将Integer
更改为Integer
可以解决该错误,但是
Long
对于If day >= start_date Or day <= start_date + 7 Then
PeriodNum = first_week
> = serial_num
总是返回1或对于start_date
<"error"
返回serial_num
。测试的第二部分start_date
并不重要,因为如果是Or day <= start_date + 7
,则另一个测试是FALSE
。我通过将日期扩展到C381并将其延续到2020年来进行了测试。因此,请回到图纸板上!
第三次迭代
将所有TRUE
更改为Or
可以确保第二部分得到评估。
And
在Excel中,我注意到1/6/19(应该是期间2的第一天)显示为1。因此测试有问题。将If day >= start_date And day <= start_date + 7 Then
PeriodNum = first_week
ElseIf day > start_date + 7 And day <= start_date + 14 Then
PeriodNum = second_week
ElseIf day > start_date + 14 And day <= start_date + 21 Then
PeriodNum = third_week
ElseIf day > start_date + 21 And day <= start_date + 28 Then
PeriodNum = fourth_week
Else
PeriodNum = "error"
End If
更改为day <= start_date + 7
应该可以解决,但返回day < start_date + 7
。这是因为后续测试不允许使用"error"
。
第四名。迭代
day = start_date + 7
返回Excel,在向下滚动之前看起来不错。 19/1/27,下面的所有内容均返回 If day >= start_date And day < start_date + 7 Then
PeriodNum = first_week
ElseIf day >= start_date + 7 And day < start_date + 14 Then
PeriodNum = second_week
ElseIf day >= start_date + 14 And day < start_date + 21 Then
PeriodNum = third_week
ElseIf day >= start_date + 21 And day < start_date + 28 Then
PeriodNum = fourth_week
Else
PeriodNum = "error"
End If
。 "error"
显然不能超过day
。
第五名。迭代
将start_date + 28
更改为day = serial_num
,然后进行测试以查看与0、7、14、21和28相关的数字。
day = (serial_num - start_date) Mod 28
返回Excel,一切看起来都很好。
最终迭代-完善
仍有一些改进:
day = (serial_num - start_date) Mod 28
If day >= 0 And day < 7 Then
PeriodNum = first_week
ElseIf day >= 7 And day < 14 Then
PeriodNum = second_week
ElseIf day >= 14 And day < 21 Then
PeriodNum = third_week
ElseIf day >= 21 And day < 28 Then
PeriodNum = fourth_week
Else
PeriodNum = "error"
End If
未使用,因此将其删除number_periods As Integer
WeekInPeriod` PeriodNum name is deceptive. It isn't returning a period but a week in a period so
是VBA函数(返回月份中的日期)。我将其更改为day
。描述性的变量名称使用户更容易解析。DayInPeriod28
更改为serial_num
。MyDate
比嵌套的Ifs更紧凑。不要声明和定义只使用一次的变量。这是浪费时间和空间。
Select Case