Excel VBA質問箱 IV

当質問箱は、有志のボランティア精神のおかげで成り立っています。
問題が解決したら、必ずお礼をしましょうね。
本サイトの基本方針をまとめました。こちら をご一読ください。

投稿種別の選択が必要です。ご注意ください。
迷惑投稿防止のため、URLの入力を制限しています。ご了承ください。


6852 / 13646 ツリー ←次へ | 前へ→

【42588】For〜Nextを使って ToShiYo 06/9/15(金) 20:02 質問[未読]
【42596】Re:For〜Nextを使って neptune 06/9/15(金) 22:10 発言[未読]
【42604】Re:For〜Nextを使って ToShiYo 06/9/16(土) 12:17 お礼[未読]
【42615】Re:For〜Nextを使って neptune 06/9/16(土) 15:37 回答[未読]
【42635】Re:For〜Nextを使って ToShiYo 06/9/17(日) 9:07 お礼[未読]
【42639】Re:For〜Nextを使って neptune 06/9/17(日) 10:30 回答[未読]
【42667】Re:For〜Nextを使って yata 06/9/18(月) 21:08 回答[未読]
【42757】Re:For〜Nextを使って ToShiYo 06/9/20(水) 19:34 お礼[未読]

【42588】For〜Nextを使って
質問  ToShiYo  - 06/9/15(金) 20:02 -

引用なし
パスワード
      A      B     C
1 基準      一般    会員
2 50000円以上   15%     30%
3 20000円以上   10%    20%
4 10000円以上     5%    10%

上記の表で、
一般は15%・・〜・・5%引き
会員は30%・・〜・・10%引き
をMsgBoxに表現したいのですが・・・
「一般」と「会員」の区別が下のコードで表現が出来ないのですが、
どの部分を訂正したらよいのでしょうか?
アドバイスお願いします。

Sub 割引率()
Dim a As String
For i = 2 To 3
  For n = 2 To 4 
   If Column > 2 Then
     a = Cells(1, 2).Value
    Else
     a = Cells(1, 3).Value  
   Cells(n, i).Select
     MsgBox a & "は" & Selection.Value * 100 & "%割引です"   
   End If     
  Next n
Next i
End Sub

^^^^^^^^^^^^^^^^^^
更に欲ばりですが、
最終的には
「一般」で「50000円以上」は15%引き
     「20000円以上」は10%引き
   :
   :
「会員」で「10000円以上」は10%引き 
まで仕上げたいのですが・・・
これはまた後日検討したいと思っています
^^^^^^^^^^^^^^^^^^^^^
 

【42596】Re:For〜Nextを使って
発言  neptune  - 06/9/15(金) 22:10 -

引用なし
パスワード
   希望するResとは違うと思います。

あなたが、頭の中で
>一般は15%・・〜・・5%引き
>会員は30%・・〜・・10%引き
を判断する時はどうやってしますか?

VBAはExcelでの決まった仕事を自動化する為のVBのサブセットですが、
ありがたいことに「あなたが、頭の中で判断する」代わりをやって
もらうプログラムを書くことができます。

それには、あなたの頭の中を整理しなければなりません。
整理した後、それをVBAで実現するだけです。頭の中は別に
Excelを意識する必要はないのです。後で考えれば良いのですから。
先ずは、自分で考える練習をしなければいけません。

仕様ではなくあなたが頭の中ではこういう手順で処理している事
を考えて書いてみて下さい。
このようなResではなくもっと良いアドバイスを受けられるでしょう。

【42604】Re:For〜Nextを使って
お礼  ToShiYo  - 06/9/16(土) 12:17 -

引用なし
パスワード
   ▼neptune さん:

アドバイスありがとうございます。
その通りですね。頭では理解が出来るのですが・・・
コード化することが出来ない状態です。
でも、貴殿のアドバイスに基づき、整理してやってみました。
曲がりなりにも、何とかできました。
ご意見をいただければ幸いです。
これからもよろしくお願いします。

