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

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

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

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

Q&A

解決済

1回答

3354閲覧

ExcelVBAのフォームで同じような処理をまとめたい

morutemu

総合スコア45

VBA

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

0グッド

0クリップ

投稿2018/06/06 00:43

編集2018/06/06 00:57

ExcelVBAにてフォームを作成し、いくつかテキストボックスがあるのですが、
その値が変わったときに関数が動くようなプログラムを作ったのですが、
プログラム全体を見てみると同じような処理がただ並んでいます。
これらをまとめたいのですが、どのようにしたらよいでしょうか?

VBA

1'回転数チェンジ関数_01 2Private Sub RotationSpeedTextBox01_Change() 3 IntermediateProc ("RotationSpeed") 4End Sub 5 6'回転数チェンジ関数_02 7Private Sub RotationSpeedTextBox02_Change() 8 IntermediateProc ("RotationSpeed") 9End Sub 10 11'周速チェンジ関数_01 12Private Sub PeripheralVelocityTextBox01_Change() 13 IntermediateProc ("PeripheralVelocity") 14End Sub 15 16'周速チェンジ関数_02 17Private Sub PeripheralVelocityTextBox02_Change() 18 IntermediateProc ("PeripheralVelocity") 19End Sub 20 21'R長さチェンジ関数_01 22Private Sub FilletLengthTextBox01_Change() 23 '中間処理 24 IntermediateProc ("FilletLength") 25End Sub 26 27'R長さチェンジ関数_02 28Private Sub FilletLengthTextBox02_Change() 29 '中間処理 30 IntermediateProc ("FilletLength") 31End Sub

*追加
その他処理

VBA

