プロが教える店舗&オフィスのセキュリティ対策術

データを入力するシート『入力シート』があります。1行目は項目があり、2行目からデータを入力をしていきます。A~D列まで入力し、E列にチェックボックスがあり、シート1に出力する行はチェックボックスにチェックをいれます。このチェックボックスにチェックを入れた時にA~D列の中で空白セルがあった場合”未入力セルがあります。”とエラーメッセージを表示したいのです。
ご教授くださいませ。

質問者からの補足コメント

  • うーん・・・

    すみません、再度実行してみたら出来ました!!
    このチェックボックスのチェックをもう一度クリックしてチェックを外すことがありますが、チェックをクリックしても外れないのです・・・。どこか項目をdeleteしてチェックをクリックするとメッセージがでてチェックが外れるようになっています。。。
    もう一度教えてくださいませ。

    No.3の回答に寄せられた補足コメントです。 補足日時:2017/06/08 14:20
  • うーん・・・

    何度も追加追加で申し訳ございません。
    G列にチェックボックスのtrue false の表示をさせたいのと、F列にも同じ内容のチェックボックスを表示してこのtrue false の表示はH列に表示したいのですが、上手くいきません。。。
    ご教授いただけませんでしょうか。

    宜しくお願いいたします。

    No.4の回答に寄せられた補足コメントです。 補足日時:2017/06/10 02:30

A 回答 (8件)

これね、難しくはないんですけど


チェックボックスって フォームとActiveXの2種類あるのは
ご存知でしょうか?
そのどちらを使うかで様相が大きく変わります。
フォームは古いタイプなので今はActiveXが推奨だと思うんだけど
チェックボックスの数だけイベントの記述が必要です。
どちらを想定されていますか?
    • good
    • 0
この回答へのお礼

ありがとうございます。
フォームを使用しています。
チェックボックスの数は100個あります。

お礼日時:2017/06/08 07:43

今日は外に出てるので直接書けませんけど、callerを使うと呼び出し元が判定出来るので、そこから行が辿りつけると思います。

    • good
    • 0
この回答へのお礼

ありがとうございます。
調べてみましたが、答えまで行き着かなかったので、お帰りお待ちしています。
よろしくお願いします。

お礼日時:2017/06/08 11:39

ご質問は、なかなか難しいです。


既存のものに、それを実現させるのは難しいです。

>1行目は項目があり、2行目からデータを入力をしていきます。

'標準モジュール(統一コード)
Sub チェック1_Click()
Dim chkName As Variant
Dim n As Variant
Dim i As Long
chkName = Application.Caller
n = InStr(1, chkName, " ")
If n > 0 Then i = Mid(chkName, n + 1)
With ActiveSheet
 If Application.CountBlank(.Cells(i + 1, 1).Resize(, 4)) > 0 Then
  MsgBox "未入力セルがあります", vbExclamation
  .CheckBoxes(chkName).Value = xlOff
 Else
   .CheckBoxes(chkName).Value = xlOn
 End If
End With
End Sub

解説:

フォームコントロールならではですが、同じマクロを利用します。どのチェックボックスを触ったか、Application.Caller で名前を取ります。ActiveXコントロールでは、自作で同じ機能を持つプロパティを取り付けなくてはなりません。

「チェック 1 」などの「名前+空白+数字」または、「名+空白+名+空白+数字」というオブジェクト名であることが、条件です。「チェック 1」の末尾の1を使って、処理をする関係で、オブジェクト名が重要です。オブジェクト名と行が合っていない場合は、予備的なマクロで、オブジェクト名と合わせなくてはなりません。オブジェクトから行の位置を取り出すことも可能ですが、とても不安定でまともには行かない例も多くあります。

この1を取り出して、1+1 =2行目をCountBlank(4列分)で、0 でなければ、
エラー・メッセージを出します。

なお、こういうマクロは、チェックボックスを取り付けから、全部、マクロで設定するのが一般的で、一瞬できれいに貼り付けまで終わってしまいます。

'//標準モジュール
Sub AddCheckBoxes()
Dim c As Variant
With ActiveSheet
.CheckBoxes.Delete 'チェックボックスは一旦すべて消します。
For Each c In Range("A2", Cells(Rows.Count, 1).End(xlUp)) 'A2~最後行まで
With .CheckBoxes.Add(c.Offset(, 4).Left + Int(c.Width / 2), c.Top + 0.1, _
 c.Offset(, 4).Width, c.Height)
  .Caption = ""
  .Name = "Cb " & c.Row '行数とオブジェクト名を連動させる
  .OnAction = "MyMacro1" '統一マクロの登録
  .Placement = xlMove '行に合わせてオブジェクトが動く
  .Visible = True
 End With
