05 ブックとシートをシンクロさせる(2)
検証環境 SONY VAIO PCG-U1(Crusoe860MHz/240MB)
WinXPHomeSP1/IE6.0SP1/MSExcel2002SP2
なんだかいろいろぼーとかしているうちに、前稿からすでに2年近く経ってしまいました。
いゃ決してTabと戦うのをあきらめたわけじゃなかったんですよ。えぇえぇいませんでしたとも。ほんとですって。
たゆまぬ努力で改良し続けていましたってば。けっして2年ぶりにふっと気が向いたんじゃありませんって(^^;)。
とはいぅものの、自分でもちょっと前回までの話を忘れてるよぅな気がしますので、まずはおさらい。
まず、UserFormをひとつ作成し、frmTatakauと名前を付けました。
で、CommanButtonを1個、ListBoxを2個貼り付けました。
で、このfrmTatakauに書き込んだコードはだいたいこんな感じ。
前回までにお見せしたものから、コメント回りをちょっといじってありますが、コードそのものは変更していません。
Option Explicitちょっと長いですが、勘弁してください。
'****************
' UserForm起動時
'****************
Private Sub UserForm_Initialize()
Call sGetAllBooks 'Book情報の取得と表示
Call sGetSheets(ActiveWorkbook) 'Sheet情報の取得と表示
End Sub
'**************
' 再取得ボタン
'**************
Private Sub cmdGetSheets_Click()
Call sGetAllBooks 'Book情報の取得と表示
Call sGetSheets(ActiveWorkbook) 'Sheet情報の取得と表示
End Sub
'****************************************
' Book再選択によるシート情報の取得と表示
'****************************************
Private Sub lstWorkbooks_Click()
Workbooks(lstWorkbooks.List(lstWorkbooks.ListIndex)).Activate
Call sGetSheets(ActiveWorkbook)
End Sub
'**********************************************
' Excelにロードされている全Book情報の取得と表示
'**********************************************
Private Sub sGetAllBooks()
Dim i As Integer
'*** ExcelにロードされているBookの名前をListBoxに表示する
'ListBoxのClear
lstWorkbooks.Clear
'Book名→ListBox
For i = 1 To Workbooks.Count
If (LCase(Workbooks(i).Name) <> "personal.xls") Then
lstWorkbooks.AddItem Workbooks(i).Name
End If
Next
'*** 現在ExcelでカレントになっているいるBookの行を選択状態にする
For i = 0 To Workbooks.Count - 1
If (lstWorkbooks.List(i, 0) = ActiveWorkbook.Name) Then
lstWorkbooks.Selected(i) = True
Exit For
End If
Next
End Sub
'****************************************
' 指定されたBookの全Sheet情報の取得と表示
'****************************************
Private Sub sGetSheets(wbSlct As Workbook)
Dim i As Integer
'*** 指定されたBook中のSheetの名前をListBoxに表示する
'ListBoxのClear
lstSheets.Clear
'Sheet名→ListBox
For i = 1 To wbSlct.Sheets.Count
lstSheets.AddItem wbSlct.Sheets(i).Name
Next
'*** 現在ExcelでカレントになっているSheetの行を選択状態にする
For i = 0 To wbSlct.Sheets.Count - 1
If (lstSheets.List(i, 0) = wbSlct.ActiveSheet.Name) Then
lstSheets.Selected(i) = True
Exit For
End If
Next
End Sub
これからもっと長くなりますので、覚悟してください。
で、先に進む前に。
なんで思わせぶりなヒキにしたのか今となっては自分でもわからないんですが。
Book選択時にExcel側のカレントBookを変更シンクロさせる機能は説明しといて、Sheet選択時にExcel側のカレントSheetをシンクロさせるコードを説明していなかったんですね私。
こんなもん何ほどのもんでもないので、さくっとこんなコードを足しておきましょう。
'********************************これで準備完了。先へ進みます。
' Sheet一覧と表示Sheetのシンクロ
'********************************
Private Sub lstSheets_Click()
ActiveWorkbook.Worksheets(lstSheets.List(lstSheets.ListIndex)).Activate
End Sub
さてこれでイケるかなだめだ。
考えてみれば当たり前ですね。
Workbook単位で考えてると、1つのWorkbookで複数のウィンドウを開いていると対応できません。
てことは、Workbook単位ではなく、表示されているウィンドウ単位で考えていかないばなんない、ってことですね。
えーと、WorkbookオブジェクトはWindowsコレクションを持ってるんですね。ので、こいつのWindowNumberを基準にウィンドウを指定してやればいいんです。
てことで、表示をWorkbook名+indexに変えてクリック時にアクティブにするのもWorkbook指定ではなくWindow単位に変更。
あ、でも、Winodwを1つしか持たないWorkbookの場合はWindowNumberを表示しない方がいいですね。Excelのウィンドウキャプションがそんな感じですから、合わせた方が操作時に違和感がないっぽいので。
'**********************************************えーと。
' Excelにロードされている全Book情報の取得と表示
'**********************************************
Private Sub sGetAllBooks()
Dim i As Long
Dim j As Long
Dim strWinName As String
Dim lngListIndex As Long
'*** ExcelにロードされているBookの名前をListBoxに表示する
'ListBoxのClear
lstWorkBooks.Clear
'Book名→ListBox
For i = 1 To Workbooks.Count
If (LCase(Workbooks(i).Name) <> "personal.xls") Then
If (Workbooks(i).Windows.Count <= 1) Then
strWinName = Workbooks(i).Name
lstWorkBooks.AddItem Workbooks(i).Name
If (strWinName = ActiveWorkbook.Name) Then
lngListIndex = lstWorkBooks.ListCount - 1
End If
Else
For j = 1 To Workbooks(i).Windows.Count
strWinName = Workbooks(i).Name & ":" _
& Workbooks(i).Windows(j).WindowNumber
lstWorkBooks.AddItem strWinName
If (strWinName = ActiveWorkbook.Name & ":" _
& CStr(ActiveWindow.WindowNumber)) Then
lngListIndex = lstWorkBooks.ListCount - 1
End If
Next
End If
End If
Next
'*** 現在Excelで表示されているBookの行を選択状態にする
lstWorkBooks.Selected(lngListIndex) = True
End If
まず、ロードされているWorkBook総当たりってループはそのままで。
ループ内部では、まずそのWorkBookがWindowをいくつ持っているかを判定しています。
1つ以下だったらファイル名のみ。2つ以上であればWindowの数だけ、ファイル名+WindowNumberを表示させます。
取得したWindow一覧の中からアクティブウィンドウを探すのは、後からではもう一度同じようなループを書かなければならなくなりますので、このループの中で同時に判定、ListBoxのIndexを覚えておいて、ループ終了後に選択状態にさせるようにしています。
で、表示をWindow単位に変更してしまったわけですから、クリックした時に選択されるのもWindow単位にしなければなりませんね。
'****************************************WindowNumberって取得しかできないプロパティですので、これを指定して一発ポンでアクティブにするウィンドウを指定することができません。
' Book再選択によるシート情報の取得と表示
'****************************************
Private Sub lstWorkBooks_Click()
Dim strBookName As String
Dim lngWindowCnt As Long
Dim i As Long
strBookName = lstWorkbooks.List(lstWorkbooks.ListIndex)
If (InStr(strBookName, ":") > 0) Then
lngWindowCnt = CLng(Mid$(strBookName, InStr(strBookName, ":") + 1))
strBookName = Left$(strBookName, InStr(strBookName, ":") - 1)
For i = 1 To Workbooks(strBookName).Windows.Count
If (Workbooks(strBookName).Windows(i).WindowNumber = lngWindowCnt) Then
Workbooks(strBookName).Windows(i).Activate
Exit For
End If
Next
Else
Workbooks(strBookName).Activate
End If
Call sGetSheets(ActiveWorkbook)
End Sub
ので冗長ですが、当該WorkBookに含まれるWindowをindex基準でブン回して、おめあてのWindowNumberを持つウィンドウを探し出してやらなければなりません。
で、結果はこんな感じで。
これでだいたい、欲しかった機能を用意することができました。 では次回は、もうちょっとだけ使いやすく。