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

行ごとにデータ値が空である場合と空でない場合がある、非正規化されたデータセットがあります。それらを正規化する必要があります。

すなわち

        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 個の関連付けられた日付の名前を持つプロジェクト データを含む約 100 行があり、これらを分割して、マイルストーン ヘッダー/マイルストーン名/プロジェクト コードごとの日付をリストする複数の行を作成する必要があります....マイルストーンの場合名前とデータは空白です。レコードはスキップできます...

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。これは、すべてのマイルストーンが 2 列離れていることを前提としています。

于 2013-01-13T08:09:47.347 に答える