二次元配列で任意の一行をカット&挿入(再挑戦)
昨日は、二次元配列で任意の一行に対し何某かを挿入する際、xlUPとxlDownを選択できるようにした。
infoment.hatenablog.com
この結果を踏まえ、先日の ↓ に再挑戦する。
infoment.hatenablog.com
昨日も紹介したように、xlUPで上に押し上げるということは、指定行を一つ下に下げてxlDownするのと同じこと。この部分はたびたび登場するので、切り出して関数化した。
' シフトの方向による、挿入対象列との差分を求める。 ' xlDown ・・・0 ' xlUp ・・・1 Private Function dr(row_shift As Excel.XlDirection) As Long If row_shift <> xlToLeft And row_shift <> xlToRight Then dr = (xlDown - row_shift) / (xlDown - xlUp) End If End Function
数学的に多少なりともテクニカルな部分であるため解説すると、以下の通り。
row_shift = xlDownの場合。
(xlDown - row_shift) / (xlDown - xlUP)
= (xlDown - xlDown) / (xlDown - xlUP)
= 0 / (xlDown - xlUP)
= 0
従って、指定行からの変更は無い。
row_shift = xlUpの場合。
(xlDown - row_shift) / (xlDown - xlUP)
= (xlDown - xlUP) / (xlDown - xlUP)
= 1
従って、指定行の1行下を、指定行に改める。
カット&ペーストの部分にも手を加えた。例えば「貼り付け」なのに、シフト方向を指定しても仕方がないし、xlUpを指定するとエラーになってしまう(一番下に加えようとするとはみ出すため)。その辺りを加味した結果が、こちら。
' カット&ペースト Public Function RowCutAndPaste(ByVal source_row_index As Long, _ ByVal destination_row_index As Long, _ Optional cut_or_copy As Excel.XlCutCopyMode = xlCut, _ Optional overwrite_or_insert As CutAndPasteResult = cpOverWrite, _ Optional row_shift As Excel.XlDirection = xlDown) As Variant Dim arr As Variant arr = source_row_array(source_row_index) ' 貼り付け または 挿入先を準備。 ' 貼り付けの場合は処置不要。 If overwrite_or_insert = cpInsert Then source_array = RowInsert(destination_row_index, row_shift) ' 上書きでxlUpを指定すると、行方向で要素数がオーバーするため、強制的にxlDownとする。 ElseIf overwrite_or_insert = cpOverWrite Then row_shift = xlDown End If ' 貼り付け または 挿入。 For c = cMin To cMax source_array(destination_row_index + dr(row_shift), c) = arr(1, c) Next ' カット または コピー ' コピーの場合は処置不要。 If cut_or_copy = xlCut Then ' 挿入行がカット行以前にある場合、カット行を+1。 If overwrite_or_insert = cpInsert Then If source_row_index >= destination_row_index Then source_row_index = source_row_index + 1 End If End If RowCutAndPaste = RowDelete(source_row_index) Else RowCutAndPaste = source_array End If End Function
以上を踏まえた、クラスモジュールのコード全文が ↓ こちら。
そして、テストした結果がこちら。
Sub test() Dim SQC As SeaquenceClass Set SQC = New SeaquenceClass Dim arr_1() As Variant Dim arr_2() As Variant Dim arr_3() As Variant Dim arr_4() As Variant Dim arr_5() As Variant Dim i As Long For i = 1 To 8 arr_1 = Range("A1").CurrentRegion.Value arr_2 = SQC.TargetArray(arr_1).RowCutAndPaste(4, i, xlCut, cpInsert, xlUp) arr_3 = SQC.TargetArray(arr_1).RowCutAndPaste(4, i, xlCut, cpOverWrite, xlUp) arr_4 = SQC.TargetArray(arr_1).RowCutAndPaste(4, i, xlCopy, cpInsert, xlUp) arr_5 = SQC.TargetArray(arr_1).RowCutAndPaste(4, i, xlCopy, cpOverWrite, xlUp) Range("A12").Resize(UBound(arr_2), UBound(arr_2, 2)) = arr_2 Range("F12").Resize(UBound(arr_3), UBound(arr_3, 2)) = arr_3 Range("A22").Resize(UBound(arr_4), UBound(arr_4, 2)) = arr_4 Range("F22").Resize(UBound(arr_5), UBound(arr_5, 2)) = arr_5 MsgBox i Next End Sub
一応今回も、意図した動きを実現した。
本シリーズの最終回まで、あと2~3回!
以上、参考まで。