05 行選択ショートカットキーができるまで
前回なんか大急ぎでソースだけ提示してしまって失敗したなぁと思っているさるべーじですこんばんは。
本サイトは一応、
のプロセスの部分をこそお伝えしていきたいといぅか実況生中継といぅかなんかそんな感じでいきたいので。
てことで今回は、前回のソースができるまでのお話となります。
ただしIMEのOn/Offの状況に関わらず。
↓
VBAで組み込んで実装しよう。
ってまず発想の部分はいいですよね?で、ショートカットとしての実装の部分はEXCEL生産性向上委員会のコンテンツ参照ということでいいですよね?
のでここでは主に実装したい機能の中身を作るところを。
Excelに限らずMicrosoft Officeには、Visual Basic for Application(VBA)といぅプログラミング言語が組み込まれています。今さらですが。
このVBA、いかにもVBの仲間だよーって感じのネーミングなんですが、成り立ちはまったく違います。VBがMicrosoft BASICの流れを汲むのに対し、VBAはWordやExcelのマクロからの進化形ですので。
ですから、未だにマクロという言い方がアプリ本体にもヘルプにも残ってしまっています。なんとなく誤解しやすそぅな部分ではありますが、
です。まったくおんなじもんです。マクロを実行するってことは、VBAプログラムを実行するってことなんです。
ので。[新しいマクロの記録]をすると、VBAプログラムが自動作成されます。逆に言えば、作りたいプログラムの主な動作は[新しいマクロの記録]で手に入れることができるってことになります。ふっふっふ。
今回作りたいプログラムは行選択なわけですから、行選択の操作を記録すれば、その部分のコードは手にはいることになります。まずはそこからやってみましょう。
Sub Macro1()これは24行目、G列にカーソルがあるときの動作です。"24:24"ってのは、1つめの数値が開始行、2つめの数値が終了行でしょうか。では、複数行を選択して行選択操作を記録してみれば、ここらへんの数値の変化を確認できそぅですね。試してみましょう。
'
' Macro1 Macro
' マクロ記録日 : 2002/3/1 ユーザー名 : salvage
'
'
Rows("24:24").Select
Range("G24").Activate
End Sub
Sub Macro1()やはり"24:24"→"24:28"に変わりました。
'
' Macro1 Macro
' マクロ記録日 : 2002/3/1 ユーザー名 : salvage
'
'
Rows("24:28").Select
Range("E24").Activate
End Sub
最後のRangeはカレントカーソルを設定するメソッドですが、別にカーソルが移動するわけではなし、不要なよぅな気がするんですけど挿入されているのはなぜでしょうわかりません。
まぁとりあえずRangeメソッドは無視しといて、後で不具合でも出てきたら入れてみるといぅことで。わははは。
となると、後は選択されているセルの一番上と一番下の行番号が取得できればいいんです。 選択されているセルはRangeオブジェクトとして参照できるわけですから、「Rangeオブジェクト」でヘルプをみてみればいいんですよね。
Rangeオブジェクトを使うには、必ず引数として選択セルの行列を指定しなくちゃいけない。って、その選択セルの行を知りたいわけですから。
しかもOfficeのヘルプってむちゃくちゃ使いにくい。てゅうかバグだらけ。
目次はExcel Basic・Office Basic・Visual Basic・Forms Basicで分かれているし、[質問]機能も[キーワード]機能も漏れだらけ。なんだねこれは。Office2000でもXPでも同じへんてこ具合ですし、msdnLibrayならばどぅかと見てみると、2000とXP両方のヘルプが入っちゃってるし。
でもまぁしかたがないので、msdnLibrayの検索機能(なぜVBAのヘルプから[検索]機能がなくなっちゃったのかなぁ…[質問]機能では代替になってないっす)で「Range」をキーワードに引きまくり&読みまくり。
…どぅもRangeオブジェクトは、選択セルの情報を持つさまざまなオブジェクトの定義なだけで、実際のインスタンスはそれぞれ別個に固有名詞がついているよぅです。
自分でセル範囲を指定してどぅこぅしたい時にRangeオブジェクトを直接いじくるってだけの話で、すでに選択されているセル範囲とか名前付けされているセル範囲を参照するにはそれ専用のオブジェクトを使うらしい、と。
これはもぅ単語の見当がつかないので、ヘルプを目次に沿って片っ端から読みまくり。…どぅやらApplicationオブジェクトのSelectionプロパティみたいなんですね。Rangeオブジェクト型のプロパティ。なんだそりゃ。
いゃ、本家VBだってFontプロパティは構造体を持つわけですから、オブジェクト型のプロパティだってあっておかしくはありません。ありませんけど。
などとExcelのオブジェクト構造のデザインにいまいち承伏しかねつつ先へ。
ApplicationオブジェクトのSelectionプロパティアクティブ ウィンドウで現在選択されているオブジェクト(ヘルプより)ででありRangeオブジェクトを返すので、この下の構造はRangeオブジェクトの方の説明を見ろ、といぅことになりますので見ます。
…って、なぜか見ているのはRangeコレクションの項目。どぅもRangeにはコレクションとオブジェクトとプロパティがあるよぅで。
プロパティはオブジェクトの1要素
と理解していた私にはちょっとついていくのが難しいです。
えーと。
Selectionプロパティ=Rangeオブジェクトとして考えていいのかな?で、Rangeコレクションのヘルプがコレクションとオブジェクトをごちゃごちゃに説明しているとして読めば、単純にSelectionオブジェクトのRowプロパティを参照すればいいのかな?であれば、
ということになりますね。実際やってみたら、おっけーでした。
ここまでくれば。
最終行は、最初の行+行数-1で算出できます。あとはこの最初の行と最終行をそれぞれ変数に入れて、それを文字列化したものを間に":"かましてつなげてRows().SelectのRows側の引数にしてやればいいわけです。
で、できあがったのがこれ。
Dim intSttRow As Integerおっけー!後はこれをAuto_Openプロシージャの中にApplication.OnKey "+^ ", "RowsSelect"として入れてExcelの再起動をかければ。
Dim intEndRow As Integer
intSttRow = Selection.Row
intEndRow = Selection.Rows.Count + SttRow - 1
Rows(CStr(intSttRow) & ":" & CStr(intEndRow)).Select
おぉっ、ちゃんと動作するする。Shift+Ctrl+Spaceで行選択ができますよ。
よぅしこれで文書の作成がさくさく効率よくだめだ。
しかたない。2つ以上の選択領域がある時にはエラーのダイアログを出すことでしのぐことにしましょう。
先ほどの、ヘルプのRangeコレクションのページをもぅ一度丹念に読んで。たぶんRangeコレクションの中に選択されている領域の個数まで格納されているはずですから。
…見つけました。Countプロパティ。これでSelection.Countが2以上ならだめだ。Selection.Countは総行数を返す。どぅもSelection.Count=Selection.Rows.Countみたいですね。てゅうか、Selectionの要素省略時デフォルトが行関係のよぅな。
では、領域数のカウントは?といぅと、ヘルプ-Countプロパティの使用例にありました。
てことで、さっきのコードに追加。
Dim SttRow As Integerおっけー!ちゃんと動作(以下略。)
Dim EndRow As Integer
If (Selection.Areas.Count > 1) Then
MsgBox "複数のセル選択領域がある場合には" & vbCrLf _
& "行選択はできません"
Exit Sub
End If
SttRow = Selection.Row
EndRow = Selection.Rows.Count + SttRow - 1
Rows(CStr(SttRow) & ":" _
& CStr(EndRow)).Select
よぅしこれで文書の作成が今度こそさくさく効率よくまだだめだ。
一行おきに一行ずつ行挿入したい時に、ひとつずつ選んで行挿入→繰り返す、なんてやってられるか。
ここはひとつ、複数行選択→一発あちこち挿入をなにがなんでも実装したい。
てことで、調査のし直しからやり直し。
複数領域を選択している時に行挿入をすると、マクロの記録ではどーいぅコードが生成されるか。
Sub Macro1()
'
' Macro1 Macro
' マクロ記録日 : 2002/3/1 ユーザー名 : salvage
'
'
Range("11:11,14:14,18:19").Select
Range("A18").Activate
End Sub
てことは"11:11,14:14,18:19"の部分を文字列として用意してやればいいわけですから。
先ほどの領域数取得の時に、Selectionを選択領域単位で見るときにはAreasを使えばいいといぅことはわかりました。でヘルプで見ると、Rangeコレクションからたどった時に出てくるAreasはプロパティなんですが、その説明はAreasコレクションを返しますといぅ。ご丁寧にAreasコレクションへの文中リンクもあるといぅ。でそちらをたどると、Areasコレクションの説明ページへ。そのページの使い方の中に、Selection.Areas(1).Clearの記述発見。
しかもRangeオブジェクト。
ちなみに3領域選択した時にAreas(0)はエラー、Areas(3)は3つめの領域の要素を返しましたので、Areasの引数は、1~選択領域数(0~選択領域数-1ではない)といぅことになります。
てことは、こぅだ!
Dim intSttRow As Integerおっけー!ちゃんと動作(以下略。)
Dim intEndRow As Integer
Dim strRows As String
Dim i As Integer
'*** 対象行バッファの初期化
strRows = ""
'*** 全ての選択領域の取得
→対象行バッファへ格納(複数選択領域に対応)
For i = 1 To Selection.Areas.Count
If (strRows <> "") Then strRows = strRows & ","
intSttRow = Selection.Areas(i).Row
intEndRow = intSttRow _
+ Selection.Areas(i).Rows.Count - 1
strRows = strRows & CStr(intSttRow) _
& ":" & CStr(intEndRow)
Next
'*** 選択領域の行選択
Range(strRows).Select
以上、ここまでと前回Upしたソースとなります。
いやぁ苦労しましたしました。わずか十数行のコードを書くのに
ってまとめに入ろぅとしたら、前述EXCEL生産性向上委員会の玉蔵さんがこのページを見てくださって、
(北海道弁意訳)
との熱いメッセージが。
試しにやってみたら…ってExcelXPのMax行番号65536。すでにこの時点でアウト。念のためにやってみたら
オーバーフローしました。
そりゃそぅですね。
てことでさらに修正。真のコードはこれだぁ!
Sub RowsSelect()いつのまに32767の壁を突破していたんだExcel。列数はIV=256までなのは変わらないくせに(いゃ昔は128までだったか?)。
Dim lngSttRow As Long
Dim lngEndRow As Long
Dim strRows As String
Dim i As Long
'*** 対象行バッファの初期化
strRows = ""
'*** 全ての選択領域の取得
→対象行バッファへ格納(複数選択領域に対応)
For i = 1 To Selection.Areas.Count
If (strRows <> "") Then strRows = strRows & ","
lngSttRow = Selection.Areas(i).Row
lngEndRow = lngSttRow _
+ Selection.Areas(i).Rows.Count - 1
strRows = strRows & CStr(lngSttRow) _
& ":" & CStr(lngEndRow)
Next
'*** 選択領域の行選択
Range(strRows).Select
End Sub
玉蔵さん、ありがとうございました。
また前回のコードを真に受けた読者諸氏は今回のコードに差し替えるようお願い申しあげたく平に。
まぁそんなこともあるさっ。
コメント
EXCEL利用者の一人です。以前から気になっていたデータ入力の際に行選択(Shift+Space)ショーカットが使えなくなる理由が判ってすっきりしました。その上対処法まで・・・。良い情報をありがとうございます。
投稿者: 修行僧 | 2007年07月16日 22:58
あまり話題になりませんが、実はOfficeについてはIMEの存在やキーボードレイアウトの違いなど、日本語環境での特異性がけっこうあちこちにあったりします。
メーカーが対処してくれないのであれば自力で何とかしなければならない、ってのがちょっと大変ですよね。
投稿者: さるべーじ | 2007年07月18日 08:12