3

我浏览了关于这个主题的类似主题但被卡住了,我需要一些 Excel 2003 中的 VBA 专家的帮助

我有一排数据如下

 (Project Code)    ...(Milestone1)  (Date1)     (Milestone2)  (Date2) ... (Milestone 10)(Date3)
        ColumnA    ... ColumnAG     ColumnAH    ColumnAI     ColumnAJ  ...  ColumnAY    ColumnAZ
        Header1        Header33     Header34    Header35     Header36  ...  Header51    Header52
 rowkey datavalue1     datavalue33   datavalue34 datavalue35  datavalue36 ... datavalue51

我有一个非规范化数据集,其中数据值可能逐行为空,也可能不为空。我需要使它们正常化。

IE

        1234567        start    12/12/2012    build      12/01/2013 ... finish 01/02/2014        
        1234568        plan     14/12/2012    contract   02/02/2013  ... NULL   NULL

会成为

        1234567        header33  start    12/12/2012
        1234567        header34  build    12/01/2013
        ...
        1234567        header51  finish   01/02/2014
        1234568        header33  plan     14/12/2012
        1234568        header34  contract 02/02/2013

我有大约数百行,包含名称为 10 个里程碑和 10 个关联日期的项目数据,并且需要将它们拆分,因此我有多行列出每个项目代码的里程碑标题/里程碑名称/日期....如果里程碑名称和数据是空白的记录可以跳过...

在 Excel 2007 中有一个类似的帖子将包含数据列的行转换为包含多行的列,但不知道如何更改以将其应用于上述场景......

任何帮助将不胜感激谢谢

4

1 回答 1

0

好的,这个代码真的不是太高级,但是有点乏味。我为您设计了这个,它应该可以满足您的需求。它充满了您可以用来帮助学习代码的评论(如果您想自己再次这样做)。祝你好运!

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. 这是假设您的所有里程碑都相隔两列。

于 2013-01-13T08:09:47.347 回答