参照元に参照先の通し行番号を書き込む(1)
参照元に参照先の通し行番号を書き込む(1)
Wordの本文中で、参照箇所を明示したいときがある。段落番号とか見出しだったら、「相互参照」機能を使って文中に挿入できて、変更にも追随してくれるから良いのだが、通し行番号だけは、どうにもやり方がわからなかった。(もし「標準機能にあるで!」というのがあれば教えろ教えてください。)
行番号の参照などというものは、常に揺れ動くものなので、手動で管理するのは死ぬほどめんどくさいし、絶対に修正漏れが起こる。そこで、「ブックマーク」機能を使って解消することを考えた。
基本的には前回
までの続きです。
Bookmarkオブジェクトを使う
考え方
「ブックマーク」という機能を使えば、文書中の任意の場所に名前を付けることができる。VBAでは、Bookmark
オブジェクトを操作することによって、「ブックマーク」機能を使うことができる。
そこで、次のように考えた。
- 参照先の箇所にブックマークを設定する
- 参照元の「○行目」の行番号の部分(「○」の部分。)にブックマークを設定する
- 前回作成したFunctionを用いて、参照先の通し行番号を取得する
- 取得した行番号を文字列型に変換して「○」の部分に上書きする
こんな感じ。
ブックマークの設定
とりあえず、今回は手動で設定する。
まずは参照先。
このように、64行目の先頭に「参照先01」というブックマークを設定。
次に参照元。
このように、「○行目」の「○」の部分に「参照元01」というブックマークを設定。
以上。
ブックマークした箇所(Rangeオブジェクト)の取得
まず、上記で設定したブックマークについて、Bookmark
オブジェクトを取得する方法。
これは、まずDocument
オブジェクトのBookmarks
プロパティを参照してBookmarks
コレクションを取得する。
んで、あとはItem
メソッドのインデックスに取得したいブックマークの名前を指定すれば良い。
Item
は省略できるので、実際の書き方は
Document.Bookmarks("[ブックマーク名]")
になる。
Bookmark
オブジェクトが取得できれば、あとはそのRange
プロパティを参照すれば、ブックマークした箇所のRange
オブジェクトが取得できる。実に簡単。
参照元の文字を行番号に置き換える
参照元の「○」の部分をRange
オブジェクトとして取得しているのだから、あとはそのText
プロパティを書き換えたら良い。
楽勝!
コード
参照元に参照先の通し番号を挿入するコードは次の通り。
処理の中で、前回作成したgetLineNumber
メソッドを呼び出しているので、そのコード(標準モジュールLineNumUtil
に記載。)も再掲する。
リスト1 標準モジュール ModuleMain
Private Sub test00() Dim Doc As Document Set Doc = Application.ActiveDocument '参照元のブックマークオブジェクトを取得' Dim bm As Bookmark Set bm = Doc.Bookmarks("参照元01") '参照先ブックマークの通し行位置を取得' Dim lineNum As Long lineNum = LineNumUtil.getLineNumber(Doc.Bookmarks("参照先01").Range) '参照元のテキストを書き換える' bm.Range.Text = CStr(lineNum) End Sub
リスト2 標準モジュール LineNumUtil
Public Function getLineNumber( _ ByVal tgtRange As Range) As Long Dim ret As Long 'tgtRangeのあるページ番号を取得' Dim currPage As Long currPage = tgtRange.Information(wdActiveEndPageNumber) 'tgtRangeのあるページ内での行番号を取得' Dim currLine As Long currLine = tgtRange.Information(wdFirstCharacterLineNumber) 'tgtRangeが1ページ目にあるときは、その行番号を返す' If currPage = 1 Then ret = currLine GoTo Finalizer: End If '2ページ以上ある時は、手前のページまでの累計を足さなければいけない' Dim Doc As Document Set Doc = tgtRange.Parent 'カーソル位置を記録' Dim orgRange As Range Set orgRange = Selection.Range '文書の先頭にカーソルを置く' Call Doc.Range(0, 0).Select '1ページ目の最終位置を取得' Dim pageEnd As Long '1ページ目の最終位置を選択' Dim i As Long For i = 1 To currPage - 1 pageEnd = Doc.Bookmarks("\Page").End Call Doc.Range(pageEnd - 1, pageEnd - 1).Select ret = ret + Selection.Range.Information(wdFirstCharacterLineNumber) '次のページの先頭へ' Call Selection.MoveRight(wdCharacter, 1, wdMove) Next ret = ret + currLine 'カーソル位置を戻す' Call orgRange.Select Finalizer: getLineNumber = ret End Function
例によって細かくコメントを入れたので、説明は省略。
うむ。これで盤石のはずだ!
使ってみる
リスト1を実行すると、
ウホッ! 完璧!
こんどは、
こんなふうにテキトーに参照先の位置をズレータにしておいて、再度実行!
キ、キバヤシ……。これは一体どういうことなんだよ……。
あふれる涙を抑えながら「ブックマーク」を調べると、
なんと、テキストを書き換えたブックマーク(参照元01)が消えとる……orz
おわりに
どうも間違えてロンしてしまったか、フリテンだったようだ。
もう一工夫必要だということだ。
WordVBAはおれを甘やかしてくれぬ……。
で、今回の教訓。
BookmarkオブジェクトのRange.Textを書き換えるとBookmarkオブジェクトは消滅する。
覚えておこう。