[[20190822120508]] 『For〜NextでIf〜Then〜Elseのサンドイッチ』(りき) ページの最後に飛ぶ

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

 

『For〜NextでIf〜Then〜Elseのサンドイッチ』(りき)

現在、以下のように記述していますが、これをFor 〜 Nextでサンドイッチするやり方をご教授いただけないでしょうか。やってはみたのですがどうもうまくしません。
(31ヶ所(E8:AI8)のさらに35列記入しなくていけないので以下の記述の仕方では途方もない作業になるので)

If Range("E8").Value = "○" And Range("F8").Value = "●" Then

   Range("G80").Value = Range("G80") - 0.5

ElseIf Range("E8").Value = "○" And Range("F7").Value = "●" And Range("F8").Value = "" Then

       Range("G80").Value = Range("G80") - 0.5

ElseIf Range("E7").Value = "○" And Range("F8").Value = "●" And Range("E8").Value = "" Then

       Range("G80").Value = Range("G80") - 0.5

ElseIf Range("E7").Value = "○" And Range("F7").Value = "●" And Range("E8,F8").Value = "" Then

       Range("G80").Value = Range("G80") - 0.5

End If

< 使用 Excel:Excel2010、使用 OS:Windows7 >


 条件に合った場合の処理がすべて同じですが、間違いないですか?
 F列になったら G80 は どうなります?

 それと 
 Range("E8,F8").Value 
 では エラーになると思いますが。 

(渡辺ひかる) 2019/08/22(木) 12:24


 すみません

 Range("E8,F8").Value

 はエラーにはなりませんね

 Valueへの代入は E8、F8 になるようですが

 値の取得は

 Range("E8").Value

 と同じになるようです。

(渡辺ひかる) 2019/08/22(木) 12:47


 IF文を省略しましたけど
 こんな感じですかね

 Sub test()

    Dim i As Long

    For i = 1 To Range("AI1").Column - Range("E1").Column + 1
        With Range("D7")
            If .Offset(1, i).Value = "○" And .Offset(1, i + 1).Value = "●" Then
               Range("G80").Value = Range("G80") - 0.5
            End If
        End With
    Next

 End Sub

(渡辺ひかる) 2019/08/22(木) 13:21


ご提示のロジックは、E7:E8のいずれかが○であり、かつ、F7:F8のいずれかが●ならばG80セルを減算、ですね? 35列というのは、例えばG7:G8のいずれかがどうなっていれば減算になるのでしょう? ○なのか●なのか、それともそれ以外の新たな文字なのか。 ルールが判らないと、教えようがないです。

そして、○●と書いてますが、実際にそれは1文字なのでしょうか?

もうひとつ、E8 F8 の条件のときだけ、他のセルの空欄判定がありませんが、以下のパターンでも減算して良いのですか?(どういうパターンなら幾つ減算なのか、幾つか図解してもらうと判りやすいです)

	E	F
7	○	●
8	○	●
(???) 2019/08/22(木) 13:28

すみません、簡略化しぎて基本的なルールを書いていませんでした。
これは、勤務表でE7が予定でE8が実績です。なので基本的には予定通り勤務するので8行は空白。勤務変更になってもE7は空白にせずそのまま。各勤務記号の種類によって勤務時間が表示されるプログラムは完成しました。(都合上E7orE8の勤務時間はG80に入る以下H80,I80 ...)ですが、特例として○●の勤務となる場合に限り、G80に入る数値から-0.5を引くプログラムにしたいのです。(ボタン配置)

以下の例だと実績に記号が入っているため、予定よりも実績の方が優先される。

     1日  2日  3日 ... 31日
      E  F   G     AI
予定 7  − 休
実績 8 ○ ●

勤務時間         9 ...

という事なので-0.5の条件は以下の4パターンが考えられる。
それ以外はとくに変化なしのVBAにしたい。

  E F
7 − 休
8 ○ ●   1日目、2日目ともに勤務変更になった。

  E F
7 − ●
8 ○     1日目、勤務変更。2日目、勤務予定通り。

  E F
