[[20110305030124]] 『マクロによるシート切替について』(初心者) ページの最後に飛ぶ

[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]

 

『マクロによるシート切替について』(初心者)
 Excel2003  WindowsXPを使用しています。 
 全文検索で下記のマクロを見つけて使わせて頂こうと
 思っています。ボタンに登録して次のシートに切り替わって
 いきます。
 Sub 右シートへ()
  '右隣のシートをアクティブにする
  ActiveSheet.Next.Activate
 END SUB
 今回の質問ですが、最右のシートにきた時
 次のシートがないのでマクロがエラーになります。
 現在の対応策はこれも全文検索で見つけた
 On Error Resume Next
 ActiveSheet.Next.Activate
 という形にしてエラー発生時は何も処理をしない
 ようにしていますが、「最終シートです」とか「次の
 シートはありません」とかのMSGBOXを表示させたい
 と考えていますが、エラーが発生したらMSGBOXを
 表示させる構文の書き方がわかりません。
 どのように書けばいいでしょうか。
 よろしくお願いします。 
 ------------

 さらに全文検索をして解決策がありました。
 Sub 右シートへ()
  '右隣のシートをアクティブにする
   On Error GoTo err1
  ActiveSheet.Next.Activate
     Exit Sub
 err1:
 MsgBox "最終シートです"
 End Sub

 にてエラー時MSGBOXを表示することができました。
 エラー処理を他の構文に(マクロ)作って、起動していました。
 同じ構文のなかにエラー処理を記述しなくてはいけない
 ことがわかりました。
 (初心者)


 VBAはシートをインデックス番号で表すことが出来ます。
 「前から数えて ○番目のシート」
 と言った感じです。

 現在のシートが何番目のシートなのか
 全部でシートが何枚有るのか
 それぞれ調べて、比較をすることでも
 メッセージボックスを表示させる事が出来ると思います。
    Sub 右シートへ1()
    '右隣のシートをアクティブにする
        If ActiveSheet.Index = Sheets.Count Then
            MsgBox "最終シートです。"
        Else
            ActiveSheet.Next.Activate
        End If
    End Sub
 左端かどうかを確認するには、「1」と比べると良いかもしれません。

 また、インデックス番号を利用してシートを移動しても良いですね。
    Sub 右シートへ2()
    '右隣のシートをアクティブにする
        If ActiveSheet.Index = Sheets.Count Then
            MsgBox "最終シートです。"
        Else
            Sheets(ActiveSheet.Index + 1).Activate
        End If
    End Sub
 ActiveSheet.Indexに加減算する数を変更すれば
 どこのシートにでもいけることになります。

 二つ以上移動する場合は、移動できるかどうかの判定部分は
 変更が必要になってきますが。。。

 (HANA)


 マクロは慣れていないと思いますが、
 On Error Resume Next は
 単にエラーを「無視する」ということなので、常用しない方が今後のためです。
 内容が正しくなくとも、何の警告も出なくなります。

 On Error Goto xxx は使い方次第で、正しく使えば有用とは思いますが、
 今回のような内容でしたら、HANA さんが提示されたように条件判定をきちんとする
 よう心がけた方がよいと思います。
 (Mook)

 HANAさん、わざわざすみません。ありがとうございます。

 両方の構文ともうまくいきました。

 ちょっとわからないのですが宜しかったら教えてください。
 今、EXCEL画面の下のシート名一覧は
 シート名を変更して
 1番、2番、最終と3つのシートがあります
 コードの表示上では
  Micrososot excel obuject
 Sheet1 (1番)
 Sheet2 (2番)
 Sheet3 (最終)
  this workbook
 となっています。
 教えて頂いた構文

 >If ActiveSheet.Index = Sheets.Count Then
 を自分なりの言葉にしたいのですが
 シート名:最終にいる状態で
 ActiveSheet.Index ・・・今のシート番号(Sheet3)が
 Sheets.Count ・・シー総数(3)と同じなら という意味で 
 自分なりの覚え方にしたのですがそういうふうでいいでしょうか
 手操作でシートの順番を
 1番、最終、2番の順にしてもマクロはうまくいきます
 コードの表示上では
  Micrososot excel obuject
 Sheet1 (1番)
 Sheet2 (2番)
 Sheet3 (最終)
  this workbook
 のまま順番は入れ替わっていないのですが、シート名2番が最終(最右)
 にある状態でもうまくいくのはなぜでしょうか
 うまくいっているのに変な質問なのですが
 自分なりの言葉で納得しよううとすると
 >If ActiveSheet.Index = Sheets.Count Thenはどういう説明になるの
 でしょうか。
 ようするに ActiveSheet.Indexはどういう意味か ということかも
 しれませんが。よろしくお願いします。 

 Mookさん。おしゃる通りだと思いました。
 そこで、ここでしっかり納得したいと思い質問をさせて頂きました。
 質問を長々かいてしまってわかりにくいかもしれませんが

 HANAさんの
 >VBAはシートをインデックス番号で表すことが出来ます。
 >「前から数えて ○番目のシート」
 >と言った感じです。

 >現在のシートが何番目のシートなのか
 >全部でシートが何枚有るのか
 >それぞれ調べて、比較をすることでも
 >メッセージボックスを表示させる事が出来ると思います。
 この部分がピンとこないというか、わからないのが現状です。

 (初心者)


 非表示シートがあるということも考慮して・・・・。

 Sub test1()
    Dim sht As Object
    On Error Resume Next
    Set sht = ActiveSheet.Next
    Do Until sht Is Nothing
       Err.Clear
       sht.Select
       If Err.Number = 0 Then Exit Do
       Set sht = sht.Next
    Loop
    If sht Is Nothing Then MsgBox "最後のシートです"
    On Error GoTo 0
 End Sub
 Sub test2()
    Dim sht As Object
    Set sht = ActiveSheet.Next
    Do Until sht Is Nothing
       If sht.Visible = xlSheetVisible Then
          sht.Select
          Exit Do
       End If
       Set sht = sht.Next
    Loop
    If sht Is Nothing Then MsgBox "最後のシートです"
 End Sub

 test1は、On Error 〜を使った仕様。
 test2は、使わない仕様です。

 私は、この事象でエラートラップを利用した方法が特別問題があるとは
 思いません。もちろん、On Errorを使わない方法に問題もありません。
 この辺りは、どちらでもコードがわかりやすくなっていればよいと思っています。

 一般論として、On Error ステートメントに関して・・・。

 私がVBAでの仕事で On Error 〜 を使っていないブックなど
 きちんと確認はしていませんが、たぶん一つもない はずです。
 そのくらい使用頻度の高いステートメントです。

 ファイルI/Oに関するコードでは、間違いなく使いますしね!!
 よって、常用しないというより、正しい使い方を学ぶ ことをお勧めします。

 Mookさんの投稿にある

 >単にエラーを「無視する」ということなので

 これに関しては、同感です!!

 ichinose


 シートインデックスは
 >>「前から数えて ○番目のシート」
 を示します。

 >コードの表示上では
 VBEのオブジェクトウィンドウ(左上の窓)に表示されている順番の事ですよね?
 手作業でシートの順番を入れ替えても、並びは変わりませんね。

 これは、(シート名)の前にある Sheet○ の名前でソートされて表示されています。

 ですから、VBEの方を見るのではなく【エクセルのシートタブの並び】を見て下さい。
 アクティブシートは、シートタブを数えた時、左から何番目にあるか。 = ActiveSheet.Index

 と整理すると、納得が行きますか?

  Micrososot excel obuject
 Sheet1 (1番) ←この間の並びで「何番目にあるか」
 Sheet2 (2番) ←が分かるコードでは
 Sheet3 (最終) ←【ありません】。
  this workbook

 エクセルの方の
 |1番/2番/最終/
   ↑    ↑    ↑
 この並びで「何番目にあるか」です。

 なので、シートを入れ替えた時も・・・・
 |1番/最終/2番/
   ↑    ↑    ↑
 「最終」シートは 2番目にあって(ActiveSheet.Index)
  シートは全部で 3番目まであるので(Sheets.Count)
  一つ後ろのシートが選択できます。

 「2番」シートは 3番目にあって(ActiveSheet.Index)
  シートは全部で 3番目まであるので(Sheets.Count)
  一つ後ろのシートは選択できません。

 (HANA)


 HANAさん。たびたびすみません。ありがとうございます。 
 >エクセルの方の
 >1番     /2番  /最終/
 > ↑        ↑       ↑
   (1番目)(2番目)(3番目)
 >この並びで「何番目にあるか」です。

 この説明よくわかりました。
 構文(マクロ)を起動する際、今のシートが左から数えて
 何番目にいるのかをActiveSheet.Indexっていうんですね。
 今のシート名「最終」にいる場合ActiveSheet.Index=3
 その番号とSheets.Count=シート総数(3)を確認して今のシートが
 最右のシートだと 判断するということですね。
 よくわかりました。
 具体的な説明ありがとうございました。

 ichinoseさん。
 構文2つもご提示ありがとうございました。
 非表示のシートを作っておいてtest1、test2両方ともに
 表示しているシートの最右のシートでMsgBox "最後のシートです"
 が表示しました。
 構文の中身はチョットチンプンカンプン(表現が古いかもしれませんが)
 ですが、出来る範囲で確認してみようと思います。 
 いずれにせよ、・・・を考慮して・・・というところが今後どのような 
 仕様にするのかという場面で必要になってくるんだなあということが 
 すこしわかったような気がします。 
 ありがとうございました。(初心者)


 解決後ですが、On Error ステートメントについてもう一つ・・・・。

 >同じ構文のなかにエラー処理を記述しなくてはいけない
 同じ構文------>同じプロシジャーだと思いますが、
 私もそのとおりだと思いますし、今までもそのようにしていました、が・・・。

 例として、割り算の計算で0で割る場合を取り上げます。
 新規ブックの標準モジュールに

 Sub 割り算()
    On Error GoTo 割り算err
    Dim 割られる数 As Long
    Dim 割る数 As Long
    割られる数 = Application.InputBox("割られる数を入力してください", Type:=2)
    If TypeName(割られる数) <> "Boolean" Then
       割る数 = Application.InputBox("割る数を入力してください", Type:=2)
       If TypeName(割る数) <> "Boolean" Then
          MsgBox 割られる数 & "÷" & 割る数 & "  =  " & (割られる数 / 割る数)
       End If
    End If
    On Error GoTo 0
    Exit Sub
 割り算err:
    MsgBox Err.Description
 End Sub

 上記の割り算の実行で、割られる数として 1 割る数として、0を入力すると

 仕様どおり 「0 で除算しました。」というメッセージが表示されます。

 これを以下のようにプロシジャーを分割し、

 Sub 割り算2()
    On Error GoTo 割り算2err
    Dim 割られる数 As Long
    Dim 割る数 As Long
    割られる数 = Application.InputBox("割られる数を入力してください", Type:=2)
    If TypeName(割られる数) <> "Boolean" Then
       割る数 = Application.InputBox("割る数を入力してください", Type:=2)
       If TypeName(割る数) <> "Boolean" Then
          Call 割り算計算(割られる数, 割る数)
       End If
    End If
    On Error GoTo 0
    Exit Sub
 割り算2err:
    MsgBox Err.Description
 End Sub
 '==============================================================
 Sub 割り算計算(ByVal ln1 As Long, ByVal ln2 As Long)
    MsgBox ln1 & "÷" & ln2 & "  =  " & (ln1 / ln2)
 End Sub

 上記の割り算2を実行し、前回同様
 割られる数として 1 割る数として、0を入力しても
 「0 で除算しました。」というメッセージが表示されます。

 つまり、プロシジャー 割り算計算 内の
 
 MsgBox ln1 & "÷" & ln2 & "  =  " & (ln1 / ln2)

 の↑の箇所で発生したエラーが

 別プロシジャー割り算2の

  割り算2err:
    MsgBox Err.Description

 上記のエラー処理ステートメントで処理されてしまっています。
 私は、非常に不思議でした。

 もっとも呼び出すプロシジャーがオブジェクトモジュールの場合は、きちんと
 エラーになりましたが・・・。

 このことから、
 >同じ構文のなかにエラー処理を記述 
 しなくてもエラー処理が可能になってしまうことがある ということになります。
 On Error 〜 の使用方法としては、NGですが、

 この現象を知らないと思わぬ動作になってしまう場合もあるので 記述しておきます。

 ichinose

 ichinoseさん。さらなる記述ありがとうございます。
 まず、Sub 割り算 実行してみました。

 割られる数:100
 割る数:25
 とすると