Next
End With
End Sub

Sub MyMacro1()
'統一マクロ
Dim chkName As Variant
Dim n As Variant
Dim i As Long
chkName = Application.Caller
n = InStrRev(chkName, " ")
If n > 0 Then i = Mid(chkName, n + 1)
With ActiveSheet
 If Application.CountBlank(.Cells(i, 1).Resize(, 4)) > 0 Then 'i+1 ではなく、iになる
  MsgBox "未入力セルがあります", vbExclamation
  .CheckBoxes(chkName).Value = xlOff
 Else
   .CheckBoxes(chkName).Value = xlOn
 End If
End With
End Sub


以下は、興味がないようでしたら、無視して構いません。
●フォームコントロールかActiveX コントロールか?

同じ内容のActiveXコントロールで統一したマクロを作るつもりなら、Classインスタンス が必要です。実際に、似たようなマクロを100個も書いていたら大変なのです。

フォームコントロールとActiveX コントロールとどちらが良いというのは、はっきりと明言できませんでしたが、最近では、旧ファイルでActiveX コントロールで作ってきたものが、最近、トラブルを発生し、フォームコントロールに替えなくてはならない自体が起きています。

かつて、Microsoft 側では、Ver.5のフォームコントロールにあるものをなくす方法にあったようです。しかし、Office 2007以降、事情が変わったとしか言えません。その証拠に、開発-挿入-[フォームコントロール・ActiveX コントロール]と二者択一になっています。

ActiveX コントロールは、シートモジュール備え付けなので、同じ内容でも、基本的にはマクロの融通が利かない、別のコントロールを設けなくてはならないとか、コントロール配列が効かないなどの理由で、敬遠されることが多いようです。これは、あくまでも、ワークシート上のみに限られる問題です。Classで、擬似的にコントロール配列するぐらいなら、最初から、フォームコントロールを使ったほうが早いと言えます。
「エラーメッセージの表示vba」の回答画像3
この回答への補足あり
    • good
    • 0
この回答へのお礼

詳しいご説明までしていただきまして、ありがとうございます。
早速、2つ目のチェックボックスの貼り付けから全部マクロで行う方を実行してみたのですが、n = InStrRev(chkName, " ")→が方が違いますとエラーが出てきました。
そのまま貼り付けしたのですが・・・、何が問題なのでしょうか。教えてくださいませ。

お礼日時:2017/06/08 14:13

こんにちは。



>このチェックボックスのチェックをもう一度クリックしてチェックを外すことがありますが、チェックをクリックしても外れないのです・・・。

不思議なロジックになりますが、統一マクロの中で、CountBlank に0がないなら、マクロは中止という命令を入れれば、全部揃ってチェックが入れられている行のみ、チェックを外すことが可能になります。

'//
Sub MyMacro1()
'統一マクロ
Dim chkName As Variant
Dim n As Variant
Dim i As Long
Dim bln As Boolean '*
chkName = Application.Caller
n = InStrRev(chkName, " ")
If n > 0 Then i = Mid(chkName, n + 1)
With ActiveSheet
 bln = Application.CountBlank(.Cells(i, 1).Resize(, 4)) > 0 '*
 If bln = False Then Exit Sub 'マクロ中止
 If bln Then 'i+1 ではなく、iになる
  MsgBox "未入力セルがあります", vbExclamation
  .CheckBoxes(chkName).Value = xlOff
 Else
   .CheckBoxes(chkName).Value = xlOn
 End If
End With
End Sub
この回答への補足あり
    • good
    • 0
この回答へのお礼

お礼が遅くなり、説明不足もあり申し訳ありませんでした。
すごいです!!!

チェックが外れました!!!
本当にありがとうございます。

いただいたvbaを元に勉強させていただきます。
ありがとうございました。

お礼日時:2017/06/09 09:52

もうお答え出ていますが


ActiveSheet..CheckBoxes(Application.Caller).TopLeftCell.Row
を使うと押されたチェックボックスの行が
番号に関係なく得られるので
それを想定しておりました。