7 ○ 休
8   ●   1日目、勤務予定通り。2日目、勤務変更になった。

  E F
7 ○ ●
8       1日目、2日目ともに勤務予定通り。

です。よろしくお願い致します。
(りき) 2019/08/22(木) 14:44


1列が1日であり、G列は3日目でしょうか? それとも、E列F列共に1日目の情報であり、2日目の情報はG7:H8?

追加説明だと、E列が1日目でF列が2日目に見えます。 そうだとすると、G列が3日目であり、E7:F8の判定の次はF7:G8になりますが、●と〇の関係が逆になりませんか? それとも〇も●も実は文字列に意味が無く、「−」「休」と空白に意味があり、その他なんでもOKだったりしますか?
(???) 2019/08/22(木) 15:02


>1列が1日であり、G列は3日目でしょうか?

はい、そうです。行ごとに日付は移動するのでEは1日目、Fは2日目、G列は3日目です。

>E7:F8の判定の次はF7:G8になりますが、●と〇の関係が逆になりませんか? それとも〇も●も実は文字列に意味が無く、「−」「休」と空白に意味があり、その他なんでもOKだったりしますか?

「○」も「●」も文字列に意味があり、「−」「休」と空白には意味がありません。
あくまで、【○●が連続で続く勤務の時に-0.5をしたい】という事なのです。

自分の説明で伝わりますでしょうか?
それともdropbox等でサンプルファイルのURLを上げた方がよろしいでしょうか?
(りき) 2019/08/22(木) 15:36


E7よりE8が優先。なのでこの場合は、1日目(−)2日目(●)になる。
よって、-0.5はなし。

  E  F
7 ○ ●
8 −  
(りき) 2019/08/22(木) 15:56

私もですが、外部ストレージは、万が一にもウィルス検出しないよう、見てくれない人が多いです。

なるほど、1日は1列で、3日目以降は別な文字列で判定する訳ではない、と判りました。 そうであれば、E7:E8のいずれかが〇で、次の列はいずれかが●、という判定でも構わないかと思うのですが、いかがでしょう? 4セルを4種類判定する必要が無くなって、2種類の判定で済むようになります。

 Sub test()
    Dim i As Long

    For i = 5 To 34
        If 0 < InStr(Cells(7, i) & Cells(8, i), "○") And 0 < InStr(Cells(7, i + 1) & Cells(8, i + 1), "●") Then
            Cells(80, i + 2).Value = Cells(80, i + 2).Value - 0.5
        End If
    Next i
 End Sub
(???) 2019/08/22(木) 16:01

あと気になったのが、G80セルを直接減算すると、マクロを動かす度に数値が減っていってしまうので、G81とか別のセルに-0.5を代入するだけにして、G80とG81の和を計算するようにしてはいかがでしょうか。
(マクロ使わず、全部数式でもできそう)
(???) 2019/08/22(木) 16:09

数式例なぞ。G81セルとか、元とは違う行に以下の数式を貼り、日数分ドラッグコピーしてみてください。
 =IF(AND(0<COUNTIF(E$7:E$8,"○"),0<COUNTIF(F$7:F$8,"●")),-0.5,"")
(???) 2019/08/22(木) 16:18

>私もですが、外部ストレージは、万が一にもウィルス検出しないよう、見てくれない人が多いです。

マクロが付いているのでウイルスは怖いですね。失礼しました。

>E7:E8のいずれかが〇で、次の列はいずれかが●、という判定でも構わないかと...

それだと

  E F
7 ○ ●
8 − ○

1日目(−)2日目(○)も○●の判定になってしまいますのではやり4パターンなのかなと思っています。

>G80セルを直接減算すると、マクロを動かす度に数値が減っていってしまうので、G81とか別のセルに-0.5を代入するだけにして、G80とG81の和を計算するようにしてはいかがでしょうか。

オリジナルデータがあり、そこに勤務マークを入力し出力するのではやり、今のボタン形式がベストなのです。
(りき) 2019/08/22(木) 16:26


追加条件が駄目でしたね。 これだとマクロも数式も、追加条件時でも減算してしまいますね。 もう一工夫必要か…。
  E  F
