- 締切済み
ご教授願います。
VBA初心者です。 業務上で困っているのでどなたかご教授願います。 VBAは多少勉強しましたが、期限の関係上自力解決が困難となりました。 よろしくお願い致します。 <プログラム構成> userformを利用して、選択項目を設けます。 選択していった内容をデータシートに最終的に記録します。 例) userform1(userform名"色") ○赤 ○青 ○緑 ○黄 [次へ] [戻る] ←コマンドボタンで作成。[次へ]選択でuserform2へ。今回は赤を選択したとします。 userform2(userform名"種類") ○りんご ○トマト ○パプリカ ○東京タワー [次へ] [戻る] ←同様。今回はりんごを選んだとします。 userform3(userform名"季節") ○一月 ○四月 ○八月 ○十二月 [テキストボックスでコメント欄作成] [完了] [戻る] ←今回は四月を選択し、テキストには[甘い]と入力し、完了します。完了するとデータシートへ転送されるとします。 <データシートの構成> 色 種類 季節 コメント 赤 りんご 四月 甘い このように構成されます。また、次回登録したい場合は、空白セルを検索して前のデータの下に引き続き登録されていくようにしたいです。 <現在までの進度> userformを作成し、選択項目を選び、予め登録してあるuserformが表示されるところまでVBAでプログラムを組みました。 しかし、userformで選択していった項目をデータシートへ転送するやり方がわかりません。私の考えは、選択項目毎にuserformが予め登録されているので、完了ボタンを押せば今までの選択項目を転送されるように最後のuserformに登録していればいいのでは。と思っています。 なので今回では最後のuserfromの完了を押せば最後のuserfromの完了ボタンにデータシートへ"色"種類"季節"はもう"赤"りんご"四月(ここは選択項目を転送されるようにオプションコマンドにプログラム入力"をし、テキストボックスに入力されているコメントをそのまま転送されるのがいいと思いました。 ******************************** ここまで進めるのに苦労しましたので、今までのプログラムを使用したいのですが、最後のプログラムをご教授願いないでしょうか? 拙い御説明で不明瞭な点があると思いますが、よろしくお願い致します。 こまめに閲覧して返答してくださった方へのお礼、不明瞭な点の明確化を図っていきたいですが、私の返答が遅くなるかもしれません。 わがままばかりで申し訳ないですが、よろしくお願い致します。
- みんなの回答 (7)
- 専門家の回答
みんなの回答
- kmetu
- ベストアンサー率41% (562/1346)
フォームを消して進んでいく場合 都度unloadを利用したいのでしたら、グローバル変数等を利用して 閉じる前にデータを保存しておくか、都度セルに書き込む操作が必要と なります。 unloadではなくて UserForm1.Hide を利用してみればいかがですか 見えなくしているだけなので 戻ったときにボタンの選択状態も覚えていますし 現在のコードのunloadの部分を変更するだけですみます。 それで最後にすべてのフォームをunloadします。 エラーが出るのは消したために存在しなくなったオブジェクト UserForm1.OptionButton1.Captionなどを指定してるからだと思います。 フォームを開いたときにどのシートが見えているのか分からないのですが Range("a" & m_row).Value = UserForm1.OptionButton1.Caption は現在見えているシートにデータを書き込みます。 sheet2の最終行を調べて別のシートに書き込んだ場合 変なところに書き込むことになります。 sheet2限定にした方がよさそうなので先のコードを以下のように変更してください。 With Worksheets("sheet2") m_row = .Range("a" & Rows.Count).End(xlUp).Row + 1 If UserForm1.OptionButton1 = True Then .Range("a" & m_row).Value = UserForm1.OptionButton1.Caption ElseIf UserForm1.OptionButton2 = True Then .Range("a" & m_row).Value = UserForm1.OptionButton2.Caption 中略 .Range("c" & m_row).Value = UserForm2.TextBox1.Value End With Rangeの前にドット"."が存在することに注意してください。 シートの保護については何もそのあたり操作をしていないので原因は不明です。
- kmetu
- ベストアンサー率41% (562/1346)
> Worksheets(2)でシート名に関わらずシートを指定するか、 > Worksheets("変更したシート名") > か、ですね はい ただシートを順番(番号)で指定する場合気をつけないと 該当シートの左に新しいシートを追加したとか シートの位置を移動したりした場合 見当違いのシートを指定することになりますから 思わぬ動作になってしまって、全然見当違いの場所を変更してしまったりします。 マクロを実行した結果は元に戻すことができないと思いますので 深刻な結果になる可能性もあります。 それと違ってシート名で指定した場合は、シート名を変更しても 指定箇所でエラーになって止まりますからこちらのほうが無難でしょう。 とはいえ、シート名で指定できない状態になることもあるでしょうから 数値(変数も可)で指定できることを覚えておいても損はないと思います。
補足
度々すみません。 うまくいきませんでした。 今userformをオプションコマンドで進んでいく際に、「次へ」のボタンのプログラムに private sub commandbutton1 click() if (optionbutton1 value = true) then unload userform1 userform2.show Eself (optionbutton2 value = true) then unload userform1 userform2 ・・・ となっているのですが、前回ご教授頂いたプログラムだとuserfromを消して進んでいくのはどうもまずそうですね? 消さないで進んでいくしかありませんかね? 今「完了」のプログラムには前回ご指導頂いたプログラムをいれています。 後 m_row =Worksheets("sheet2").Range("a" & Rows.Count).End(xlUp).Row + 1 でsheet2のところに私が設定したシート名をいれているのですが、実行しても設定したシートに登録されなかったり。実行エラー1001が発生したりして、セルの保護を加えた覚えはないのですが保護されていてダメですとかでます。 どうしてでしょうか? 本当にわからずじまいで申し訳ありません。 よろしくお願い致します。
- kmetu
- ベストアンサー率41% (562/1346)
> シートは2で名前は変えているのですが、この場合名前は関係ないとはおもってはいたんで、変更したコードで大丈夫だとおもったのですが何がいけないのかわかりません。 シートの名前が不明なのでデフォルトの名前Sheet2を例示しているだけですので 名前を変更している場合その名前を指定します。 名前を指定しない場合、左からの順番を数値で指定します 左から2番目でしたら Worksheets(2) になります。
補足
なるほど! 今日はもう帰宅したので明日早速試してみます! シート指定の方法は2通りあるみたいですね。 Worksheets(2)でシート名に関わらずシートを指定するか、 Worksheets("変更したシート名") か、ですね。 これでよろしいんでしょうか? 早期返答ありがとうございます。
- kmetu
- ベストアンサー率41% (562/1346)
> >m_row = ActiveSheet.Range("a" & Rows.Count).End(xlUp).Row + 1ですがこれは空白セルを検索しているのでしょうか? A列のデータが入力された最終行の次の行番号を取得しています A15までデータが入っている場合16という数値がm_rowに代入されます > また、ActiveSheetのあとにActiveSheet1のようにシート番号(?)を入力すればよろしいのでしょうか? いえそのままActiveSheetでいいです、現在選択されているシートという意味です sheet2とか決まっているのでしたら Worksheets("sheet2").Range("a" & Rows.Count).End(xlUp).Row + 1 とかに変更してください > これはuserform1のオプションボタンを1~4までのどれかを選択した場合、先ほどのActiveSheetのセルのA列の空白行にオプションボタンの名前が入る。で理解してよろしいでしょうか? 最初に説明した行のA列のセル(説明の通りだとA16)に userform1の選択されたオプションボタンのCaption (ボタンの名前ではなくボタンの横のテキスト)が入ります。 次のブロックはform2の結果はB列にという流れになりますので ご自身のフォームの数にあわせて適宜追加してください。 > >Range("c" & m_row).Value = UserForm2.TextBox1.Value これはuserform2のテキストボックスがc列の空白行に転送されるでよろしいでしょうか? C列でA列のデータが入っている最終の次の行(最初に説明した通りだとC16) になりますのでもしそこに何かデータが入っている場合上書きします。 > 最後に確認なんですが、このプログラムは前回わたくしが説明しました「完了のコマンドボタンのvbaに書き込めばよろしいんでしょうか? はいそうです。
補足
返答が遅くなったにも関わらずご丁寧な回答ありがとうございます。 丁寧な説明のおかげでプログラム内容が理解できました。 しかし、初歩的な事どうもわかっていないのか、ご指導いただいた内容で自分のフォームに合わせて利用しましたがデバックエラー(?)がでてきました。 m_row = ActiveSheet.Range("a" & Rows.Count).End(xlUp).Row + 1ですが、ご指導いただいた通り m_row =Worksheets("sheet2").Range("a" & Rows.Count).End(xlUp).Row + 1 としましたが、エラーがでました。 シートは2で名前は変えているのですが、この場合名前は関係ないとはおもってはいたんで、変更したコードで大丈夫だとおもったのですが何がいけないのかわかりません。 たびたび申し訳ありませんがご指導お願い致します。
- hornet3
- ベストアンサー率19% (12/62)
今月いっぱいなら楽勝ですね。 (1)入れたいセルに入れたい値を入れる。 (2)テキストボックスの内容をボタンを押したときにセルに入れる。 (3)オプションボタンで選択した内容をセルに転送する。 (4)シートのどの行まで値が入っているか調べる。 (5)空白の行を探して値を入れる。 (6)完了ボタンをおすまで選択した内容を一時的に覚えておき、完了ボタンを押したときに一度に値がはいるようにする。 の順にやっていきましょう。一度に説明すると混乱するのでひとつづつ。 (1)シートとセルを指定して、値を入れるには、以下のようにします。 Sheet1.Cells(4,2).Value = "甘い" Sheet1という名前のシートの4列2行目に”甘い”という文字列が入ります。
補足
返答が大変遅くなり申し訳ありません。 また、返答ありがとうございます。 順番は理解できました。 Sheet1.Cells(4,2).Value = "甘い" これも理解できました。
- kmetu
- ベストアンサー率41% (562/1346)
Dim m_row m_row = ActiveSheet.Range("a" & Rows.Count).End(xlUp).Row + 1 If UserForm1.OptionButton1 = True Then Range("a" & m_row).Value = UserForm1.OptionButton1.Caption ElseIf UserForm1.OptionButton2 = True Then Range("a" & m_row).Value = UserForm1.OptionButton2.Caption ElseIf UserForm1.OptionButton3 = True Then Range("a" & m_row).Value = UserForm1.OptionButton3.Caption ElseIf UserForm1.OptionButton4 = True Then Range("a" & m_row).Value = UserForm1.OptionButton4.Caption End If If UserForm2.OptionButton1 = True Then Range("b" & m_row).Value = UserForm2.OptionButton1.Caption ElseIf UserForm2.OptionButton2 = True Then Range("b" & m_row).Value = UserForm2.OptionButton2.Caption ElseIf UserForm2.OptionButton3 = True Then Range("b" & m_row).Value = UserForm2.OptionButton3.Caption ElseIf UserForm2.OptionButton4 = True Then Range("b" & m_row).Value = UserForm2.OptionButton4.Caption End If Range("c" & m_row).Value = UserForm2.TextBox1.Value Unload UserForm2 Unload UserForm1 こんな感じでいかがでしょう フォームはとりあえず2個にしていますのでご自身の環境に合わせて 増やしてください。
補足
返答が大変遅くなり申し訳ありません。 また、返答・プログラムのご教授ありがとうございます。 プログラムに関して質問をさせてください。 >m_row = ActiveSheet.Range("a" & Rows.Count).End(xlUp).Row + 1 ですがこれは空白セルを検索しているのでしょうか? また、ActiveSheetのあとにActiveSheet1のようにシート番号(?)を入力すればよろしいのでしょうか? >If UserForm1.OptionButton1 = True Then Range("a" & m_row).Value = UserForm1.OptionButton1.Caption ElseIf UserForm1.OptionButton2 = True Then Range("a" & m_row).Value = UserForm1.OptionButton2.Caption ElseIf UserForm1.OptionButton3 = True Then Range("a" & m_row).Value = UserForm1.OptionButton3.Caption ElseIf UserForm1.OptionButton4 = True Then Range("a" & m_row).Value = UserForm1.OptionButton4.Caption End If これはuserform1のオプションボタンを1~4までのどれかを選択した場合、先ほどのActiveSheetのセルのA列の空白行にオプションボタンの名前が入る。で理解してよろしいでしょうか? >Range("c" & m_row).Value = UserForm2.TextBox1.Value これはuserform2のテキストボックスがc列の空白行に転送されるでよろしいでしょうか? 最後に確認なんですが、このプログラムは前回わたくしが説明しました「完了」のコマンドボタンのvbaに書き込めばよろしいんでしょうか? 以上、返答が大変遅くなりましたが、もう一度見ていただいたなら回答していただきたいと思います。 よろしくお願い致します。
- hornet3
- ベストアンサー率19% (12/62)
(1)なんのVBAでしょう?エクセル?アクセス?オートキャド?・・・ (2)期限はいつまでですか?(あんまり短期間だとソースでやりとりしないと無理かと・・・。)
補足
早期返答ありがとうございます。 (1)なんのVBAでしょう?エクセル?アクセス?オートキャド?・・・ >>エクセルです。他にもVBAがあるのを忘れていました。 (2)期限はいつまでですか?(あんまり短期間だとソースでやりとりしないと無理かと・・・。) >>今月中くらいが一応期限です。ソースとは現在までのプログラム構成ということでしょうか? 申し訳ありませんが内容そのものはご提示できませんので、例でしかこちらとしてもご対応できません。 返答していただいたのに申し訳ありません。 不明瞭な点がございましたらこちらで再度例などを提示させていただきます。 宜しくお願い致します。
補足
たびたびのご回答ありがとうございます。 unloadではなくてhideなどがあるのですね。 なるほど。英語の意味でも隠すといった意味がありますもんね。 プログラムの勉強をしている際に英語の意味があてはまることからして言われてみればわかります。 ありがとうございます。 ちなみに書き込むシート選択肢によって利用する場合、どこかを変数表示すればいいのかはわかりますけど、 どこを 前おきのプログラム?がどういったものが必要か などがわかりません。 kmetuさんの御説明は大変わかりやすく、関心させていただいてますが、vbaがとても便利で楽しいものだと思ってきました。 これも一重にkmetuさんのおかげです。 何度も申し上げていますが本当にありがとうございます。