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

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

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

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

Windows

Windowsは、マイクロソフト社が開発したオペレーティングシステムです。当初は、MS-DOSに変わるOSとして開発されました。 GUIを採用し、主にインテル系のCPUを搭載したコンピューターで動作します。Windows系OSのシェアは、90%を超えるといわれています。 パソコン用以外に、POSシステムやスマートフォンなどの携帯端末用、サーバ用のOSもあります。

Q&A

解決済

6回答

3653閲覧

マクロの判定文の書き方

Alice0225

総合スコア206

VBA

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

Windows

Windowsは、マイクロソフト社が開発したオペレーティングシステムです。当初は、MS-DOSに変わるOSとして開発されました。 GUIを採用し、主にインテル系のCPUを搭載したコンピューターで動作します。Windows系OSのシェアは、90%を超えるといわれています。 パソコン用以外に、POSシステムやスマートフォンなどの携帯端末用、サーバ用のOSもあります。

1グッド

0クリップ

投稿2016/01/28 08:24

編集2016/01/28 08:24

現在マクロを作成しており、
「Excelファイル内の入力必須セルに入力がない場合の処理」をコーディングしています。
入力必須セルは3つあり、未入力の項がある場合は
「入力必須の(~~~)が入力されていません」というエラー文を表示させます。
上記の(~~~)にあたる部分を作るに際し、

全て入力されている
Aが未入力
AとBが未入力
AとBとCが未入力
Bが未入力
BとCが未入力
Cが未入力
AとCが未入力

のパターンが考えられる為、下記のように仮実装しました。

VBA

1'未入力判定 2 If A = 1 & B = 1 & C = 1 Then 3 error01 = "" 4 ElseIf A = 0 And B = 1 And C = 1 Then 5 error01 = "A" 6 ElseIf A = 0 And B = 1 And C = 0 Then 7 error01 = "A,B" 8 ElseIf A = 0 And B = 0 And C = 0 Then 9 error01 = "A,B,C" 10 ElseIf A = 1 And B = 0 And C = 1 Then 11 error01 = "B" 12 ElseIf A = 1 And B = 0 And C = 0 Then 13 error01 = "B,C" 14 ElseIf A = 1 And B = 1 And C = 0 Then 15 error01 = "C" 16 ElseIf A = 0 And B = 0 And C = 1 Then 17 error01 = "A,C" 18 End If

※エラーが複数ある場合は間を「,」で区切りたい。(重要)

上記コードを簡略化(というか効率化…?)させたいのですが、どのような方法が考えられますでしょうか。
現在は3つ(A,B,C)の組み合わせですが、5つ 8つ などと個数が増える場合にも流用できるものであると助かります。

thom.jp👍を押しています

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

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

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

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

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

guest

回答6

0

ベストアンサー

単純に、error01 にエラーを羅列(?)したいという事で良いでしょうか。
以下のような感じではどうでしょうか。

※VBAってあんまり触ったことがないのでコーディングがおかしかったら適宜修正してください。
※ロジックの一例です。

VB

1error01 = "" 2 3If A = 0 Then 4 If error01 <> "" Then error01 &= "," 5 error01 &= "A" 6End If 7 8If B = 0 Then 9 If error01 <> "" Then error01 &= "," 10 error01 &= "B" 11End If 12 13If C = 0 Then 14 If error01 <> "" Then error01 &= "," 15 error01 &= "C" 16End If

もしエラーだったら、まず error01 が空かどうかを調べて、空でなければカンマを追加します。
それからエラー文字列を追加していきます。
どうですかね。


【追記】

VBA も三項演算子 使えるのか。そっちのほうがすっきりしますかね。

VB

1If A = 0 Then 2 error01 &= IIf(error01 <> "", ",", "") & "A" 3End If

本当に例示のように、変数の桁数が揃ってるなら、このくらいの長さなら一行で書いちゃいますかね 私なら。
変数名の桁数が異なるようだとガタガタして見辛い気がしますが。

VB

1If A = 0 Then error01 &= IIf(error01 <> "", ",", "") & "A" 2If B = 0 Then error01 &= IIf(error01 <> "", ",", "") & "B" 3If C = 0 Then error01 &= IIf(error01 <> "", ",", "") & "C"

