好的,这个代码真的不是太高级,但是有点乏味。我为您设计了这个,它应该可以满足您的需求。它充满了您可以用来帮助学习代码的评论(如果您想自己再次这样做)。祝你好运!
Sub normalizeData()
Dim i As Integer, j As Integer, k As Integer
Dim r As Integer
Dim bReport As Workbook, Report As Worksheet, Report2 As Worksheet
Dim m(0 To 9) As Integer 'This sets up the variables for your milestones
Dim mileString As String, dateString As String
Set Report = Excel.ActiveSheet
Set bReport = Report.Parent
Set Report2 = bReport.Worksheets.Add
'There are two ways to identify your milestones to the subroutine: either have some kind of identifier to search _
for within the value of the milestone cell; or define them explicitly. I'm going to do the latter since I don't know _
what might be in those cells.
m(0) = 33 'The column number for each milestone
m(1) = 35
m(2) = 37
m(3) = 39
m(4) = 41
m(5) = 43
m(6) = 45
m(7) = 47
m(8) = 49
m(9) = 51
r = Report.UsedRange.Rows.Count 'Get the last row number and assign it to a _
short variable (just to make things easier).
Report2.Cells(1, 1).Value = "Normalized Data" 'Placing a header row allows us to use used range without having _
to worry about identifying the first iteration. If you've ever tried this _
by yourself you probably know what I'm referring to.
With Report2.Range("A1:D1") 'Just makin it purdy
.Merge
.HorizontalAlignment = xlCenter
.Interior.Color = RGB(0, 20, 99)
.Font.Color = RGB(224, 238, 255)
.Font.Bold = True
.Font.Size = 14
End With
For i = 2 To r
For j = 0 To 9
If Report.Cells(i, m(j)).Value <> "" And _
Report.Cells(i, m(j)).Value <> "Null" Then 'I'm not sure if the empty values will be null or blank strings.
mileString = Report.Cells(i, m(j)).Value
dateString = Report.Cells(i, m(j) + 1).Value
k = Report2.UsedRange.Rows.Count + 1
Report2.Cells(k, 1).Value = Report.Cells(i, 1).Value
Report2.Cells(k, 2).Value = Report.Cells(1, m(j)).Value 'Assuming your header is on the first row
Report2.Cells(k, 3).Value = mileString
Report2.Cells(k, 4).Value = dateString
Report2.Cells(k, 4).NumberFormat = "MM/dd/yyyy"
End If
Next j
Next i
For i = 2 To Report2.UsedRange.Rows.Count
If i Mod 2 = 0 Then
Report2.Range("A" & i & ":D" & i).Interior.Color = RGB(227, 235, 252) 'Alternating row color for easier reading.
End If
Next i
'************** This part adds borders. Omit this block if you don't want them.************
With Report2.Range("A1:D" & Report2.UsedRange.Rows.Count)
.Borders(xlEdgeTop).Weight = xlThin
.Borders(xlEdgeBottom).Weight = xlThin
.Borders(xlLeft).Weight = xlThin
.Borders(xlRight).Weight = xlThin
.Borders(xlInsideHorizontal).Weight = xlThin
.Borders(xlInsideVertical).Weight = xlThin
End With
'******************************************************************************************
End Sub
PS:确保您在运行宏时位于非规范化工作表上。它旨在将该工作表引用为活动工作表并将标准化数据放入新工作表中。
另请注意,我使用了一个数组来识别里程碑,但我相信您可以轻松地使用For...Next
带有第 2 步增量的循环来提高可伸缩性。例如,在这种情况下,for 循环的开头看起来像For j = 33 to 51 Step 2
. 这是假设您的所有里程碑都相隔两列。