質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

Q&A

解決済

2回答

284閲覧

実行ボタン押下(2連続)をすると、ユーザの入力したデータが20日分プラスされてしまう。

King_of_Flies

総合スコア382

VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

0グッド

0クリップ

投稿2017/09/26 05:35

VBAでツールを作成しました。
コメントを多く書いたので、動作の説明は省きます。

このツールにはユーザの入力する箇所が5か所あり、
B3セル = 作業着手実績 入力例: 2017/09/26
B4セル = 作業完了実績 入力例:2017/09/26

B6~B300 = 作業着手予定日 入力例:16/09/26(火)
C6~C300 = 作業完了予定日 入力例:16/09/26(火)
D6~D300 = 作業進捗    入力例:100

というような物になっているのですが、
実行ボタンを押下(一回目)は期待する通りの動作をしてくれのですが、
結果が出た状態で再度実行ボタンを押下すると、
B6~B300,C6~C300の入力した日付が、20日づつ足される現象が起きています。

おそらく、FormatEditorの中で記載している年度合わせに使用した”20” + bar のところが影響しているのだと思いますが、
解決方法を教えて下さい。

あと、コーディングのアドバイスもよろしく承ります。

以下、VBAコード

VBA

1Const C_START_FIRST As String = "先行着手" 2Const C_START As String = "着手" 3Const C_START_LATE As String = "遅れ(着手)" 4Const C_START_LATED As String = "遅れ(未着手)" 5Const C_START_EMP As String = "" 6 7Const C_END_FIRST As String = "先行完了" 8Const C_END As String = "完了" 9Const C_END_LATE As String = "遅れ(着手)" 10Const C_END_LATED As String = "遅れ(未着手)" 11Const C_END_EMP As String = "" 12 13 14 15'実行ボタン押下で実行。 16'ユーザがセルに入力したデータから、Eセル、Fセルにパラメータをセットする。 17Sub 実行() 18 '入力された日付を指定のフォーマットに変更する。 19 Call FormatEditor 20 'Eセル、Fセルに文字列をセットする。 21 Call CellSetter 22 'Eセル、Fセルの文字色を初期化する。 23 Call ColorReset 24 'Eセル、Fセルから遅れのパラメータを持つデータの文字を赤字に変換する。 25 Call ColorSetting 26 'A1セルをセレクト状態にする。 27 Range("A1").Select 28End Sub 29 30'リセットボタン押下で実行。 31'ユーザが入力したデータと、実行によって記述されたEセル、Fセルのデータを削除する。 32Sub リセット() 33 '作業着手実績、作業完了実績に入力された文字を削除する。 34 Call DeleteResultDate 35 '作業着手予定日、作業完了予定日に入力された文字を削除する。 36 Call DeletePlanDate 37 'Eセル、Fセルの文字色を初期化する。 38 Call ColorReset 39 'A1セルをセレクト状態にする。 40 Range("A1").Select 41End Sub 42 43'入力された作業着手予定日、作業完了予定日の"16/09/26(火)"形式の入力を"2016/09/26"形式に整える。 44Sub FormatEditor() 45 46 '作業着手予定日 47 For i = 6 To 300 48 If Len(Cells(i, 2).Value) > 0 Then 49 Cells(i, 2).NumberFormatLocal = "yyyy/m/d;@" 50 foo = InStr(Cells(i, 2).Value, "(") 51 If foo > 0 Then 52 bar = Left(Cells(i, 2).Value, foo - 1) 53 Else 54 bar = Cells(i, 2).Value 55 End If 56 Cells(i, 2).Value = CDate("20" + bar) 57 Else 58 '作業着手予定日が空ならFor文から抜ける。 59 Exit For 60 End If 61 Next i 62 63 '作業完了予定日 64 For i = 6 To 300 65 If Len(Cells(i, 3).Value) > 0 Then 66 Cells(i, 3).NumberFormatLocal = "yyyy/m/d;@" 67 foo = InStr(Cells(i, 3).Value, "(") 68 If foo > 0 Then 69 bar = Left(Cells(i, 3).Value, foo - 1) 70 Else 71 bar = Cells(i, 3).Value 72 End If 73 Cells(i, 3).Value = CDate("20" + bar) 74 Else 75 '作業着手予定日が空ならFor文から抜ける。 76 Exit For 77 End If 78 Next i 79 80End Sub 81 82Sub CellSetter() 83 For i = 6 To 300 84 '作業着手予定日が空ならFor文から抜ける 85 If Cells(i, 2).Value = "" Then 86 Exit For 87 End If 88 89 '作業着手予定日~ < 作業着手実績日 90 If Cells(i, 2).Value < Cells(3, 2).Value Then 91 If Cells(i, 4).Value = 0 Then 92 Cells(i, 5).Value = C_START_LATED 93 ElseIf Cells(i, 4).Value > 0 Then 94 Cells(i, 5).Value = C_START_LATE 95 End If 96 97 '作業着手予定日~ = 作業着手実績日 98 ElseIf Cells(i, 2).Value = Cells(3, 2).Value Then 99 If Cells(i, 4).Value = 0 Then 100 Cells(i, 5).Value = C_START_LATE 101 ElseIf Cells(i, 4).Value > 0 Then 102 Cells(i, 5).Value = C_START 103 End If 104 105 '作業着手予定日~ > 作業着手実績日 106 ElseIf Cells(i, 2).Value > Cells(3, 2).Value Then 107 If Cells(i, 4).Value = 0 Then 108 Cells(i, 5).Value = C_START_EMP 109 ElseIf Cells(i, 4).Value > 0 Then 110 Cells(i, 5).Value = C_START_FIRST 111 End If 112 End If 113 Next i 114 115 For i = 6 To 300 116 '作業完了予定日が空ならFor文から抜ける 117 If Cells(i, 3).Value = "" Then 118 Exit For 119 End If 120 121     '作業完了予定日 < 作業完了実績日 122 If Cells(i, 3).Value < Cells(3, 3).Value Then 123 If Cells(i, 4).Value = 100 Then 124 Cells(i, 6).Value = C_END_LATED 125 ElseIf Cells(i, 4).Value < 100 Then 126 Cells(i, 6).Value = C_END_LATE 127 End If 128 129 '作業完了予定日 = 作業完了実績日 130 ElseIf Cells(i, 3).Value = Cells(3, 3).Value Then 131      If Cells(i, 4).Value = 100 Then 132 Cells(i, 6).Value = C_END 133 ElseIf 100 <> Cells(i, 4).Value Then 134 Cells(i, 6).Value = C_END_LATE 135 End If 136 137 '作業完了予定日 > 作業完了実績日 138 ElseIf Cells(i, 3).Value > Cells(3, 3).Value Then 139 If Cells(i, 4).Value = 100 Then 140 Cells(i, 6).Value = C_END_FIRST 141 ElseIf 100 <> Cells(i, 4).Value Then 142 Cells(i, 6).Value = C_END_EMP 143 End If 144 End If 145 Next i 146 147End Sub 148 149 150 151'B3,C3セルを削除する。 152Sub DeleteResultDate() 153 Range("B3:C3").Select 154 Selection.ClearContents 155End Sub 156 157'B6~E6の下に記入されているデータをすべて削除する。 158Sub DeletePlanDate() 159 Range("B6:F6").Select 160 Range(Selection, Selection.End(xlDown)).Select 161 Selection.ClearContents 162End Sub 163 164'D6,E6のセルのカラーリング設定 165Sub ColorSetting() 166 For i = 6 To 300 167 If Cells(i, 5).Value = C_START_LATE Or Cells(i, 5).Value = C_START_LATED Then 168 Cells(i, 5).Select 169 With Selection.Font 170 .ColorIndex = 3 171 .TintAndShade = 0 172 End With 173 End If 174 175 If Cells(i, 6).Value = C_END_LATE Or Cells(i, 6).Value = C_END_LATED Then 176 Cells(i, 6).Select 177 With Selection.Font 178 .ColorIndex = 3 179 .TintAndShade = 0 180 End With 181 End If 182 Next i 183End Sub 184 185'D6,E6のセルのカラーリング設定を削除する。 186Sub ColorReset() 187 Range("D6:F6").Select 188 Range(Selection, Selection.End(xlDown)).Select 189 With Selection.Font 190 .ColorIndex = xlAutomatic 191 .TintAndShade = 0 192 End With 193End Sub 194 195

よろしくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

自己解決されたようですが、問題点を指摘しておきます

使っている変数を宣言していないために意図しない結果になっています
使う変数は必ず宣言して「データ型」を明示しましょう
うまくいかないところはエラーになって教えてくれたり、変数名の打ち間違いやスコープの問題も早く解決できると思います

具体的な問題箇所は以下です

Cells(i, 2).NumberFormatLocal = "yyyy/m/d;@" foo = InStr(Cells(i, 2).Value, "(") If foo > 0 Then bar = Left(Cells(i, 2).Value, foo - 1) Else bar = Cells(i, 2).Value End If Cells(i, 2).Value = CDate("20" + bar)

※同じような処理をしている箇所も同様に

最初の状態でCells(i, 2)に入っている16/09/26(火)文字列と認識されます

変数barどこにも宣言されていないのでVariant型(どのような型のデータでも格納できる特殊な型)となります

bar = Left(Cells(i, 2).Value, foo - 1)

を実行するとVariant型変数 bar に 文字列 が代入されたと認識されます

その後の

Cells(i, 2).Value = CDate("20" + bar)

ですが、"20" + barの部分は**"20"をbarに入っている文字列に結合する**ことがおこなわれます

"20" と "16/09/26" の結合で "2016/09/26" となるので、ここまでは狙い通りだと思います