(VB ではこの書き方ができますが、VBA はどうだろう)

投稿2016/01/28 08:55

編集2016/01/29 02:54
sk_3122

総合スコア1126

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

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

Toyoshima

2016/01/28 09:02

ネストしてるIF文に対応するEndIfが無いですが・・・ sk_3122さんのカンマ考慮、お見事です!
Alice0225

2016/01/29 01:15

ご回答ありがとうございます。 3行で済んでしまうんですね…。
sk_3122

2016/01/29 02:56

すみません、三項演算子の箇所の記述をミスっていたので直しておきました。一応。 誤:error01 &= IIf(error01 <> ",", "") & "A" 正:error01 &= IIf(error01 <> "", ",", "") & "A" IIf(条件, Trueの場合の値, Falseの場合の値)
Alice0225

2016/01/29 09:41

今回は「行数が少なく簡単に実装できる」sk_3122様の回答をベストアンサーとさせていただきました。 ご回答ありがとうございました!
guest

0

ちょっと趣旨とズレるかもしれませんが、セル限定で汎用的にするならセル側に必須入力の目印をつけてしまって(たとえば背景色とか)、

シートサンプル

コードでその目印を探すという手もあります。

lang

1Sub Sample() 2 Const 薄黄色 = 19 3 Dim セル As Range 4 Dim エラー As String 5 6 For Each セル In Sheets(1).Range("c4:c8") 7 If セル.Interior.ColorIndex = 薄黄色 And セル = "" Then 8 エラー = エラー & セル.Offset(0, -1).Value & ", " 9 End If 10 Next 11 エラー = Left(エラー, Len(エラー) - 2) 'カンマをけずる。 12 13 MsgBox エラー & "が未入力です。" 14End Sub

投稿2016/01/28 13:53

thom.jp

総合スコア686

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

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

Alice0225

2016/01/29 01:05

ご回答ありがとうございます。 そのような手法もあるのですね…。 ちょっと今回はExcelファイルの仕様を変えることが出来ないので今後に活かさせて頂きます。
guest

0

最近触ってない上、試してないのでエラーがあるかもしれませんがご参考になれば幸甚です。
項目がフォームではなくセルとのことですのでRangeオブジェクトで動的に値を取得できると思います。
これなら、5つ 8つ などと個数が増える場合にも流用できるかと思います。

下記は項目のセル位置が連続していない場合に有効です。

Dim cells() As String Dim err As String '入力必須カラムを「;」区切りで指定 cells = Split("A1;B1;C1", ";") err = "" For Each cell In cells() If Range(cell).Value = "" Then err = err & cell & "," End If Next cell If err <> "" Then '末尾のカンマを削除 err = LEFT(err, LEN(err) - 1) End If

下記は項目のセル位置が連続している場合に有効です。

Dim rng As Range Dim err As String Set rng = Range("A1:C9") err = "" For Each r In rng If r.Value = "" Then err = err & r.Address(False, False) & "," End If Next r If err <> "" Then '末尾のカンマを削除 err = LEFT(err, LEN(err) - 1) End If

投稿2016/01/28 10:00

編集2016/01/29 03:12
xenbeat

総合スコア4258

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

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

Alice0225

2016/01/29 01:12

ご回答ありがとうございます。 cellsに範囲(A1:C9等)を指定することは可能なのでしょうか?
xenbeat

2016/01/29 03:08

最初のサンプルコードは範囲指定できないものとなります。ポツポツと対象セルが散らばっている状況では有効かと思います。ロジック的にはあまり変わりませんが範囲指定できるサンプルを追記させていただきました。手元に実行環境がないのでこちらも未検証です。
Alice0225

2016/01/29 09:26

追記ありがとうございます。 全てにおいて後ろにカンマをつけ、最後に一番後ろのカンマを消す手法なのですね。 私は頭が固いので柔軟な発想でびっくりです…
guest

0

こんな感じでどうでしょう

error01 = "" If A = 0 Then error01 = "A" End If If B = 0 Then error01 = error01 + IIf(Len(error01) > 0, ",B", "B") End If If C = 0 Then error01 = error01 + IIf(Len(error01) > 0, ",C", "C") End If

