• 締切済み

VBAに関して、プロシージャが大きく悩んでいます。

回答よろしくおねがいします。 現在、全国の各都道府県のある数値を測るプログラムを改良しています。 入力画面に人口等の数値を入力すれば自動的に計算が行われるプログラムなんですが、現在改良する際にプログラムが大きくなりすぎて悩んでいます。 入力画面はユーザーフォームで作成してあるのですが、改良を行うとプロシージャが大きすぎますと警告が出ます。 そこでprivate subを用いて3つにプログラムを分け、最後にcallでそれらを選択したが計算されませんでした。 元々あったプログラム(改良前のものなので普通ならばできるはず)をprivate sub1、private sub2、private sub3として同じユーザーフォーム内に3つに分割しました。それぞれきちんと定義はしてあります。最後にcallで3つを呼び出したのですが、何一つ計算されませんでした。エラーが出るわけでもありません。入力画面にて入力された数値はひとつのprivate subにのみ有効なんですか? 現在この問題に対して考えているのは、本筋(ユーザーフォーム内のプログラム)を定義のみとし、ifやcallを使い別のモジュールで計算させ結果だけ本筋に戻すことを考えています。こういったことは可能でしょうか? 可能な場合は具体的にどういうプログラムになるのか教えていただければありがたいです。 よろしくお願いいたします。

みんなの回答

  • chayamati
  • ベストアンサー率41% (254/607)
回答No.4

大変ですね システムを[変数の宣言を強制する]なっていますか 変数名の入力ミスはありませんか 自分の体験でですが 変数名に[_](アンダーバー)をいれた変数を 途中からアンダーバーを抜いて記述したりして期待通りの結果が得られないことが よくありました。 このようなポカミスはなかなか見つけにくく苦労しました。 変数を宣言しなくとも暗黙の宣言として取り扱われます。 変数の宣言を強制するにして実行するとエラーに引っかかります [ツール]→[オプション]→[編集]→[変数の宣言を強制するにチェックを入れる]

回答No.3

こんにちは。 他の方がお答えになっていない点を回答させていただきます。 >改良を行うとプロシージャが大きすぎますと警告が出ます。 「プロシージャが大きすぎます」というのは、残念ながら、コードの書き方そのものが失敗しています。確かに行数が多いという事実の他に、コードにセル座標が散りばめてあるということで、それは、VBAのコードとして、マクロの用をなさないのです。私は、何万行というコードでシステムを書いたことがありますが、そのような警告表示はでません。 そういう場合は、設計の段階から、構造的に組み立て、はじめから書きなおさないと、直しようがないのです。 >元々あったプログラム(改良前のものなので普通ならばできるはず)をprivate sub1、>private sub2、private sub3として同じユーザーフォーム内に3つに分割しました。 同じユーザーフォーム内にあるのなら、ローカルモジュールへのPrivate ステートメントでも問題はないのですが、その内容にもよります。 あまり、いろんなことを言っても混乱するだけでしょうから、丁寧に、ステップ(F8)でコードを追いかけてみることでしょうか、それ以上は、今の段階では分かりません。

  • tsubuyuki
  • ベストアンサー率45% (699/1545)
回答No.2

> 入力画面にて入力された数値はひとつのprivate subにのみ有効なんですか? とりあえず、ここに関して簡単に説明すると、 プロシージャのはじめで宣言、つまり以下 Dim AAA As Integer Private Sub Sub1()   AAA=10   Call Sub2 End Sub Private Sub Sub2()   Range("A1")=AAA   Call Sub3 End Sub Private Sub Sub3()   Range("A2")=AAA End Sub のような構成にすると、全てで同じ変数を使えます。 良かったら、新規ブックにでも貼り付けてお試しくださいませ。 Private Sub  ~  Sub 内で宣言すると、その中でしか使えません。 で、大きすぎる件ですが・・ 残念ながら、私もそんなに大きなモノを組んだことが無いので何とも言えません。 取り得る手段としては、やはり分割するとか、無駄な処理を省くだとか、 逆に同じ処理をするところをなんとかループさせるとか・・ そのくらいしか思いつかないです。 中身を見れば何か思いつくかもしれませんが、ココではそれも不可能です。 1番さんもおっしゃる通り、ツールを駆使して地道にデバッグしていくしかないかなぁ・・ と言うのが正直なところです。

  • ap_2
  • ベストアンサー率64% (70/109)
回答No.1