しかし2度目になると問題がおきます

Cells(i, 2)に入っている2016/09/26はエクセルの日付書式として正しいためDateと認識されます

bar = Left(Cells(i, 2).Value, foo - 1)
を実行するとVariant型変数 bar に Date値 が代入されたと認識されます

その後の

Cells(i, 2).Value = CDate("20" + bar)

"20" + barの部分は**"20"をbarに入っているDate値(2016/09/26)に加算する**ことがおこなわれます

"2016/09/26" の 20 日後なので "2016/10/16" と計算されます

もしもDim bar As Stringという宣言をしていたら、"20" + barは常に文字列の結合と解釈されるため、2度目の"20" + barを通ると202016/09/26となり、CDateでエラーになるでしょう

(処理の補足として、2回目以降はすでに 20 の文字が先頭に足されているので、20を先頭に足して日付に変換する処理そのものは不要ですね)

このように、変数宣言をしていないと予期しない問題がでてきますので、よほどのことが無い限りは必ず宣言するようにしましょう

なお、宣言忘れを防ぐ方法として、モジュール先頭行に必ずOption Explicitと書くことをおススメします

以上ご参考まで

投稿2017/09/26 06:24

編集2017/09/26 07:01
takito

総合スコア3111

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

King_of_Flies

2017/09/26 06:35

変数宣言をしないで変数を使用するとVariant型になることを今知りました。 変数に関しては、宣言をStringで固定しようと思います。 ありがとうございました。
King_of_Flies

2017/09/26 06:43 編集

変数の定義を含めます
guest

0

自己解決

解決しました。
Cells(i, 3).Value = CDate("20" + bar)の一行を
If分岐の中で処理させようと思います。

追記
コーディングについてのアドバイスは引き続き受け付けます。

投稿2017/09/26 05:49

編集2017/09/26 05:53
King_of_Flies

総合スコア382

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問