個数が増えるなら関数にしたほうがよいでしょうね

ご参考までに

投稿2016/01/28 09:47

takito

総合スコア3111

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

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

Alice0225

2016/01/29 01:13

ご回答ありがとうございます。 この手法だとすっきりしていて見やすく使いやすそうですね!
guest

0

手元に Excel がないので検証していませんが、こんなのはどうでしょう。

VBA

1Dim xCellRows(3) As Long 2Dim xCellCols(3) As Long 3Dim strError(3) As String 4xCellRows(0) = 3: xCellCols(0) = 4: strError(0) = "A" ' 3 行目 4 列目のセルが空かチェック。空の場合は "A" というメッセージ 5xCellRows(0) = 5: xCellCols(0) = 5: strError(1) = "B" ' 5 行目 5 列目のセルが空かチェック。空の場合は "A" というメッセージ 6xCellRows(0) = 6: xCellCols(0) = 5: strError(2) = "C" ' 6 行目 5 列目のセルが空かチェック。空の場合は "A" というメッセージ 7' 8Dim strMessages(3) As String 9Dim indexMessage As Integer: indexMessage = 0 10Dim indexCell As Integer: indexCell = 0 11For indexCell = 0 To 2 12 If .Cells(xCellRows(indexCell), xCellCols(indexCell)) == "" Then 13 strMessages(indexMessage) = strError(indexCell) 14 indexMessage = indexMessage + 1 15 End If 16Next indexCell 17Dim i As Integer 18Dim strResult As String: strResut = "" 19If indexMessage > 0 Then 20 strResult = strMessage(0) 21 For i = 1 To indexMessage - 1 22 strResult = strResult & "," & strMessage(i) 23 Next i 24End If

最後のメッセージをカンマ区切りにする処理は、ReDim で配列の長さを変えて Join 関数でやるというのもいいかもしれません。

あと、これくらいの処理になると、私はクラスを作ってしまいます。その方が見通しがよくなるので。

あと、Excel 自体の機能で、セルに入力規則を設定して、空白の場合にはエラーメッセージを出すというのもできたと思いますが、それだとマクロを使うまでもないのですが、それでは駄目なんでしょうか。

投稿2016/01/28 09:19

unau

総合スコア2468

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

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

Alice0225

2016/01/29 01:11

ご回答ありがとうございます。 初心者なのでよくわからない部分がちょこちょこあるのですが、 これはどのような処理の流れになるのでしょうか。
unau

2016/01/29 01:45

最初の 6 行が、「このセルは空じゃ駄目で、空だった場合にはこのエラーメッセージを出す」というのを 3 セル分記述してあるところです。「:」を使っているところは、ひとまとりまりの意味を持つ処理をまとめて書いたところです。複数行を「:」でつなげるのをマルチステートメントと呼びます。 8 行目からがメインの処理で、セルをチェックしていって、空のところがあったら strMessages という配列に格納していきます。次は配列の何番目に格納すればいいのか、というインデックスが indexMessage になります。 もし、VBA を動かす環境があるなら、デバッガで一つ一つ進めながら変数の中身がどうなるか見ていくのもよいのではないでしょうか。Excel はそういう統合開発環境としてもたいへん優れていると思います。
Alice0225

2016/01/29 09:39

ご説明ありがとうございます。 中々初心者の自分には難しいですね…
guest

0

検証してませんが・・・こうですかね・・・

VBA

1Dim error1 As String 2If A=0 Then 3 error1 = "A" 4EndIf 5If B=0 Then 6 error1 = error1 & ",B" 7EndIf 8If C=0 Then 9 error1 = error1 & ",C" 10EndIf

投稿2016/01/28 08:50

Toyoshima

総合スコア422

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

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

Toyoshima

2016/01/28 09:01

ああ・・・・sk_3122さんのほうが正解です・・・。 Aの判定ブロックに入らないパターンが漏れてました。。 お恥ずかしい・・・。
Alice0225

2016/01/29 01:17

ご回答ありがとうございます。 私も最初同じ様な考えで作成をし、途中で破綻していることに気付きまして… そのあとはずっと混乱してしまっています(笑)
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.47%

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

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

質問する

関連した質問