デシまるのブログ(Amazing!!) -4ページ目

デシまるのブログ(Amazing!!)

やる気がありません。どこに売ってますか?

Microsoft Office 365 Solo(1年版) [オンラインコード] [ダウンロ.../マイクロソフト
¥11,800
Amazon.co.jp


これまで仕様書とか設計書とか作るときにExcelを使うことがなかったのですが、
今の現場ではExcelで作ることも多いらしく、慣例に則って作っていたのですが、、、ふとレビューのとき

「目次作ってね。章ごとにリンク貼って飛べるように。」

ファ!?

テンプレとした元の資料には目次なんか無かったっすけど。。。いや、、、はい。

その時は時間が無かったのと、そこまでの量じゃなかったのでせっせと作りましたが、今後も同じこと言われそうなのでマクロを作っておきました。

やりたいことは大したことではなくてこれだけ
・シートのA列を章タイトルとして使用しているので、空白じゃなければ章としてリンクを作成
・ページ番号をリンクの横に出す


ということでソースは下。

※アメブロってソースきれいに貼れない。。。syntaxhighlighterとか入れたいけどなぁ。。


-----------------------------------------------------

' 「目次」シート名
Const CONTENTS_PAGE_NAME As String = "目次"

' 目次出力開始位置
Const START_POSITION As String = "B3"

' 目次出力時にクリアする領域
Const OUTPUT_AREA As String = "B:C"

' 見出し検索行数
Const SEARCH_ROW_MAX As Long = 65535


' 目次作成開始
Public Sub CreateContents()

Dim contentsSheetIndex As Integer
contentsSheetIndex = FindWorksheet(CONTENTS_PAGE_NAME)
If contentsSheetIndex >= 0 Then
CreateIndexInner (contentsSheetIndex)

Else
MsgBox "シート名が「目次」のシートを作成してください。", vbOKOnly
End If

End Sub

' シート名でシートを探してIndexを返す
Private Function FindWorksheet(ByVal searchSheetTitle As String) As Integer
Dim result As Integer: result = -1

Dim i As Integer
Dim sheet As Worksheet
For i = 1 To Worksheets.Count
Set sheet = Worksheets(i)
If sheet.Name = searchSheetTitle Then
result = i
Exit For
End If
Next

FindWorksheet = result
End Function

' 目次作成処理
Private Sub CreateIndexInner(ByVal contentsSheetIndex As Integer)

Dim sheetIndex As Integer
Dim contentsSheet, currentSheet As Worksheet
Dim contentsRange, currentRange As Range
Dim i, pageCount As Long

Set contentsSheet = Worksheets(contentsSheetIndex)
Set contentsRange = contentsSheet.Range(START_POSITION)
pageCount = 0

'--- 出力エリアのクリア
contentsSheet.Range(OUTPUT_AREA).Hyperlinks.Delete
contentsSheet.Range(OUTPUT_AREA).Value = ""

For sheetIndex = contentsSheetIndex + 1 To Worksheets.Count
Set currentSheet = Worksheets(sheetIndex)
'--- 見出しのリンクを作成
For i = 1 To SEARCH_ROW_MAX
Set currentRange = currentSheet.Range("A1").Offset(i, 0)
If currentRange.Value <> "" Then
contentsSheet.Hyperlinks.Add Anchor:=contentsRange, Address:="", SubAddress:=(currentSheet.Name & "!" & currentRange.Address), TextToDisplay:=currentRange.Value
contentsRange.Offset(0, 1).Value = pageCount + GetPageNumber(currentRange)
Set contentsRange = contentsRange.Offset(1, 0)
End If
Next

pageCount = pageCount + GetSheetPageCount(sheetIndex)
Next

End Sub

' 指定Rangeが印刷時、何ページ目に印刷されるかを返す
Private Function GetPageNumber(rng As Range) As Long
Dim result As Long

Dim hpb As HPageBreak
Dim vpb As VPageBreak
Dim hCount, vCount As Long

hCount = 0
vCount = 0

For Each hpb In rng.Parent.HPageBreaks
If hpb.Location.Row <= rng.Row Then hCount = hCount + 1
Next

For Each vpb In rng.Parent.VPageBreaks
If vpb.Location.Column <= rng.Column Then vCount = vCount + 1
Next

If rng.Parent.PageSetup.Order = xlDownThenOver Then
'印刷方向が左から右の時
result = vCount * (rng.Parent.HPageBreaks.Count + 1) + hCount + 1

Else
'印刷方向が上から下の時
result = hCount * (rng.Parent.VPageBreaks.Count + 1) + vCount + 1

End If

GetPageNumber = result
End Function

' 指定シートの印刷総ページ数を返す
Private Function GetSheetPageCount(ByVal sheetIndex As Integer)
Dim result As Long

Dim sheet As Worksheet
Set sheet = Worksheets(sheetIndex)
result = (sheet.HPageBreaks.Count + 1) * (sheet.VPageBreaks.Count + 1)

GetSheetPageCount = result
End Function
------------------------------------------------------

モジュール作ってペタッとしてください。
「目次」っていうシートを作っておいて、それを目次を作成したいシートの手前に移動して、マクロを実行してください。

A列の検索は65535行でやめちゃったりしてるところとか、出力先とか
適当にいじって使ってください。

一応、動作確認したファイルも置いておきます。
目次自動作成.xlsm


Microsoft Office Home and Business 2013 [オンラインコ.../マイクロソフト
Amazon.co.jp