>このチェックボックスのチェックをもう一度クリックしてチェックを外すことがありますが
多分あなただけが判る、あるあるじゃないでしょうか?
当初の説明からどういう場合にそういうケースがあるかを
読み取れないと思います。

if ActiveSheet..CheckBoxes(Application.Caller).value then exit sub
でもいけそうな。
    • good
    • 0
この回答へのお礼

説明不足で申し訳ございませんでした。
色々と教えてくださり、ありがとうございました。

お礼日時:2017/06/09 09:52

チェックボックスってセルとリンクさせることができますよね。


その上で、Worksheet_Changeイベントプロシジャで、リンクしたセルの変更を拾って、チェックを行うのはどうでしょうか。

No.3の WindFallerさんの方式で、一括してリンク設定してしまえば、手間もかからないし・・・。

この後、チェックされている行だけを別シートに抽出みたいなことを行うと思うのですが、その際もセルの値で判断できるので、一石二鳥です。
    • good
    • 0
この回答へのお礼

すごい!
そうなんです。
この後チェックしている行だけ別シートに抽出するのですが、どうしようかなと今晩考えてみる予定でした。
ママチャリさんのご意見を軸に考えてみます。

またわからないところが出てきたら教えてくださいです。

お礼日時:2017/06/09 09:55

遅くなってすみません。

パソコンが、ついに故障しはじめて、朝8:30頃から、本日の14時ごろ立ち上がりました関係で、まだおっかなびっくりでPC触っている状態です。

以下は、既存のチェックボックスの付け足し機能ですが、マクロ自体は、同じ内容のものにしました。もし、思ったような具合でなかったら、私の、補足の読み間違えです。


''//
Sub AdditionalF_Checkboxes()
'前回のマクロの付け足し
Dim i As Long
Dim rng As Range
Dim cb As CheckBox
Dim flg: flg = False '★True にすると、付け足したCheckBoxの削除:通常 False
With ActiveSheet
If flg Then
'付け足しのチェックボックスのやり直し
 For Each cb In .CheckBoxes
  If UCase(cb.Name) Like "CB2*" Then
   cb.Delete
  End If
 Next
End If
 For i = 2 To .CheckBoxes.Count + 1  '★注意 2行目からなので、i=2
  If UCase(.CheckBoxes(i).Name) Like "CB*" Then
   .CheckBoxes(i).LinkedCell = "$G$" & CStr(i + 1) '2行目から始まるという条件で
   
   Set rng = .Cells(i, "F")
   With .CheckBoxes.Add(rng.Left + Int(rng.Width / 2), rng.Top + 0.1, rng.Width, rng.Height)
    .LinkedCell = "$H$" & CStr(i)
    .Name = "CB2" & Space(1) & CStr(i)
    .Caption = ""
    .OnAction = "MyMacro1"
    .Placement = xlMove
   End With
   End If
 Next i
End With
End Sub
    • good
    • 0
この回答へのお礼

お礼が遅くなり申し訳ございませんでした。
うまくいきませんでした。

私の説明が悪いと思います。
もう一度一から考え直します。
すみません。。。

何度も教えていただいてありがとうございました。

お礼日時:2017/06/13 09:25

パソコンが一時的だと思いますが、息を吹き替えしたようで今書き込み出来ています。

ただ、今、PCの主要部分はバックアップ中です。PCを新しくする予定です。

>思ったような具合でなかったら、私の、補足の読み間違えです。
うまく行かなかったのは、補足の読み間違えと書いた通りですが、同じ内容のチェックボックスを取り付けることを考えて作られたものです。それは、まずいとは思いながらも、既存のチェックボックス(それも、私が先に出したマクロで作られたチェックボックスに限ります)に付け足すマクロですから、一気に作り上げるものと違うので、何らかの問題が出ないとも限らないのです。

今、言えるのは、最初から、一気に全体的に作り上げたほうが確実だというしかありません。
「エラーメッセージの表示vba」の回答画像8
    • good
    • 0
この回答へのお礼

ありがとうございます。
もう一度考え直しまして、チェックボックスをやめて”1”を入力することにしました。作業列を設けてISBLANKの掛け算の計算式を入れ、E列に1を入力した時に『入力規を則』で(=OFFSET(E2,0,4)<>""を入力して)I列がブランクの時は入力規則のエラーメッセージを表示することにしました。

本当にいろいろとありがとうございました。

お礼日時:2017/06/16 02:44

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!