100÷25=4

 割られる数:100
 割る数:0
 とすると
 0で除算しました

 割られる数:未入力
 OK
 型が一致しません

 割られる数:未入力
 キャンセル
 割る数:未入力
 キャンセル
 オーバーフローしました
 となりました。

 ichinoseさんが説明されたいことの以前の段階で疑問がうまれて
 しまいました。
 割られる数:100
 割る数:25
 とすると
100÷25=4

 以外のMSGBOXは記述されていないのに
 エラーの入力というか0で割ったり入力なしでOK
 した場合も対応のMSGBOXが表示するのは
 割り算2err:
    MsgBox Err.Description
 これが走ると上記のMSGBOXが表示すると考えてもいいでしょうか
 全文検索で見ても探せなかったのですがいかがでしょうか
 まず、ここで疑問がうまれましたので教えてください。
 (初心者)


 挙動を確かめることも大切ですが、エラーの発生したときに処理内容を理解する方
 がよいと思います。

 VBA(VBSも)ではエラーが発生すると処理を中断しますが、これはエラーが発生したときの
 デフォルトの挙動で
 On Error Goto 0
 を設定したのと同じ動作です。

 自身でエラー処理をしたい場合は、処理先のルーチンを指定しますし、
 On Error Resume Next
 でエラーを無視して、次の処理を進めます。

 いずれの場合もエラーが発生した場合は、Err というオブジェクトに、エラーコードや
 エラーの説明が記録されます。
