アドベントカレンダー 24日目
データを蓄積してそれを最後にセルに出力するなんてことはあると思うのですが
データ量が増えるとエクセルに出力する部分がえらく時間がかかるようになります
高速で出力するには、配列に格納して出力するのが最速となります。
ただ…
出力する時に行と列をいれかえる必要があったりCollectionならAddするだけで
要素が追加できるとこをいちいち、要素数が存在しない時と存在する時で処理を
分岐して毎回Redim Preserveしなきゃいけないなんてのはめんどくさい以外の
何者でもありません。
そういうのは、裏側でこっそり処理して表側には見えないようにしてあげた方が便利よいですよね。
そんなわけで、セルに出力することに特化させた二次元配列のクラスを作ってみました。
好きな名前でもつけてくださいな。
使い方ですがサンプル内にコメントで追加しました。
■値の追加、値の取り出し
データを蓄積してそれを最後にセルに出力するなんてことはあると思うのですが
データ量が増えるとエクセルに出力する部分がえらく時間がかかるようになります
高速で出力するには、配列に格納して出力するのが最速となります。
ただ…
出力する時に行と列をいれかえる必要があったりCollectionならAddするだけで
要素が追加できるとこをいちいち、要素数が存在しない時と存在する時で処理を
分岐して毎回Redim Preserveしなきゃいけないなんてのはめんどくさい以外の
何者でもありません。
そういうのは、裏側でこっそり処理して表側には見えないようにしてあげた方が便利よいですよね。
そんなわけで、セルに出力することに特化させた二次元配列のクラスを作ってみました。
- Option Explicit
- Dim Data() As String
- Dim x As Long
- Dim y As Long
- Dim DelColumn As Integer
- 'Setter/Getter
- Public Property Let DeleteColumn(ByVal num As Integer)
- DelColumn = num
- End Property
- Public Property Get DeleteColumn() As Integer
- DeleteColumn = DelColumn
- End Property
- Private Sub Class_Initialize()
- '初期化
- x = -1
- y = -1
- End Sub
- Function Count()
- '要素数を返す
- Count = UBound(Data, 2) + 1
- End Function
- Function Item(ByVal a As Long, ByVal b As Long)
- '要素の値を返す
- Item = Data(a, b)
- End Function
- Function Last()
- '最終要素を返す
- Last = UBound(Data, 2)
- End Function
- Private Function TransposeData()
- Dim s As Long
- Dim t As Long
- Dim TPData() As String
- ReDim TPData(y, x)
- For s = 0 To y
- For t = 0 To x
- TPData(s, t) = Data(t, s)
- Next
- Next
- TransposeData = TPData
- End Function
- Function Value() As String()
- '2次元配列自体を返す
- Value = Data()
- End Function
- Sub Add(ByRef list As Variant)
- Dim i As Long
- '1次元の要素数が確定していない時、要素数の調査をおこなう
- If x = -1 Then
- If TypeName(list) = "Variant()" Then
- x = UBound(list)
- Else
- x = 0
- End If
- End If
- '要素数の再定義
- y = y + 1
- ReDim Preserve Data(x, y)
- If TypeName(list) = "Variant()" Then
- For i = 0 To x
- '要素数が足りないときは、空文字を指定
- On Error Resume Next
- Data(i, y) = list(i)
- On Error GoTo 0
- Next
- Else
- Data(x, y) = list
- End If
- End Sub
- Sub Clear()
- Erase Data
- DelColumn = -1
- x = -1
- y = -1
- End Sub
- Sub Output(ByVal Sht As Worksheet, ByVal Cell As String)
- Dim BaseRow As Long
- Dim BaseCol As Long
- BaseRow = Sht.Range(Cell).Row
- BaseCol = Sht.Range(Cell).Column
- 'DelColumnが1以上でセットされている時該当列をクリアする
- If 0 < DelColumn Then
- Sht.Range(Sht.Cells(BaseRow, BaseCol), Sht.Cells(65536, BaseCol + DelColumn)).Clear
- End If
- Sht.Range(Sht.Cells(BaseRow, BaseCol), Sht.Cells(BaseRow + y, BaseCol + x)) = TransposeData()
- End Sub
- Option Explicit
- Sub SampleCode1()
- Dim Data As New Hogehoge
- Dim i As Long
- 'Addメソッドに対し、Array関数で配列を作って渡せばよいです
- Call Data.Add(Array("A01", "B05", "C001", "D1", "なんとなくだめ"))
- Call Data.Add(Array("A01", "B10", "C002", "D2", "それとなくだめ"))
- Call Data.Add(Array("A01", "B15", "C003", "D3", "そこはかとなくだめ"))
- Call Data.Add(Array("A01", "B20", "C004", "D4", String(256, "■")))
- '一つ一つのデータにアクセスしたい場合はItemメソッドで
- '通常の二次元配列のようにアクセスするとよいです。
- For i = 0 To Data.Last
- Debug.Print Data.Item(0, i) & Data.Item(1, i) & Data.Item(2, i)
- Next
- '出力する際、いちいち領域を指定する必要はありません。
- '出力したいシートのオブジェクトと左上のセルを指定するだけで十分です。
- Call Data.Output(ThisWorkbook.ActiveSheet, "B3")
- '連続してコードを実行して出力する場合、前回出力したデータが残ってしまうので
- '出力時に該当する行より後ろの行をClearしたい時は、事前に列数を指定すると削除してくれます。
- Data.DeleteColumn = 5
- Call Data.Output(ThisWorkbook.ActiveSheet, "B3")
- 'Clearメソッドで初期化されます。
- Call Data.Clear
- '一元配列ならいちいちArray関数にいれる必要はありません。
- Call Data.Add("abc")
- Call Data.Add("def")
- Call Data.Add("ghi")
- Call Data.Output(ThisWorkbook.ActiveSheet, "A10")
- End Sub
0 件のコメント:
コメントを投稿