• ベストアンサー

ExcelVBAの知恵をお貸しください。

一つのシートで、複数のセル範囲を選択している場合に、セル範囲を選択しているのか?列、行を選択しているのかを判別する方法として次のようなのを考えました。 それとなく動いているのですが、なんとなくスマートでなく、場当たり的な感じがしますが、どのようにすればいいのか判りません!! どなたか、アドバイス頂けないでしょうか?宜しくお願いいたします。 Sub test()  Dim myRang As Range  Dim myArry As Variant  For Each myRang In Selection.Areas myArry = Split(Replace(myRang.Address, ":", ""), "$") If UBound(myArry) <> 2 Then   MsgBox "セル範囲を選択しています。" & myRang.Address Else If IsNumeric(myArry(1)) Then MsgBox "行を選択しています。" & myRang.Address Else MsgBox "列を選択しています。" & myRang.Address End If End If  Next End Sub

質問者が選んだベストアンサー

  • ベストアンサー
  • Wendy02
  • ベストアンサー率57% (3570/6232)
回答No.1

こんばんは。 >なんとなくスマートでなく、場当たり的な感じがしますが、どのようにすればいいのか判りません!! Split(Replace(myRang.Address, ":", ""), "$") ここまでのレベルまで使ってしまって、なんとなくすっきりこない、その気持ちは分かるけれども、それを、自分の外に求めないほうがよいと思いますね。1年前の自分と比較して進歩しているなら、それで良いと思います。 年数やコードの数を重ねれば、それなりに、満足いくような格好にはなるけれども、「エラーなく、動きさえすれば良いのだ」と思って、先に進んでいくしかないと思います。ご質問のコードでも立派なものだと思います。ある別の掲示板の常連さんのコードを思い出しました。その方は、そういうスタイルの書き方で掲示板にいつも書いています。だから、キリがないです。 私だって、こんなことは自信があるわけではありません。 ただ、なるべく、エラー・フリー(エラーを出さない)を目指す、それだけだと思います。 Sub Test2()   Dim r As Range   Dim a As Range   Dim i As Long, j As Integer   Dim msg As String   If StrComp(TypeName(Selection), "Range", 1) <> 0 Then Exit Sub   Set r = Selection   For Each a In r.Areas     i = a.Rows.Count     j = a.Columns.Count     If a.Count = 1 Then       msg = "1つのセルを選択しています。"     ElseIf i > 1 And j > 1 Then       msg = "セル範囲を選択しています。"     ElseIf i > 1 Then       msg = "列を選択しています。"     ElseIf j > 1 Then       msg = "行を選択しています。"     End If     MsgBox msg & ": " & a.Address, 64   Next a   Set r = Nothing End Sub

その他の回答 (2)

  • cj_mover
  • ベストアンサー率76% (292/381)
回答No.3

こんにちは。"ある別の掲示板の常連"です。 遅すぎるレスですが、とりあえず、ご要望のものを...。 Sub Test_SS() Dim strM As String '' ...MsgBoxで表示する文字列 Dim strB As String '' ...一時的に格納する文字列(使いまわし) Dim strRngA() As String '' ...Addressを","区切りで(各Area毎に)文字列の配列に Dim strBA() As String '' ...各strRngAを"$"区切りで文字列の配列に(使いまわし) Dim i As Integer strB = ActiveWindow.RangeSelection.Address strRngA = Split(strB, ",")  For i = 0 To UBound(strRngA) strM = strM & CStr(i + 1) strB = strRngA(i) ' If strB = "$1:$65536" Then 'strM = strM & "_すべてのセル_" ' Else strBA = Split(strB, "$")   If UBound(strBA) And 4 Then strM = strM & "_セル範囲_"   ElseIf CBool(Val(strBA(1))) Then strM = strM & "_行範囲_"   ElseIf Not CBool(Val(strBA(2))) Then strM = strM & "_列範囲_"   Else strM = strM & "_単一セル_"   End If ' End If strM = strM & strB & vbLf ' & vbLf  Next i 'Erase strBA 'Erase strRngA strM = strM & "以上の 範囲 を選択中です。" 'strM = Replace$(strM, "$", "") 'strM = StrConv(strM, vbWide) MsgBox strM End Sub ''注:「無くても動く」部分をコメント('以下)にしておきます ''Excel2000/2002で動作確認済です Rangeオブジェクトやプロパティの参照・取得を減らして、 文字列変数でループ処理することでパフォーマンスを高める という狙い(?)ならば、"すっきり"したのではないでしょうか。 行数・字数を減らす意味なら、色々出来ると思いますが、 できるだけ「犠牲」にするもののないように書いてみました。 但し、このような目的の為だけに、 こうした記述を実践で使うかといえば、微妙です。 目的を実現する方法だけを問う質問だったなら、 Q&Aの回答として書くか、は、NOです。 (#1さん#2さんのような記述が一般的で妥当だと思います) 記述が長くなるということは、 「エラーの機会が増える」 「メンテナンスが複雑になる」 一般的でない書き方をするということは、 「他の人が管理・メンテナンスすることを難しくする」 といった「犠牲」を払うことになります。 どうしても必要な記述で、人に配布する場合には、 管理者向けの丁寧な説明文とセットで考える必要があるでしょう。 そこまでする必要があるのかないのか、実践での判断、 それ以前に、色々な方法がある中で、目的に照らして、 前提にした選択肢が十分で適当なものかどうか、 私はいつも考えさせられます。 昨年下半期の個人的な課題として掲げていたのが、 ・次の実践の機会に正しい選択ができるように幅を拡げる研究。 ・出来上がった自分のスタイルを、疑って、壊して、再構築。 本来は個人的に行う学習・探求なのですが、こうした事を 他者と共有できる場-"ある別の掲示板"のトピックス-で、 ご提示のコードに良く似た内容のものを書いたことがあります。 その時は、Range参照文字列そのものを編集・加工して 新たなRangeオブジェクトを合成する、という目的でしたので、 それなりに整合性はあったと思っているのですが、 説明不足や不備があって誤解を招いた面もあったようです。 こうした経緯がありましたので此処に出てくることにしました。 この場に書いて良いか迷う点もありました。 よかったら"ある別の掲示板"にも遊びに来ませんか? ご活躍を期待しております。頑張ってください。

  • onlyrom
  • ベストアンサー率59% (228/384)
回答No.2

オーソドックスなのをひとつ。。 '-------------------------------------------- Sub Test()  Dim myRang As Range  For Each myRang In Selection.Areas    If myRang.Columns.Count = Columns.Count Then      MsgBox "行選択: " & myRang.Address    ElseIf myRang.Rows.Count = Rows.Count Then      MsgBox "列選択: " & myRang.Address    Else      MsgBox "セル選択: " & myRang.Address    End If  Next End Sub '--------------------------------------------- 因みに質問者提示のコードでは、セルを【ひとつ選択】したとき正しいメッセージが出ないのでは?  

関連するQ&A

専門家に質問してみよう