7 ○ ●
8 −  

○●が本当に1文字であれば、7行目8行目を文字列結合して、末尾1文字だけ取り出せばいけそう。 それとも、E列は入力のある後のセルを使うけど、F列はどちらでも良い、とかありますか?(考慮するのは4パターンだけじゃなかった事になります)
(???) 2019/08/22(木) 16:29


現在は、こんなかんじで動いています(実際は31日分)。
3日分まで記述しました。

'1列目
If Range("E8").Value = "○" And Range("F8").Value = "●" Then

   Range("G80").Value = Range("G80") - 0.5

ElseIf Range("E8").Value = "○" And Range("F7").Value = "●" And Range("F8").Value = "" Then

       Range("G80").Value = Range("G80") - 0.5

ElseIf Range("E7").Value = "○" And Range("F8").Value = "●" And Range("E8").Value = "" Then

       Range("G80").Value = Range("G80") - 0.5

ElseIf Range("E7").Value = "○" And Range("F7").Value = "●" And Range("E8,F8").Value = "" Then

       Range("G80").Value = Range("G80") - 0.5

End If

'2列目
If Range("F8").Value = "○" And Range("G8").Value = "●" Then

   Range("H80").Value = Range("H80") - 0.5

ElseIf Range("F8").Value = "○" And Range("G7").Value = "●" And Range("G8").Value = "" Then

       Range("H80").Value = Range("H80") - 0.5

ElseIf Range("F7").Value = "○" And Range("G8").Value = "●" And Range("F8").Value = "" Then

       Range("H80").Value = Range("H80") - 0.5

ElseIf Range("F7").Value = "○" And Range("G7").Value = "●" And Range("F8,G8").Value = "" Then

       Range("H80").Value = Range("H80") - 0.5

End If

'3列目
If Range("G8").Value = "○" And Range("H8").Value = "●" Then

   Range("I80").Value = Range("I80") - 0.5

ElseIf Range("G8").Value = "○" And Range("H7").Value = "●" And Range("H8").Value = "" Then

       Range("I80").Value = Range("I80") - 0.5

ElseIf Range("G7").Value = "○" And Range("H8").Value = "●" And Range("G8").Value = "" Then

       Range("I80").Value = Range("I80") - 0.5

ElseIf Range("G7").Value = "○" And Range("H7").Value = "●" And Range("G8,H8").Value = "" Then

       Range("I80").Value = Range("I80") - 0.5

End If
(りき) 2019/08/22(木) 16:33


つねに8行が優先。8行に入力があれば7行は無視される。
質問に対する答えになっているでしょうか?

  E F
7 ○ ●
8 − 

(りき) 2019/08/22(木) 16:38


 > つねに8行が優先。8行に入力があれば7行は無視される。 
本当にそうですか? 既存のコードだと、以下の場合でも減算しませんか?
  E  F
 7 ○ ● 
 8   休
(???) 2019/08/22(木) 16:59

すみません。

  E F

 7 ○ ● 
 8   休

これだと減算されてしまいました。
(りき) 2019/08/22(木) 17:01


こうなってしまう理由は、渡辺ひかるさんが書いてくれたように、Range("E8,F8").Value という書き方はF8は無視されるからです。 F8は何が入っていても構わない、という事になっているのです。 元のコードは潜在バグがあったということ。

普通に考えると、実績が休みだったのなら減算する必要はないですね? E7とE8両方に入力がある場合はE8で判定するのであれば、以下ですかね。

 Sub test()
    Dim i As Long

    For i = 5 To 34
        If Right(Cells(7, i) & Cells(8, i), 1) = "○" And Right(Cells(7, i + 1) & Cells(8, i + 1), 1) = "●" Then
            Cells(80, i + 2).Value = Cells(80, i + 2).Value - 0.5
        End If
    Next i
 End Sub

おまけで、数式も。

 =IF(AND(RIGHT(E$7&E$8,1)="○",RIGHT(F$7&F$8,1)="●"),-0.5,"")
(???) 2019/08/22(木) 17:11

