VBAの小技 Excelで指定した領域を除外した領域を作る

またまた何か変な小ネタですが…ちょっととあることをやっていると「Excelにおいて、指定した領域のうち、ある部分だけが含まれない状態を作りたい」という不思議な要求が出てきたので、それをかなえるべくVBAで処理を組んでみました。Excel限定ですので多分VBA以外でこんな処理は作れないでしょうし、作る意味もない、というか。

 

コードは…

こんな感じでしょうか。

Function ExcludeRange(rr As Range, re As Range) As Range
    Dim ra As Range, rt As Range, ri As Range, ret As Range

    For ai = 1 To rr.Areas.Count Step 1
        Set ra = rr.Areas(ai)
        For i = 1 To ra.Rows.Count Step 1
            For j = 1 To ra.Columns.Count Step 1
                Set rt = Range(Cells(ra.Row + i - 1, ra.Column + j - 1), Cells(ra.Row + i - 1, ra.Column + j - 1))
                Set ri = Application.Intersect(rt, re)
                If ri Is Nothing Then
                    If ret Is Nothing Then
                        Set ret = rt
                    Else
                        Set ret = Application.Union(ret, rt)
                    End If
                End If
            Next j
        Next i
    Next ai
    Set ExcludeRange = ret 
End Function

 

構想は…

考え方はこの通り。

  • Rangeから直接差のRangeを取り出すことはできないので、「重なっていない」セルだけをくっつけていくしかない
  • 仕方がないので、Forループで一つ一つ領域→行→列を巡回して指されたRangeに重ならないかどうかを調べる(Intersectでのチェック)
  • あとは結果となる領域にくっつけていく

になります。なお、はじめのRangeに含まれているすべてのセルを巡回する特性上、かなり遅いです。参考として出しているだけですので、本気に使いたいのであればもう少し最適化が必要だと思います。(行方向のみに限定したり、列方向に限定する、など)ちゃんとRangeオブジェクトのためにIntersectやらUnionやらOffsetやらの処理はあるのに…。

まあ、ゲームの描画でも、DirtyRect管理で重なっている文の検出やら最小の再描画領域になるようにRectを再構築するなどはありそうですが、指定した範囲の除外なんていうのはほぼ出てこないパターンでしょう。アルゴリズムを考えてみる分には面白いのかもしれませんが。

 


コメントを残す

メールアドレスが公開されることはありません。

この記事のトラックバック用URL