1'-- 関数 -- 2'初期化関数 3Public Sub Initialization() 4 WarningLabel = "" 5End Sub 6 7'計算関数 8Public Sub Calculation(strVal) 9 Select Case strVal 10 '回転数 11 Case "RotationSpeed" 12 'テキストボックスが空ではない場合の処理 13 If RotationSpeedTextBox01 <> "" And RotationSpeedTextBox02 <> "" Then 14 '周速・ワーク直径を変数に代入 15 PeripheralVelocity = RotationSpeedTextBox01 16 WorkDiameter = RotationSpeedTextBox02 17 18 '回転数(min-1)の計算 19 RotationSpeed = PeripheralVelocity / (WorkDiameter * PI) * 1000 20 21 '回転数(min-1)をテキストボックスに表示 22 RotationSpeedTextBox03 = RotationSpeed 23 End If 24 25 '周速 26 Case "PeripheralVelocity" 27 'テキストボックスが空ではない場合の処理 28 If PeripheralVelocityTextBox01 <> "" And PeripheralVelocityTextBox02 <> "" Then 29 '回転数・ワーク直径を変数に代入 30 PeripheralVelocity = PeripheralVelocityTextBox01 31 WorkDiameter = PeripheralVelocityTextBox02 32 33 '周速の計算 34 PeripheralVelocity = PeripheralVelocity * WorkDiameter * PI / 1000 35 36 '周速をテキストボックスに表示 37 PeripheralVelocityTextBox03 = PeripheralVelocity 38 End If 39 40 'R長さ 41 Case "FilletLength" 42 'テキストボックスが空ではない場合の処理 43 If FilletLengthTextBox01 <> "" And FilletLengthTextBox02 <> "" Then 44 'R(半径)・角度を変数に代入 45 R = FilletLengthTextBox01 46 Angle = FilletLengthTextBox02 47 48 '長さの計算 49 Length = ((R * 2 * PI) / 360) * Angle 50 51 '長さをテキストボックスに表示 52 FilletLengthTextBox03 = Length 53 End If 54 55 '表面粗さ 56 Case "SurfaceTexture" 57 'テキストボックスが空ではない場合の処理 58 If SurfaceTextureTextBox01 <> "" And SurfaceTextureTextBox02 <> "" Then 59 '送り・ノーズRを変数に代入 60 Feed = SurfaceTextureTextBox01 61 NoseR = SurfaceTextureTextBox02 62 63 '表面粗さ(Rz)の計算 64 SurfaceTextureRz = ((Feed ^ 2) / (8 * NoseR)) * 1000 65 66 '表面粗さ(Ra)の計算 67 SurfaceTextureRa = (((Feed ^ 2) / (8 * NoseR)) * 1000) / 4 68 69 '表面粗さ(Rz)をテキストボックスに表示 70 SurfaceTextureTextBox03 = SurfaceTextureRz 71 72 '表面粗さ(Ra)をテキストボックスに表示 73 SurfaceTextureTextBox04 = SurfaceTextureRa 74 75 End If 76 77 'ドリル 78 Case "Drill" 79 'テキストボックスが空ではない場合の処理 80 If DrillTextBox01 <> "" And DrillTextBox02 <> "" And DrillTextBox03 <> "" _ 81 And DrillTextBox04 <> "" Then 82 '切削長・穴数・回転数・送りを変数に代入 83 CuttingLength = DrillTextBox01 84 NumberOfHoles = DrillTextBox02 85 RotationSpeed = DrillTextBox03 86 Feed = DrillTextBox04 87 88 'サイクルタイムの計算 89 CycleTime = ((CuttingLength * NumberOfHoles) / (RotationSpeed * Feed)) * 60 90 91 'サイクルタイムをテキストボックスに表示 92 DrillTextBox05 = CycleTime 93 End If 94 95 'サイクルタイム 96 Case "CycleTime" 97 'テキストボックスが空ではない場合の処理 98 If CycleTimeTextBox01 <> "" And CycleTimeTextBox02 <> "" And CycleTimeTextBox03 <> "" Then 99 '切削長・回転数・送りを変数に代入 100 CuttingLength = CycleTimeTextBox01 101 RotationSpeed = CycleTimeTextBox02 102 Feed = CycleTimeTextBox03 103 104 'サイクルタイムの計算 105 CycleTime = (CuttingLength * 60) / (RotationSpeed * Feed) 106 107 'サイクルタイムをテキストボックスに表示 108 CycleTimeTextBox04 = CycleTime 109 End If 110 111 'エンドミル 112 Case "EndMill" 113 'テキストボックスが空ではない場合の処理 114 If EndMillTextBox01 <> "" And EndMillTextBox02 <> "" Then 115 '長さ・テーブル送りを変数に代入 116 Length = EndMillTextBox01 117 TableFeed = EndMillTextBox02 118 119 '時間の計算 120 TimeCal = Length * 60 / TableFeed 121 122 '時間をテキストボックスに表示 123 EndMillTextBox03 = TimeCal 124 End If 125 126 'テーブル送り 127 Case "TableFeed" 128 'テキストボックスが空ではない場合の処理 129 If TableFeedTextBox01 <> "" And TableFeedTextBox02 <> "" Then 130 '送り量(mm/rev)・回転数を変数に代入 131 FeedAmount = TableFeedTextBox01 132 RotationSpeed = TableFeedTextBox02 133 134 'テーブル送り(mm/min)の計算 135 TableFeed = FeedAmount * RotationSpeed 136 137 'テーブル送り(mm/min)をテキストボックスに表示 138 TableFeedTextBox03 = TableFeed 139 End If 140 141 '毎回転送り 142 Case "TransferEveryTime" 143 'テキストボックスが空ではない場合の処理 144 If EveryRotationAndMinuteTextBox01 <> "" And EveryRotationAndMinuteTextBox02 <> "" Then 145 '毎分送り(mm/min)・回転数を変数に代入 146 FeedEveryMinute = EveryRotationAndMinuteTextBox01 147 RotationSpeed = EveryRotationAndMinuteTextBox02 148 149 '毎回転送り(mm/rev)の計算 150 TransferEveryTime = FeedEveryMinute / RotationSpeed 151 152 '毎回転送り(mm/rev)をテキストボックスに表示 153 EveryRotationAndMinuteTextBox03 = TransferEveryTime 154 End If 155 156 '毎分送り 157 Case "FeedEveryMinute" 158 'テキストボックスが空ではない場合の処理 159 If EveryRotationAndMinuteTextBox04 <> "" And EveryRotationAndMinuteTextBox05 <> "" Then 160 '毎回転送り(mm/rev)・ノーズRを変数に代入 161 TransferEveryTime = EveryRotationAndMinuteTextBox04 162 NoseR = EveryRotationAndMinuteTextBox05 163 164 '毎分送り(mm/min)の計算 165 FeedEveryMinute = TransferEveryTime * NoseR 166 167 '毎分送り(mm/min)をテキストボックスに表示 168 EveryRotationAndMinuteTextBox06 = FeedEveryMinute 169 End If 170 171 'ねじ 172 Case "Screw" 173 'テキストボックスが空ではない場合の処理 174 If ScrewTextBox01 <> "" And ScrewTextBox02 <> "" Then 175 '回転数・ピッチを変数に代入 176 RotationSpeed = ScrewTextBox01 177 Pitch = ScrewTextBox02 178 179 'ねじ予備動作の計算 180 ScrewPreliminaryMotion = (RotationSpeed * Pitch) / 1800 181 182 'ネジ予備動作をテキストボックスに表示 183 ScrewTextBox03 = ScrewPreliminaryMotion 184 End If 185 186 '図面比率 187 Case "DrawingRatio" 188 'テキストボックスが空ではない場合の処理 189 If DrawingRatioTextBox01 <> "" And DrawingRatioTextBox02 <> "" _ 190 And DrawingRatioTextBox04 <> "" Then 191 '図面長さ①・計測長さ①・計測長さ②を変数に代入 192 DrawingLength01 = DrawingRatioTextBox01 193 MeasurementLength01 = DrawingRatioTextBox02 194 MeasurementLength02 = DrawingRatioTextBox04 195 196 '図面長さ②の計算 197 DrawingLength02 = (DrawingLength01 * MeasurementLength02) / MeasurementLength01 198 199 '図面長さ②をテキストボックスに表示 200 DrawingRatioTextBox03 = DrawingLength02 201 End If 202 203 '中央長さ 204 Case "CenterLength" 205 'テキストボックスが空ではない場合の処理 206 If CenterLengthTextBox01 <> "" And CenterLengthTextBox02 <> "" Then 207 '外側・内側を変数に代入 208 Outside = CenterLengthTextBox01 209 Inside = CenterLengthTextBox02 210 211 '中央の計算 212 Center = (Outside + Inside) / 2 213 214 '中央をテキストボックスに表示 215 CenterLengthTextBox03 = Center 216 End If 217 End Select 218End Sub 219 220'エラー振り分け関数 221Public Sub ErrorAllocation(ErrNum) 222 Select Case ErrNum 223 'オーバーフローした場合 224 Case OVERFLOW_ERROR 225 'WarningLabelにエラーを表示する 226 WarningLabel = OVERFLOW_ERROR_WARNING 227 228 '0で除算した場合 229 Case DIVISION_BY_ZERO_ERROR 230 'WarningLabelにエラーを表示する 231 WarningLabel = DIVISION_BY_ZERO_ERROR_WARNING 232 233 '型が一致しない場合 234 Case TYPE_ERROR 235 'WarningLabelにエラーを表示する 236 WarningLabel = TYPE_ERROR_WARNING 237 End Select 238End Sub 239 240'キャンセルコマンド関数 241Private Sub CancelCommandButton_Click() 242 Unload Me 243End Sub 244 245Private Sub MultiPage_Change() 246 '初期化 247 Initialization 248End Sub 249 250'中間処理 251Public Sub IntermediateProc(CalItem) 252 'エラーハンドリング 253 On Error GoTo ErrorHandler 254 255 '初期化 256 Initialization 257 258 '計算関数 259 Calculation (CalItem) 260 261 'エラーがない場合はここで終了 262 Exit Sub 263 264'エラーハンドラー 265ErrorHandler: 266 'エラーごとに振り分ける 267 ErrNum = Err.Number 268 ErrorAllocation (ErrNum) 269End Sub

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

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

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

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

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

