« LibreOffice を C# アプリから操作 | トップページ | Github は危害を加える可能性があるサイト? »

2020年5月12日 (火)

Excel VBA でウィンドウ枠の固定位置を調べる

Excel の VBA(Visual Basic for Application; 要は Excel 用のマクロ言語)で、「ウィンドウ枠の固定」がしてあるワークシートの、固定位置を調べたくて、方法をウェブで調べた。


だが、見つからない。


しかたがないから MSDN の Excel object model を読みまくって自分で書いた。こんな感じで固定位置(ウィンドウ枠の固定を行った際に固定の基準にしたセル)を調べることができる。


Sub Macro1()
    Dim r As Long, c As Long, i As Integer
    With ActiveWindow
        r = .ScrollRow
        c = .ScrollColumn
        For i = 1 To .Panes.Count
            With .Panes(i)
                r = Min(r, .ScrollRow + .VisibleRange.Rows.Count)
                c = Min(c, .ScrollColumn + .VisibleRange.Columns.Count)
            End With
        Next i
    End With
   
    MsgBox Cells(r, c).Address(False, False)
End Sub


Function Min(x As Long, y As Long)
    If (x < y) Then
        Min = x
    Else
        Min = y
    End If
End Function

※ 上では Min という関数を定義して Macro1 の中で使っているが、もちろんこれはベタ書きしてもいい。


ただし注意点がある。Excel には freeze panes(日本語版では「ウィンドウ枠の固定」)という機能と split panes (日本語版では単に「分割」)という似ているが少し違う機能がある。上のマクロで使っているプロパティは両者の兼用なので、「ウィンドウ枠の固定」ではなく「分割」を行っている場合には誤動作してしまう。本来はあらかじめ ActiveWindow.Split の値を調べて、これが true だったら(true は「分割」が行われていることを示す)「ウィンドウ枠の固定」は行われていないとみなして一律に A1 にするとか、そういう配慮が必要だろう。


ちなみに、最初に解法を探した中で最も参考になったのは「インストラクターのネタ帳」のこのページの記事だった。実はこのサイトにはよくお世話になっている。大変充実したサイトだ。インストラクターのネタ帳に「いつでも正しい結果となるわけではありません 」という注意書き付きの不完全なマクロしかないのを見つけたときには、VBA できちんと調べることは不可能なのかと思って目の前が真っ暗になった…。




ということで、VBAの体で記事にしたが、本当のことを言うと、今回私はVBAでマクロを書いているわけではない。そもそも VBA なんて滅多に書かない。NetOfficeを使うC#のコードを書いているのだ。ExcelやWordのVBA用のオブジェクトモデルというのは COM でできていて、Office PIAとかNetOfficeというのはその COM オブジェクトを CLI から使うラッパーだから、使い方も VBA とほとんど同じ。Office PIA や NetOffice の情報に比べると、VBA の情報の方が圧倒的に多いので、困ったときには NetOffice の情報を探すよりも VBA の情報を探す方が良い情報が見つかりやすいのだ。それで、VBA を使うわけでもないのに「インストラクターのネタ帳」にいつもお世話になっている次第だ。

« LibreOffice を C# アプリから操作 | トップページ | Github は危害を加える可能性があるサイト? »

コメント

コメントを書く

(ウェブ上には掲載しません)

« LibreOffice を C# アプリから操作 | トップページ | Github は危害を加える可能性があるサイト? »