【发布时间】:2018-08-19 16:30:00
【问题描述】:
场景:我有一个从其他文件读取数据并导入到不同工作表的代码。其中一些文件具有月度格式的数据,而另一些则具有每日格式的数据
每日数据示例(yyyy-mm-dd):
item1 item2 item3
2010/01/01 1 1 1
2010/01/02 1 1 1
2010/01/03 1 1 1
2010/01/04 1 1 1
2010/01/05 1 1 1
数据示例monthly(yyyy-mm-dd),这里的日期通常是当月的最后一个工作日:
item1 item2 item3
2010/01/31 5 3 1
2010/02/28 4 10 5
2010/03/31 7 9 2
2010/04/30 8 4 8
2010/05/31 2 7 7
目标:我正在尝试将所有月度数据转换为每日数据,方法是保持月末所有日期的月末值相同。例如:如果我 2010/02/28 的值是 10,则 2 月的所有天数都应该等于该项目的 10。
我已经尝试过的方法:我尝试过反向循环并添加列,但没有奏效。现在我正在尝试创建两个数组(一个每天和一个每月),并比较:遍历每月行,然后每天行,如果月份和年份相同,则使该每日行的值等于每月(例如:2 月的所有日值都将等于 1 月的月值,除了 2 月的最后一天,它将是 2 月的月值)。比如:
如果我的项目 1 一月的月值为 5,二月的月值为 10,三月的月值为 3,那么我的每日数据将是(假设我的数据从 1 月开始):
01/01 至 30/01 = 5、31/01 至 27/02 = 10、28/02 至 30/03 = 3,依此类推。
问题:当我尝试这样做时,我无法正确组织循环,因此 xx 循环(用于列)最终会从错误的行中获取数据。知道如何解决这个问题,或者如何以更有效的方式进行此过程吗?
代码:
Private Sub CommandButton2_Click()
Dim monthlydatesarray As Variant, monthlydataarray As Variant, dailydatesarray As Variant, dailydataarray As Variant
Dim xx As Long, monthlydaterow As Long, dailydaterow As Long, lastRowD As Long, lastRowM As Long
Dim wbpath As String
Dim wb As Workbook
Dim ws As Worksheet
wbpath = ThisWorkbook.Path
Set wb = ThisWorkbook
Application.ScreenUpdating = False
Application.EnableEvents = False
Application.Calculation = xlCalculationManual
lastRowD = Sheets("Bid").Cells.SpecialCells(xlCellTypeLastCell).Row
lastRowM = Sheets("AMT").Cells.SpecialCells(xlCellTypeLastCell).Row
For Each ws In wb.Worksheets
If ws.Name = "A" Then
'sets proper columns for dates and data, both monthly and daily
dailydatesarray = wb.Sheets("B").Range("A2:A" & lastRowD)
dailydataarray = wb.Sheets("B").UsedRange
monthlydatesarray = wb.Sheets("A").Range("A2:A" & lastRowM)
monthlydataarray = wb.Sheets("A").UsedRange
'if date matches month and year, use the data values
For monthlydaterow = 1 To UBound(monthlydatesarray)
For dailydaterow = 1 To UBound(dailydatesarray)
If Month(monthlydatesarray(monthlydaterow, 1)) = Month(dailydatesarray(dailydaterow, 1)) And Year(monthlydatesarray(monthlydaterow, 1)) = Year(dailydatesarray(dailydaterow, 1)) Then
'loop the columns to paste the monthly data into daily array
For xx = 2 To UBound(dailydataarray, 2)
dailydataarray(dailydaterow + 1, xx) = monthlydataarray(monthlydaterow, xx)
Next xx
End If
Next dailydaterow
Next monthlydaterow
'do one more loop to repaste the last date of the month properly
For monthlydaterow = 1 To UBound(monthlydatesarray)
For dailydaterow = 1 To UBound(dailydatesarray)
If monthlydatesarray(monthlydaterow) = dailydatesarray(dailydaterow) Then
For xx = 2 To UBound(dailydataarray, 2)
dailydataarray(dailydaterow, xx) = monthlydataarray(monthlydaterow, xx)
Next xx
End If
Next dailydaterow
Next monthlydaterow
ws.UsedRange.Clear
wb.Sheets("B").Range("A1").Resize(UBound(dailydataarray, 1), UBound(dailydataarray, 2)) = dailydataarray
ws.UsedRange.Columns(1).NumberFormat = "yyyy/mm/dd"
End If
Next ws
'Optimize Macro Speed End
Application.ScreenUpdating = True
Application.EnableEvents = True
Application.Calculation = xlCalculationAutomatic
MsgBox "Process Finished"
End Sub
【问题讨论】:
-
向后循环应该可以工作
For monthlydaterow = UBound(monthlydatesarray) To 1 Step -1。你试的时候有没有遇到什么问题? -
我认为从这个例子:01/01 到 30/01 = 5、31/01 到 27/02 = 10、28/02 到 30/03 = 3....你是什么说的是除了给定月份的最后一天之外的所有日期都等于上个月的月末日位置的值。仅适用于每月。实际上,如果您在一个月中的所有日子都可用,这将是使用现有值的表格填充操作。您是否必须每个月重复第 1,2 和 3 项?
-
@Slai 当我尝试向后循环时,我遇到了与如何引用上个月日期类似的问题,两者都给我带来了同样的麻烦。
-
@QHarr 是的,基本上就是这样。我已经有一个包含所有工作日期的表格(我的dailydataarray),并且我正试图按照您理解的方式将每月数组中的数据传递到其中。代码中的 xx 循环用于列(对于每个项目,我有几千个)。所以基本上,我循环每月日期,然后是每日日期,然后是列项目(这是我卡住的地方)。
-
如果是单个值,可以使用powerquery进行表格填充。我知道您正在寻求代码解决方案,我目前正在考虑,但这是一个额外的灵感。