>○●が本当に1文字であれば、7行目8行目を文字列結合して、末尾1文字だけ取り出せば...

=IF(AND(RIGHT(E$7&E$8,1)="○" ... の発想は全くなかったです。
数式まで書いていただいて助かります。ありがとうございます。
すべて解決しました。感謝です。

(りき) 2019/08/23(金) 10:08


すみません、追加で質問です。

上記の

 Sub test()
    Dim i As Long

    For i = 5 To 34
        If Right(Cells(7, i) & Cells(8, i), 1) = "○" And Right(Cells(7, i + 1) & Cells(8, i + 1), 1) = "●" Then
            Cells(80, i + 2).Value = Cells(80, i + 2).Value - 0.5
        End If
    Next i
 End Sub

に列移動も加えたくて下記のように作成したのですけれどうまく作動しません。
どのように作成すればよろしいでしょうか?
ご教授よろしくお願い致します。

 Sub test()
 Dim i As Long
    Dim j As Long
        Dim k As Long

    For i = 5 To 34
    For j = 7 To 75 Step 2
    For k = 8 To 76 Step 2

        If Right(Cells(j, i) & Cells(k, i), 1) = "○" And Right(Cells(j, i + 1) & Cells(k, i + 1), 1) = "●" Then
            Cells(80, i + 2).Value = Cells(80, i + 2).Value - 0.5

        End If

            Next k
        Next j
    Next i

 End Sub

(りき) 2019/08/26(月) 13:22


なんで3重ループになっているんでしょう? 縦ループと横ループを掛ければ良いのだから、2重ループです。 3次元にしてどうする…。

ポイントは、7行目と8行目を j行、k行とするのではなく、j行、j+1行とすることです。 あと、段付けめちゃくちゃなので、そこは整えてください。 私が元コードを書いたというのに、改悪されるのは悲しすぎます。

 Sub test()
    Dim i As Long
    Dim j As Long

    For i = 5 To 34
        For j = 7 To 75 Step 2
            If Right(Cells(j, i) & Cells(j + 1, i), 1) = "○" And Right(Cells(j, i + 1) & Cells(j + 1, i + 1), 1) = "●" Then
                Cells(80, i + 2).Value = Cells(80, i + 2).Value - 0.5
            End If
        Next j
    Next i
 End Sub
(???) 2019/08/26(月) 14:31

>ポイントは、7行目と8行目を j行、k行とするのではなく、j行、j+1行とすることです。
ありがとうございます。Cells(80, i + 2)と同義ですね。

>段付けめちゃくちゃなので、そこは整えてください。 私が元コードを書いたというのに、 改悪されるのは悲しすぎます。
???さん、すみません。せっかくの正しいコードを申し訳ないです。

(りき) 2019/08/26(月) 14:51


もう一点ありました。
Cells(80, i + 2).Value = Cells(80, i + 2).Value - 0.5
の部分もスライドですので(80,83,86...182)下記のような作成したのですが、
【型が一致しません。】とエラーがですのですが、どこに問題があるのでしょうか?
よろしくお願い致します。

  Dim i As Long
  Dim j As Long
  Dim k As Long

    For i = 5 To 34
        For j = 7 To 75 Step 2
            For k = 80 To 182 Step 3
                If Right(Cells(j, i) & Cells(j + 1, i), 1) = "○" And Right(Cells(j, i + 1) & Cells(j + 1, i + 1), 1) = "●" Then
                    Cells(k, i + 2).Value = Cells(k, i + 2).Value - 0.5
                End If
             Next k
        Next j
    Next i
 End Sub

(りき) 2019/08/26(月) 14:55


ですから、kのループを入れると掛け算になって、縦*横*高さになって、3次元になってしまうから駄目ですって。

jのループが縦位置なのだから、これを元に代入先の縦位置を計算しましょう。
7 80
9 83
11 86
… …
71 176
73 179
75 182

こんな風に、シートにループ変数を書き出してみてください。 A列の値から計算して、B列を求める事ができれば、これが代入先の行として使えますよね?

 C1: =80+(A1-7)/2*3

こんな式になります。 ドラッグしてみて、B列と同じか確認してみてください。 この式を、私の書いたコードの、80 の代わりに使いましょう。
(???) 2019/08/26(月) 16:13


>ですから、kのループを入れると掛け算になって、縦*横*高さになって、3次元になってしま うから駄目ですって。
やっと理解できました。すみませんでした。

>jのループが縦位置なのだから、これを元に代入先の縦位置を計算しましょう。
7 80
9 83
11 86
… …
71 176
73 179
75 182

ここまでは理解できますが、それが【C1: =80+(A1-7)/2*3】なるのがいまいちわからなく
80 の代わりに代入ができないのですが、しばらく考えてから投稿いたします。
(りき) 2019/08/26(月) 17:19


ちなみに、検算に使用したA列は j の値な訳ですから、VBAの式にすると、A1 の部分が j って事です。
jが7だったとき出力先は80だった…、75のときは182になればOKですよね。

j は 2 ずつ増えて、出力先は 3 ずつ増える。 j/2*3、というのが肝です。
(???) 2019/08/26(月) 17:30


横からですが、
For j = 7 To 75 Step 2
ですから、チェックする行は
7,9,11,13...って【1】行飛ばしになってますけど、
>80,83,86...182
これだと、操作する列の方は【2】行飛ばしになりますけど、間違いないのですか?

間違いなければ それぞれ【n】回目を条件に足していったらどうでしょうか

  5 + (n回目 * 2) = 7,9,11,13
 77 + (n回目 * 3) = 80,83,86,89   

また、セル範囲の値を配列として取得してJoinでくっつけるという手も使えそうです。
(この辺は好みの問題だとおもいますが)

 Sub test2()
    Dim WF As Object: Set WF = WorksheetFunction
    Dim 列 As Long
    Dim 回目 As Long

    For 列 = 5 To 34
        For 回目 = 1 To 35

            With Cells(5 + 回目 * 2, 列)
                If Right(Join(WF.Transpose(.Resize(2)), ""), 1) = "○" And Right(Join(WF.Transpose(.Offset(, 1).Resize(2)), ""), 1) = "●" Then
                    Cells(77 + 回目 * 3, 列 + 2).Value = Cells(77 + 回目 * 3, 列 + 2).Value - 0.5
                End If
            End With

        Next 回目
    Next 列
 End Sub

(もこな2) 2019/08/26(月) 19:04


>jのループが縦位置なのだから、これを元に代入先の縦位置を計算しましょう。
7 80
9 83
11 86
… …
71 176
73 179
75 182

すみません、出力先は
7 80
7 83
7 86
… …
7 176
7 179
7 182
でした。

出力先は

  E F
7 ○ ●
8 − ○  に対して G80

    E  F
9  ○ ●
10 − ○  に対して G83

    E  F
11  ○ ●
12  − ○  に対して G86

○●等の記号入力ヶ所

   E  F  G  I  H  J  K ... AI
7
8
9

76

出力先(-0.5の計算を行うヶ所)

  E  F  G  I  H  J  K ... ... AJ
80
83
86

182

とこんな感じです。

(りき) 2019/08/27(火) 09:09


ちょっと混乱されているようなので、一度Excelを離れて、紙と鉛筆を用意して書いてみたらどうでしょう?
 ______________________________________________________________
                      ???さん               もこな2
  1回目のループ
  データ行                      7         5+(1*2)= 7
  出力行         80+( 7-7)/2*3=80        77+ (1*3) =80

  2回目のループ
  データ行                      9         5+(2*2)= 9
  出力行         80+( 9-7)/2*3=83        77+ (2*3) =83

  3回目のループ
  データ行                     11         5+(3*2)=11
  出力行         80+(11-7)/2*3=86        77+ (3*3) =86 

(もこな2) 2019/08/27(火) 12:58


理解できました。完全に解決です。

???さん、もこな2さん

ちゃんと作動しております。
長々とお付き合いいただき、ありがとうございます。
(りき) 2019/08/27(火) 14:16


コメント返信:

[ 一覧(最新更新順) ]


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