Sub 割引率()
Dim a As String
Dim b As String
For i = 2 To 3
  For n = 2 To 4
   If i > 2 Then
      b = Cells(1, 3).Value
       Cells(n, i).Select
        p = Cells(n, i).Offset(, -2).Value
           MsgBox p & "円以上の場合" & Chr(10) & b & "は" & _
             Selection.Value * 100 & "%割引です"
   Else
      a = Cells(1, 2).Value
        Cells(n, i).Select
        o = Cells(n, i).Offset(, -1).Value
           MsgBox o & "円以上の場合" & Chr(10) & a & "は" & _
             Selection.Value * 100 & "%割引です"
   End If
  Next n
Next i
End Sub

【42615】Re:For〜Nextを使って
回答  neptune  - 06/9/16(土) 15:37 -

引用なし
パスワード
   いきなりですが、ツール→オプションで「変数の宣言を強制する」をON
にすることを強くお勧めします。

なので、デバッグするのが面倒でソースはチラッとしか見てません。
チラッと見てわけがわからんかったので、作成しました。
なお、終わってみてみたらFunction Gakuでの判断が希望のものと
違うようなので、跡で適当に変更してください。
・最低必要限しか書いてません。(実用は問題あり)
・判り易いように特別な手法は使わず、力技で検索してます。

目的
基準額、会員か否かを判断して、割引率を取得する

目で表を見たときどういう風に頭で処理しているか (Excelは関係ない)
を整理する
1.検索する額と、会員か否かの情報を取得する
2.検索する額を元に基準額を探す
3.該当する基準額の行で、一般、会員を探し、割引率を取得する
4.割引率を返す
ここまでが頭の中で行う作業

ToShiYoさんのコードを見ていると↑が全く整理されていないように見える
弊害:いきなりコード化すると頭がこんがらかって間違いやすい。
   半年後の自分は他人と同じです。たぶんこのソースでは全く
   わけがわからないでしょう。(メンテナンス出来ない。)

又、最低限必要なコメントは付けましょう。
訳がわからん。解読が面倒です。

ここでExcelで考えてみる
最初にUPしていた表を使って作成してます。

GetWaribikiがメインプログラムです。

Sub GetWaribiki()
Dim kingaku As Long   '検索する額
Dim Kijyun As Long   '基準金額
Dim blnkaiin As Boolean  'TRUE:会員、FALSE:一般
Dim lRow As Long    '行番号
Dim Waribiki As Single '割引率
Dim sBuf As String

'  1 、検索する額と、会員か否かの情報を取得する
  kingaku = CLng(InputBox("検索する額を入力して下さい。", "Test"))
  blnkaiin = CBool(InputBox("会員ですか?" & vbCrLf & "会員の場合1" & vbCrLf _
            & "一般の場合0" & vbCrLf & "を入力して下さい。", "Test"))
  '2.検索する額を元に基準額を探す
  kingaku = Gaku(kingaku)
  '3.該当する基準額の行で、一般、会員を探し、割引率を取得する
'  3-1会員か、一般化を文字列化
  If blnkaiin = True Then
    sBuf = "会員"
  Else
    sBuf = "会員"
  End If
  '3-2 該当する基準額の行で、一般、会員を探し、割引率を取得する
  Waribiki = SearchKingaku(Worksheets("Sheet1"), kingaku, blnkaiin)
  MsgBox kingaku & "の割引率は" & vbCrLf & sBuf & "割引で" & vbCrLf & _
      Waribiki * 100 & "%" & vbCrLf & " です。"

End Sub

Private Function Gaku(pKingaku As Long) As Long
'2.検索する額を元に基準額を探す
  Select Case pKingaku
    Case Is < 10000
      Gaku = 10000
    Case Is < 20000
      Gaku = 20000
    Case Is < 50000
      Gaku = 50000
  End Select
End Function

Private Function SearchKingaku(pSheet As Worksheet, pKingaku As Long, pKaiin As Boolean) As Single
'3.該当する基準額の行で、一般、会員を探し、割引率を取得する
'////////////////////////////////////////////////////////
'引数
'pSheet :シートオブジェクト
'pKingaku  :検索する金額
'pKaiin   :TRUE:会員、FALSE:一般
'/////////////////////////////////////////////////////////

Const cSeachRow As Long = 1 '1列目(A列)を探す
Dim lColumuOffset As Long     '検索する行
Dim sTarget As String
Dim I As Long, IMax As Long
Dim lRet As Single      '戻り値

  lRet = 0
  
  If pKaiin = True Then
    lColumuOffset = 3   '会員
  Else
    lColumuOffset = 2   '一般
  End If
