|
こんな物かな?
Option Explicit
Public Sub AddUp()
Dim i As Long
Dim vntData As Variant
Dim rngListTop As Range
Dim rngScopeCol As Range
Dim rngColItem As Range
Dim lngColNum As Long
Dim rngScopeRow As Range
Dim rngRowItem As Range
Dim lngRowNum As Long
Dim lngFindCol As Long
Dim lngFindRow As Long
Dim lngOver As Long
'デ−タの有るシートのデータを配列に取得
'デ−タの左上隅のセルを設定
If Not GetData(vntData, _
Worksheets("Sheet1").Cells(1, "A")) Then
Beep
MsgBox "データが有りません"
Exit Sub
End If
Application.ScreenUpdating = False
'表を作るシートに就いて
With Worksheets("Sheet2")
'シートをクリア
.Cells.Clear
'表の先頭(左上隅のセル)を設定
Set rngListTop = .Cells(1, "A")
End With
With rngListTop
'列項目の初期値
Set rngColItem = .Offset(, 1)
lngColNum = 1
'行項目の初期値
Set rngRowItem = .Offset(1)
lngRowNum = 1
'表に転記
For i = 1 To UBound(vntData, 1)
'A列値の探索範囲の取得
Set rngScopeRow = rngRowItem.Resize(lngRowNum)
'A列値の行位置を探索
lngFindRow = ItemSearch(vntData(i, 1), _
rngScopeRow, lngOver, 1)
'探索値が無かった場合(未発見)
If lngFindRow = 0 Then
'探索範囲行数を更新
lngRowNum = lngRowNum + 1
'挿入位置に行を挿入
With .Offset(lngOver)
.EntireRow.Insert
End With
'挿入行位置を発見行位置に設定
lngFindRow = lngOver
'行項目の初期値を再設定
Set rngRowItem = .Offset(1)
'挿入行位置にA列値を記入
With .Offset(lngFindRow)
.Value = vntData(i, 1)
End With
End If
'日付の範囲を設定
Set rngScopeCol = rngColItem.Resize(, lngColNum)
'日付を探索
lngFindCol = ItemSearch(CLng(vntData(i, 2)), _
rngScopeCol, lngOver, 1)
'日付が無かった場合(未発見)
If lngFindCol = 0 Then
'探索範囲列数を更新
lngColNum = lngColNum + 1
'挿入位置に列を挿入
With .Offset(, lngOver)
.EntireColumn.Insert
End With
'挿入位置を発見位置に設定
lngFindCol = lngOver
'列項目の初期値を再設定
Set rngColItem = .Offset(, 1)
'挿入列位置に日付を記入
With .Offset(, lngFindCol)
'日付を記入
.Value = CLng(vntData(i, 2))
End With
End If
'発見した行列に値を記入
With .Offset(lngFindRow, lngFindCol)
.Value = .Value + 1
End With
Next i
'書式を日付に設定
rngScopeCol.NumberFormat = "yyyy/mm/dd"
End With
Set rngScopeCol = Nothing
Set rngScopeRow = Nothing
Set rngListTop = Nothing
Set rngColItem = Nothing
Set rngRowItem = Nothing
Application.ScreenUpdating = True
Beep
MsgBox "処理が完了しました"
End Sub
Private Function GetData(vntData As Variant, _
rngDataTop As Range) As Boolean
Dim rngScope As Range
Set rngScope = rngDataTop.CurrentRegion
With rngScope
'もし、データが有る場合
If .Columns.Count >= 1 And .Rows.Count >= 1 Then
'wksDataのデータを配列に取得
vntData = .Value
'データ取得成功を戻す
GetData = True
End If
End With
Set rngScope = Nothing
End Function
Private Function ItemSearch(vntKey As Variant, _
rngScope As Range, _
Optional lngOver As Long, _
Optional lngCollation As Long = 1) As Long
Dim vntFind As Variant
Dim lngDataTop As Long
If rngScope Is Nothing Then
lngOver = 1
Exit Function
End If
'Matchによる二分探索
vntFind = Application.Match(vntKey, rngScope, lngCollation)
'もし、エラーで無いなら
If Not IsError(vntFind) Then
'もし、Key値と探索位置の値が等しいなら
If vntKey = rngScope.Cells(vntFind).Value Then
'戻り値として、位置を代入
ItemSearch = vntFind
End If
'Key値を超える最小値のある行
lngOver = vntFind + 1
Else
lngOver = 1
End If
End Function
|
|