> 何一つ計算されませんでした。 たぶん・・・関数間で値の受け渡しができてないと思う。"変数"は関数内でのみ有効です。 > 別のモジュールで計算させ結果だけ本筋に Private宣言しなければ、他モジュールから呼び出せます。Public Sub か、Sub (デフォルトがPublicなので省略可能)。  'こんな感じで  Private Sub 元の関数()   変数 = フォーム '取得   Call 処理1(変数) '情報渡す   Call 処理2(変数)   フォーム = 変数 '出力  End Sub  '~別モジュール~  Sub 処理1(引数)   引数 = 引数 + 1 '引数は読書可能  End Sub ※モジュール間で関数名が重複する場合は、Module1.処理1()と区別します。 > プロシージャが大きすぎますと警告 相当なサイズですよね。ループ使うとか、処理を工夫した方がよさそうです。配列を使えるとループしやすいかも。 言ってるコトはソレっぽいので、ちょっと入門書かじれば出来るはず。「ステップ実行」「ブレイクポイント」「ローカルウィンドウ」あたりは便利な機能なので、使えるようになっとくといいですよ。 ・・・こんな感じでよいかな?

関連するQ&A

  • VBAでcallで呼び出したsubを終了させる

    VBAです。 ユーザーフォーム上で、call xxxxxを使って呼び出したsubプログラムでの計算を 途中で終了させるために コマンドボタンにendを割り当てて使用しています。 ただ、この方法だとユーザーフォームも一緒に終了してしまうため、 また再度ユーザーフォームを呼び出す必要があります。 callで呼び出したsubプログラムだけを途中で終了させる方法を教えてください。

  • VBAでユーザーフォームのcaption表示

    VBAを初めたばかりです。 VBAでユーザーフォームを作成したのですが ユーザーフォームプロパティのcaptionで入力しても 下記プログラムで入力しても表示されません。 VBA作成時の画面にはしっかりと「項目」と 表示されていますが、プログラムを実行してユーザーフォームを 呼び出すと何も表示されていません。 ご教授ください。 Private Sub UserForm_Initialize() UserForm1.Caption = "項目" With ListBox1 .AddItem "1" .AddItem "2" End With End Sub

  • エクセルVBA イベントプロシージャに引数を渡せま

    お世話になります。 エクセル2003/XP 使用です。 イベントプロシージャに引数を渡せまるかどうか教えていただけますでしょうか? 下記のコード中の変数mysheetnameを ユーザーフォーム、→ CommandButton1のプロシージャに 引数として渡して行きたいのですが、 実行すると、一番最初のWorkbook_SheetBeforeRightClickの時点で、 コンパイルエラー:  プロシージャの宣言が、イベントまたはプロシージャの定義と一致していません。 とエラー表示されます。 イベントプロシージャに引数を渡すことはできますでしょうか? ---------- ThisWorkBook内 ---------- Public mysheetname As String Private Sub Workbook_SheetBeforeRightClick(ByVal Sh As Object, ByVal Target As Range, Cancel As Boolean) mysheetname = ActiveSheet.Name UserForm1.Show (mysheetname)     '←変数mysheetnameの値をユーザーフォームに渡したい。 End Sub ---------- ユーザーフォーム ---------- Private Sub UserForm_Initialize(ByVal mysheetname As String ) 処理 End Sub Private Sub CommandButton1_Click(ByVal mysheetname As String ) 処理 End Sub ’--------- ここまで 引数について少し理解し始めたばかりの者です。 よろしくお願いします。

  • Excel VBA ユーザーフォームのテキストボックスで

    Excel2000or2003でマクロを作っております。 ユーザーフォームのテキストボックスで、例えば時間を入力するとします。 Private Sub TextBox1_Change() Worksheets("Work").Range("B3").Value = TextBox1 End Sub と書いたところ、セルには数値としてではなく文字として入ってしまうようで、後のルーチンで計算できません。 数値として扱うには、どうしたら良いでしょうか? お手数ですが、ご教授願います。

  • プロシージャをまたいて変数を扱いたい!

    こんばんは! プロシージャ間での変数の取り扱いについて読んでいてよく分からないので教えて頂きたいです。 現在、ユーザーフォームにて下記のコードを記述していますが、テキストボックス1に表示するiの値を初めは50として、正解ならiに1を加算、不正解ならi から1を減算して、テキストボックス1の内容を更新するようにしたいのですが、どのように記述すればよろしいでしょうか。 ----------------------------------------------- private sub userform_initialize() Textbox1 = int(i) end sub ----------------------------------------------- private sub commandbutton1_click() If 条件式 then "正解" else "不正解" end if call userform_initialize() end sub ------------------------------------------------- commandbutton2 以降省略

  • Private Sub内でSubをCallしたい

    Excel 2007でVBAを組もうとしています。 ユーザーフォームのコマンドボタンをクリックすると動く処理を Private Sub 内に書きましたが、処理が長くなりましたので、 Subに分けたいと思います。 Private subからSubプロシージャをCallすることはできますか? またどのSubでも同じ変数を使う場合、定義は、各Sub内で 毎回行う必要がありますか? 引数渡しのところがよく分からないので、すみませんが よろしくお願い致します。

  • EXCEL VBAのユーザーフォームに引数を渡す方法について

    すいません、EXCEL VBAのユーザーフォームに引数を渡す方法についてご質問があります。 シート上にコマンドボタンを2つ用意する。 コマンドボタン1を押すと変数mは1 コマンドボタン2を押すと変数mは2 としてユーザーフォームを呼び出す。 Public m As Integer Private Sub CommandButton1_Click()  m = 1  Call フォーム呼び出し(m) End Sub Private Sub CommandButton2_Click()  m = 2  Call フォーム呼び出し(m) End Sub Sub フォーム呼び出し(m As Integer)  UserForm1.Show End Sub 次にユーザフォームにコマンドボタンを1個置き、 ボタンを押したとき、mが1であれば「ボタン1」 mが2であれば「ボタン2」 とメッセージボックスを出し、ユーザーフォームを閉じる。 Private Sub CommandButton1_Click()   If m = 1 Then    MsgBox "ボタン2"   ElseIf m = 2 Then    MsgBox "ボタン2"   End If  Unload UserForm1 End Sub プロシージャ間の引数渡しは色々なテキストに載っているのですが ユーザーフォームに引数を渡す方法はどうも見つからず、 Private Sub CommandButton1_Click(m) としても、コンパイルエラーとなってしまいます。 よろしくご教示をお願いいたします。

  • VBA スタック容量が足りない・・・

    こんばんわ! エクセルのVBAを使った管理システムを作ろうと思うのですが、色々考えて下記のような状態にしてみたのですが、ユーザーフォームをモードレスにするとスタック容量が足りなくなります。 Sub aaa_date() If Range("a1") = 1 Then bbb_date.Show ElseIf Range("a1") = 2 Then ccc_date.Show ElseIf Range("a1") = 3 Then ddd_date.Show End If Call aaa_date End Sub bbb_date(ユーザーフォーム)に↓ Private Sub CommandButton1_Click() Range("a1") = 2 Unload Me End Sub Private Sub CommandButton2_Click() Range("a1") = 3 Unload Me End Sub ccc_date(ユーザーフォーム)に↓ Private Sub CommandButton1_Click() Range("a1") = 1 Unload Me End Sub Private Sub CommandButton2_Click() Range("a1") = 3 Unload Me End Sub ddd_date(ユーザーフォーム)に↓ Private Sub CommandButton1_Click() Range("a1") = 1 Unload Me End Sub Private Sub CommandButton2_Click() Range("a1") = 2 Unload Me End Sub ※bbb_dateとccc_dateとddd_dateはそれぞれにあるボタンを押すとA7セルの値を変更するようにして、aaa_dateでどのフォームを表示するのかを選択しています。 ※実際にはもっと沢山ユーザーフォームがあります。 上記の状態では動作するのですが、エクセルの表に値を入力したいので、bbb_dateとccc_datとddd_datをvbModeless(モードレス状態)にすると、スタック容量が足りませんと出ます。 別のやり方でもよいですので、ユーザーフォームを切り替える良い方法があったらお願いします。

  • VBA プロシージャで値を渡す方法

    エクセルVBAのプロシージャで値を渡す方法はどうしたらいいのでしょうか。 たとえば、下記のようなプログラムを書いたとします。 --------------------------------------------- Private Sub test_main() Dim drink As String Dim alcohol As String Call test(cola, beer) End Sub Public Sub test_module(ByVal drink As String, ByVal alcohol As String) Cells(1, 1).Value = drink Cells(2, 2).Value = alcohol End Sub --------------------------------------------- このプログラムはもちろん不完全です。試してみたら動きませんでした。 やりたいことは、メインのプロシージャ(test_main)から、test_moduleを 呼び出し、同時に「cola」と「beer」の値を渡します。呼び出された先で、 エクセルのワークシートのセルに値を入力します。 重複しますが、それぞれの値「cola」と「beer」は変数「drink」と「alcohol」に代入されます。 この変数をcell(1,1)とcell(2,2)に入力します。 ワークシート上のcell(1,1)には「cola」、cell(2,2)には「beer」 と入力されます。 変数は数値ではなく、文字列です。 ポイントは、変数「drink」と「alcohol」をどのプロシージャに宣言するのか また、変数に値「cola」と「beer」をのどプロシージャでどういうふうに代入するのか。 そして代入した変数をどうやって呼び出したいプロシージャに渡すのかです。 このようなことをするには、上記プログラムをどう書き換えたらよいのでしょうか。

  • VBAについて

    VBA初心者です、実験でユーザーフォームにボタンを設けて押されたら次から次にセルに文字を表示していくようなプログラムを組む場合 以下のプログラムですと 2回目のボタンクリックで 実行時エラー’1004’: アプリケーション定義またはオブジェクト定義のエラーです。 と出ます。 どなたか添削をお願いでしょうか。 Private Sub CommandButton1_Click() X = Cells(1, 1) If X = "" Then n = 1 Cells(n, 1) = "最初のボタンが押されました" Else Cells(n, 1) = "次のボタンが押されました" End If n = n + 1 End Sub

専門家に質問してみよう