'  該当する基準額の行を検索する
  With pSheet
  IMax = pSheet.Cells(pSheet.Cells.Rows.Count, 1).End(xlUp).Row
  sTarget = CStr(pKingaku) & "円以上"
    For I = 2 To IMax
      If .Cells(I, cSeachRow).Value = sTarget Then  '行が見つかった
        '割引率を返す
        lRet = .Cells(I, lColumuOffset).Value
        Debug.Print .Cells(I, lColumuOffset).Value
        Exit For
      End If
    Next I
  End With
  
  SearchKingaku = lRet
End Function

※質問は受け付けますが、改造はお断りします。

【42635】Re:For〜Nextを使って
お礼  ToShiYo  - 06/9/17(日) 9:07 -

引用なし
パスワード
   ▼neptune さん:

大変ありがとうございました。「変数の宣言を強制する」をONにします。
また親切な解説までつけていただき感謝しています。
これから更に勉強していきます。

質問の仕方が悪くって反省しています。
実はFor〜NextのNestについてのレベルの質問をしたつもりでした。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
http://www.vbalab.net/vbaqa/c-board.cgi?cmd=one;no=42601;id=excel
の回答に今気がついたのですが、このような内容の質問をしたつもりでした。
質問の仕方が
上手く表現できずに、失礼しご迷惑をおかけしました。

neptuneさんの回答を真似てInputboxを使い再度コード化しました。
一般を2、会員を3 や 50000円以上2、20000円以上3、10000円以上4など
セルの位置を数字で置き換えている点をもう少し分かりやすくする必要が
あるかと思いますが、以下のようなコードで作成しました。

Sub 割引率2()
Dim a As String
For I = 2 To 3
  For n = 2 To 4
    I = InputBox("一般は2を" & Chr(10) & _
           "会員は3を入力してください")
    n = InputBox("50000円以上は2" & Chr(10) & _
           "20000円以上は3" & Chr(10) & _
           "10000円以上は4を入力してください")
     If Selection.Column = 2 Then
     a = Cells(1, 2).Value
    Else
     a = Cells(1, 3).Value
    End If
     MsgBox a & "は" & Selection.Value * 100 & "%割引です"
  Next n
Next I
End Sub

せっかく頂戴しましたコードですが入力した結果が0%になってしまいます。
修正がいただけるようであれば幸いです。
よろしくお願いします。失礼しました。

【42639】Re:For〜Nextを使って
回答  neptune  - 06/9/17(日) 10:30 -

引用なし
パスワード
   ▼ToShiYo さん:
こんにちは

何故か、Good Timingで書き込み見てしまいます。

>実はFor〜NextのNestについてのレベルの質問をしたつもりでした。
>~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>http://www.vbalab.net/vbaqa/c-board.cgi?cmd=one;no=42601;id=excel
>の回答に今気がついたのですが、このような内容の質問をしたつもりでした。
とは思っていました。^ ^;
ですが、対症療法は簡単(極端な話、代わりに書いてあげればいいだけ。
丸投げには私はResをつけません。)ですが、自分である程度のコードを
書くスキルがある為、原因は頭が整理出来てないと思いました。
それで私の初回のResになったわけです。

ネストの話ですが、一般的な話になりますが、ネストが深くなればなるほど
・・・(良くない表現)なコードと言われているようです。
どこで読んだか忘れましたが、7ネストを超えればハッキリ駄目といわれても
仕方がないそうな?
勿論必要な場合は必要ですが、深まるに従って、私は頭の中がこんがらかります。

私のソースを見ればわかると思いますが、今回は必要ありません。

Sub 割引率2()
についてですが、とりあえず、「変数の宣言を強制する」がONなら
新規にモジュールを作成すればモジュールの最上部に「Option Explicit」
が宣言されます。この状態ではコンパイルは出来ません。

ソースそのものについては、まだネストの練習プログラムだから・・・
なんともいえません。ただ好みでいえばSelectionは使用しない方が
今後の身の為です。


>せっかく頂戴しましたコードですが入力した結果が0%になってしまいます。
>修正がいただけるようであれば幸いです。
大変失礼しました。手抜き検証でしたので、
ロジック抜けや間違いがあったようです。

