このコードはそれほど高度ではありませんが、少し面倒です。私はあなたが必要とするものを達成するはずのあなたのためにこれを設計しました. コードの学習にも役立つ解説が満載です (これを自分でやり直したい場合)。幸運を!
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
。これは、すべてのマイルストーンが 2 列離れていることを前提としています。