こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

締切り済みの質問

VBA ユーザーフォーム

エクセルVBAのユーザーフォームのInitializeでnに値を代入し

Private Sub UserForm_Initialize()
Dim n As Long
n = 19
・・・・・
End Sub

同じユーザーフォームのボタンコマンドが押されたら

Private Sub CommandButton2_Click()
MsgBox n
Worksheets("AAA").Cells(n, 3).Value = Me.テキストボックスの値.Text
n = n + 1
End Sub

nの値を用いてセルにテキストボックスの値を入れるというプログラムです。

値をいれたら、nをひとつ増やして次に備えるようにしたいのですが。

そもそも最初にnの値が受け渡しできません。
ボタンコマンドの最初の行でメッセージボックスにnの値を表示して確認しても何も数字が表示されません。

nの値の受け渡しを方法を教えてください。

投稿日時 - 2017-04-18 17:52:52

QNo.9319015

困ってます

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(2)

ANo.2

#1で説明つくされていると思いますが。
私もこういう件で、初心者で、手こずった経験があります。
ーー
総論として、本件はUserFormの初めのころの勉強で、やっていると思いますが、
「シートのセルの入力にuserフォームを使うのは」得策ではないと思います。多列の(多項目、多フィールドの。テキストボックスだけでなく、コンボボックスやオプションボタンなども利用した、多項目の入力を(初めての人に)本格的に必要項目の入力を全うさせるための、入力ツールを作る(チェックシステムも組み込む)ならこういう場合は、こういうことは必要ですが。)
直接シートに入力させる方が、簡潔で戸惑いがないでしょう。
本題にかえって
ーーー
(1)本質問は、変数のスコープという、一番VBA学習の大切かつ早く学ぶべきことと関連していると思いました。
http://excel-ubara.com/excelvba1/EXCELVBA408.htmlなど
「VBA 変数 スコープ」で照会
>上記記事内の
・シートモジュール・・・シート毎に存在します
・ブックモジュール・・・ブックで1つだけ
・フォームモジュール・・・作ったフォームの数だけ
・標準モジュール・・・好きなだけ作れます
・クラス
の区分け意識は重要でしょう。
(2)Public変数の話題があります。
「VBA 変数 Public」で照会。
Public変数も弊害が出る場合もあります。
諸言語プログラムの方針の流れとしては、別モジュールに影響をできるだけ与えないような仕組みを作り、使わせる、が基本方針でしょう。Privateというのはそういう思想でしょう。
(3)モジュールレベル変数
http://tonari-it.com/public-and-call-procedure/
>「何でもかんでもモジュールレベル変数にするべきではありません。プロシージャ内で完結する変数はDimを使うようにして、どうしてもプロシージャをまたがって使いたいもののみモジュールレベル変数にしましょう」
(3)STATIC変数の話題もあります。
http://www.asahi-net.or.jp/~ef2o-inue/vba_k/sub04_050_04.html
の「モジュールレベルの変数」のStaticの部分
(4)プロシージャ―の実行をCallで使い、前段階で決まる変数を引数に指定して、確実に渡すことを推奨している方針もあります。
ーー
それとVBAではVBEのメニューのVBAのプログラムの「実行」では、「SUB/ユーザーフォームの実行」となっていて、ユーザーフォームのInitializeイベントを指定して入れておくと
Private Sub UserForm_Initialize()
n = 1
MsgBox n
'UserForm1.Show
End Sub
このnはシートの1行目を指すnとして使えるようです。
ーー
また
Sub test02()
n = n + 1
MsgBox n
End Sub
のように
n = n + 1
を初めの方に入れておくと、nは初期化していないのに、初めにnは1
として使えます。其の後n=n+1を使う。
これは推奨されるやり方ではないかもしれないのですが。
Ststicにしておくと、他のモジュールの部分に実行コントロールが行って帰ってきても安全でしょう。
ーー
また
Private Sub UserForm_Initialize()
n = 1
MsgBox n
UserForm1.Show vbModal
End Sub
の vbModalを入れておいた方が、経験では、入力中にシートのセルに誤って空白セルを作ってしまわなくてよいようです。
ーー
UserFormはVBAでは有名ではありますが、解説書は少なく(Amazonで出てくるのは4本のみ。署名になっているのは技術評論社の1本のみ。他は1部分で解説は以外に多数あろう。)、貼り付けるコントロールの説明しかない本も多く、独学だと基礎的な(仕組みの)勉強に苦労します。

投稿日時 - 2017-04-19 12:00:57

お礼

回答ありがとうごあいました。
お礼メールが遅くなりもうしわけりませんでした。
お気づきの通り初心者です、何度もOKWEBで質問させていただき勉強している毎日です。
ただし確実にスキルはついていると感じています、今後ともよろしくおえがいいたします。

投稿日時 - 2017-05-17 09:46:15

ANo.1

変数には有効となる範囲が存在します。
今回の場合、UserForm_InitializeとCommandButton2_Clickは別のプロシージャとなります。
Dimでプロシージャ内で宣言した変数は、そのプロシージャ内でのみ有効となる変数ですので、ほかのプロシージャからは参照できません。
たとえば、Callなどで別のプロシージャに値を渡して利用するには、値渡しとして以下のように引数を指定して値を受け渡します。

Sub test1()
  Dim n As Integer
  n = 19
  Call test2(n)
End sub
Sub test2(a As Integer)
  msgbox a
End sub

値の渡し方には、元のプロシージャの変数内容が変更される参照渡しと、値だけを渡して別の変数とする値渡しがあります。
http://officetanaka.net/excel/vba/tips/tips94.htm

今回の場合別のプロシージャで値を設定して、ボタンで値を参照するので、こちらのようにプロシージャからプロシージャを呼び出すわけではありません。

プロシージャ間で同じ変数を共有させる方法としてモジュールの先頭にて変数を宣言することで、プロシージャではなく、モジュール内共通の変数を作ることができます。
UserFormモジュールの先頭にて以下のように変数nを宣言してください。

'モジュール間で共有の変数を作成
Dim n As Long
'フォームが呼び出されたら実行
Private Sub UserForm_Initialize()
  n = 19
End Sub
'ボタンがクリックされたら実行
Private Sub CommandButton2_Click()
  MsgBox n
  Worksheets("AAA").Cells(n, 3).Value = Me.テキストボックスの値.Text
  n = n + 1
End Sub

詳しくは変数のスコープで調べてみてください。
http://officetanaka.net/excel/vba/variable/05.htm

投稿日時 - 2017-04-19 09:16:12

お礼

回答ありがとうごあいました。
勉強になりました。
VBAに関して初心者で、何度もOKWEBで質問させていただき勉強を重ねているところです。
今後ともよろしくお願いいたします。

投稿日時 - 2017-05-17 09:47:56

あなたにオススメの質問