http://excelvba.pc-users.net/fol6/6_8.html
http://www.asahi-net.or.jp/~ef2o-inue/vba_k/sub04_140_02.html
 のあたりを参照されると、詳しいことがわかるかと思います。

 #なんでこういうところにMicrosoftのページが上がってこないんだろう。
 #と思ったら、下の方にあったけど
http://msdn.microsoft.com/ja-jp/library/cc344117.aspx
 #じゃぁなぁ・・・。
 (Mook)

 Mookさん、ありがとうございます。
 http://excelvba.pc-users.net/fol6/6_8.html こちらの掲載の
 マクロの出力(MSGBOX)がわかりました。
 こういうもの(オブジェクト)が用意されていることがわかりました。
 これでichinoseご提示のマクロの違いの意味にかかれます。
 ありがとうございました(初心者)

 ichinoseさん。ご報告です。Sub 割り算() Sub 割り算2()
 2つのタイプ 実行し確認しました。
 同じようにできました。

 Sub 割り算() では計算もエラー処理も1つのプロシージャのなかで
 やっていて、Sub 割り算2では入力の処理のみ実施し、実際の計算は 
 他のプロシージャにわたしていることがわかりました。
 ありがとうございました。
 On Error GoTo 0の意味がよくわらなっかたので調べました。
 エラーの判定を標準処理にする場合はOn Error GoTo 0 と記述
 とありましたのでそのまま納得しました。
 ありがとうございました。(初心者)


コメント返信:

[ 一覧(最新更新順) ]


YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki. Modified by kazu.