////////////Sub GetWaribiki() の以下を差し替えてください。
///////////これは記述ミスの修正
'  3-1会員か、一般化を文字列化
  If blnkaiin = True Then
    sBuf = "会員"
  Else
    sBuf = "一般"
  End If
  '3-2 該当する基準額の行で、一般、会員を探し、割引率を取得する
  Waribiki = SearchKingaku(Worksheets("Sheet1"), kingaku, blnkaiin)
  MsgBox kingaku & "円以上の割引率は" & vbCrLf & sBuf & "割引で" & vbCrLf & _
      Waribiki * 100 & "%" & vbCrLf & " です。"


/////////Function Gaku を以下に差し替えてください。
/////////これはロジックミスの修正
Private Function Gaku(pKingaku As Long) As Long
'2.検索する額を元に基準額を探す
  Select Case pKingaku
    Case Is >= 50000
      Gaku = 50000
    Case Is >= 20000
      Gaku = 20000
    Case Is >= 10000
      Gaku = 10000
    Case Else
      Gaku = pKingaku
  End Select
End Function

上記の差し替えで全ての金額、例えば15000とか、42000とかに対応しました。
間違えておいていうのもなんですが、機能分割していれば修正も簡単でしょ?
ネストの中に入っていればややこしいですよ。

【42667】Re:For〜Nextを使って
回答  yata  - 06/9/18(月) 21:08 -

引用なし
パスワード
   ▼ToShiYo さん:

>実はFor〜NextのNestについてのレベルの質問をしたつもりでした。
>~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>http://www.vbalab.net/vbaqa/c-board.cgi?cmd=one;no=42601;id=excel
>の回答に今気がついたのですが、このような内容の質問をしたつもりでした。
以下のようなコードで作成しました。
>
>Sub 割引率2()
>Dim a As String
>For I = 2 To 3
>  For n = 2 To 4
>    I = InputBox("一般は2を" & Chr(10) & _
>           "会員は3を入力してください")
>    n = InputBox("50000円以上は2" & Chr(10) & _
>           "20000円以上は3" & Chr(10) & _
>           "10000円以上は4を入力してください")
>     If Selection.Column = 2 Then
>     a = Cells(1, 2).Value
>    Else
>     a = Cells(1, 3).Value
>    End If
>     MsgBox a & "は" & Selection.Value * 100 & "%割引です"
>  Next n
>Next I
>End Sub
>
>せっかく頂戴しましたコードですが入力した結果が0%になってしまいます。
>修正がいただけるようであれば幸いです。
0%になるのは何処も選択されていないからです。
あなたの一番最初のコードでは Cells(n,i).Select でセルを選択していましたが、
このコードではいきなり
    If Selection.Column=2 Then
としています。
それから、For〜Nextの質問とは外れますが、InputBoxの値を変数に使用するのなら、ループする必要が無いのでは?
またInputBoxの戻り値が数値でなかったら Cells(n,i)とするとエラーになります。
入力値にほかの数字が入った時のエラー対策も必要かもしれません。

Sub 割引率2()
Dim a As String
入力1:
i = Val(InputBox("一般は2を" & Chr(10) & _
           "会員は3を入力してください"))
If i <> False Then
  If i = 2 Or i = 3 Then

入力2:
    n = Val(InputBox("50000円以上は2" & Chr(10) & _
           "20000円以上は3" & Chr(10) & _
           "10000円以上は4を入力してください"))
    If n <> False Then
      If n > 1 And n <= 4 Then
        MsgBox Cells(1, i) & "は" & Cells(n, i) * 100 & "%割引です"
      Else: GoTo 入力2
      End If
    End If
  Else: GoTo 入力1
  End If
End If
End Sub
InputBoxの引数のTypeが指定してないのでVal関数で数値にしてセルの列番号と行番号に使います。
条件分岐が多くなりましたが、ほかの数字が入った時は再入力させます。

【42757】Re:For〜Nextを使って
お礼  ToShiYo  - 06/9/20(水) 19:34 -

引用なし
パスワード
   ▼yata さん:

ありがとうございました。
非常に参考になりました。
これからもよろしくご指導ください。

6852 / 13646 ツリー ←次へ | 前へ→
ページ:  ┃  記事番号:
2610219
(SS)C-BOARD v3.8 is Free