m.ts10806

2018/06/06 00:50

IntermediateProc の内容もご提示ください。また、このままでは丸投げとなるので( https://teratail.com/help/avoid-asking )調べてみたこと、やってみたこと(そのソースコード)を具体的に追記してください。また参考先サイトがあればURLも質問に追記してください。既に見た先が回答についてしまうと無駄なやり取りが発生しますし、もしかしたら参考記事の理解が間違っているために解決に至れていないのかもしれません。https://teratail.com/help/question-tips#questionTips1-2
morutemu

2018/06/06 00:58

失礼いたしました。処理が長く、入れてませんでした。追加してみました。
m.ts10806

2018/06/06 01:15

振っているところよりも振り先の方が大事ですし、最初のコードだけだと何をしたいのか分かりません。全体提示が基本と思います。 確認したところ「似たような処理」ではありますが、全く同じではないのでまとめるのは結構難しいのではと思うのですが、いかがでしょうか?どの程度まとめるなど目標としているところがあれば追記してください。
morutemu

2018/06/06 01:28 編集

了解しました。もう追記できないようなのでこちらで失礼します。まとめたいところなのですが、IntermediateProc ("???")ここの処理です。。。 もしかすると、クラス化しないといけない感じでしょうか?
m.ts10806

2018/06/06 01:34

どうしてもクラス化をしたいようですけど、したいならしてみても良いかとは思うのですが、例えば前の質問のttyp03さんの回答は参考になりそうに思うのですが、いかがでしょうか。 https://teratail.com/questions/129409
guest

回答1

0

ベストアンサー

興味があったので、こちらのサイトを参考に実装してみました。

まず共通のイベント処理を実現するためのクラスを作ります。
名前はCommTextBoxとしてください。

VBA

1Private WithEvents tb As MSForms.TextBox 2Private item As String 3 4' 情報登録 5Public Sub NewClass(ByVal t As MSForms.TextBox, ByVal i As String) 6 Set tb = t 7 item = i 8End Sub 9 10' Changeイベント 11Private Sub tb_Change() 12 Call IntermediateProc(item) 13End Sub

フォーム側の処理。

VBA

1' 作成したクラスをテキストボックスの個数分インスタンス化 2Private ctb(0 To 5) As New CommTextBox 3 4' フォームの初期化イベント 5Private Sub UserForm_Initialize() 6 ' クラスに情報登録 テキストボックスの名前とそのテキストボックスで使用したいIntermediateProcの引数 7 ctb(0).NewClass RotationSpeedTextBox01, "RotationSpeed" 8 ctb(1).NewClass RotationSpeedTextBox02, "RotationSpeed" 9 ctb(2).NewClass PeripheralVelocityTextBox01, "PeripheralVelocity" 10 ctb(3).NewClass PeripheralVelocityTextBox02, "PeripheralVelocity" 11 ctb(4).NewClass FilletLengthTextBox01, "FilletLength" 12 ctb(5).NewClass FilletLengthTextBox02, "FilletLength" 13End Sub

変数名等は適当に書いているので適宜修正してください。

感想。
思ったよりはスッキリしました。
ただフォーム内で収まってた処理がクラス側に分散してしまうので、可読性は落ちますね。
そこをどう捕らえるか。
私なら現状維持で、無駄に一つにまとまっているCalculation関数なんかを分割したり、そういうところに力を注ぐかと思います。
そもそもCalculation関数の引数が文字列ってところから受け付けられません。
余談でした。

投稿2018/06/06 01:42

ttyp03

総合スコア16998

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

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

morutemu

2018/06/06 02:28

回答ありがとうございました。 一つ質問お願いします。 >そもそもCalculation関数の引数が文字列ってところから受け付けられません。 とありますが、通常引数は、数字などでしょうか??
ttyp03

2018/06/06 02:38

この場合の引数の意味って、処理を振り分ける識別のためだけの引数ですよね。 文字列自体に意味があるわけではない。 今の時代のPCならこの程度のことで速度(文字列の比較は遅くなる)とかリソース(数値を渡すよりより多くのメモリが必要)とか気にする必要はないのでしょうけど、コーディングとしてはあまりお勧めはできません。 なので、私なら引数用の列挙型を定義して使いますね。 こんな感じで。 Enum CALITEM  ROTATION_SPEED  PERIPHERAL_VELOCITY  FILLE_LENGTH End Enum ~ Call IntermediateProc(CALCITEM.FILLE_LENGTH)
morutemu

2018/06/06 02:58

Enumはじめて知りました。 VBAも見よう見まねで作っているので、 色々聞いてしましました。 ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問