[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]
『フォームでの在庫管理』(ayu)
料理の優先順位を決めたいときに、
食料庫のシートに
材料 個数
いちご 50
みかん 12
リンゴ 60
さとう 80
バナナ 12
レモン 30
レシピのシートに
料理名 材料 個数
イチゴジャム いちご 1
さとう 1 バナナジャム バナナ 1 さとう 1 レモン 1 リンゴジャム リンゴ 1 さとう 1 レモン 1 あるフォームに、優先順位1、優先順位2、優先順位3とコンボボックスで料理名を選択した後に、優先順位の1、優先順位2、優先順位3の作れる人数を表示させるにはどうしたらよいでしょうか??
< 使用 Excel:Excel2007、使用 OS:Windows7 >
多分この質問だけを見た人には、質問の意味が通じない気がします。 関連するフォームの項目の説明くらいはした方がよいと思います。
あと、関連の質問であれば、前回の質問もリンクを張ったほうが良いです。 [[20140923165632]] 『Excel VBAでの質問です。』(ayu)
(Mook) 2014/10/10(金) 14:59
かなり返信が遅れてしまい、すみませんでした。
前回Mookさんから教えていだたいた、マクロをフォームへ組み込む方法がよくわからず困っています。
優先順位1から優先順位3がフォーム(frm2)にあり、
優先順位のコンボボックスにイチゴジャムを選択したときに、
その横のにあるテキストボックスに数字3など表示できるような形にしたいのですが、よくわからないので困っています。
Private Sub UserForm_Initialize() 'フォームを読み込んだとき
Dim i As Integer
frm2.ComboBox1 = Clear '優先1
frm2.ComboBox2 = Clear '優先2
frm2.ComboBox3 = Clear '優先3
i = 1
Do Until Worksheets("Sheet1").Cells(i, 3).Value = ""
i = i + 1
frm2.ComboBox1.AddItem Worksheets("Sheet1").Cells(i, 3).Value Loop
i = 1
Do Until Worksheets("Sheet1").Cells(i, 3).Value = ""
i = i + 1
frm2.ComboBox2.AddItem Worksheets("Sheet1").Cells(i, 3).Value Loop
i = 1
Do Until Worksheets("Sheet1").Cells(i, 3).Value = ""
i = i + 1
frm2.ComboBox3.AddItem Worksheets("Sheet1").Cells(i, 3).Value Loop
End Sub
Private Sub ComboBox1_Change()
If frm2.Conmbobox1 = Null Then
MsgBox "優先順位1が入力されていません"
Else
"""ここに入るものがよくわかりません"""
End Sub
(ayu) 2014/10/27(月) 14:18
> 関連するフォームの項目の説明くらいはした方がよいと思います。 の説明がありませんが、下記のようなユーザフォームを想定すれば、 -------------------------------------------- 優先順位1 [ComboBox1] [TextBox1] 優先順位2 [ComboBox2] [TextBox2] 優先順位3 [ComboBox3] [TextBox3] --------------------------------------------
こんな感じでしょうか。
Private Sub UserForm_Initialize() ComboBox1.Clear ComboBox2.Clear ComboBox3.Clear
With Worksheets("Sheet1") Dim t As Variant t = .Range(.Cells(1, "C"), .Cells(Rows.Count, "C").End(xlUp)) Dim i For i = 1 To UBound(t, 1) If t(i, 1) = "" Then Exit For ComboBox1.AddItem t(i, 1) ComboBox2.AddItem t(i, 1) ComboBox3.AddItem t(i, 1) Next End With End Sub
Sub 計算更新() Dim i As Long Dim cmb As Control Dim txt As Control
材料登録 食糧庫 For i = 1 To 3 Set cmb = Me.Controls("ComboBox" & i) Set txt = Me.Controls("TextBox" & i)
If cmb.Text = "" Then txt.Text = "" Else txt.Text = 調理(食糧庫, cmb.Text) End If Next End Sub
Private Sub ComboBox1_Change() 計算更新 End Sub
Private Sub ComboBox2_Change() 計算更新 End Sub
Private Sub ComboBox3_Change() 計算更新 End Sub
前回の質問のレシピシートと今回のコンボボックスに出すシートは別名なので、 (列やデータ構成も異なるので)、そこは別シートの想定です。 (Mook) 2014/10/29(水) 11:18
下記の
材料登録 食料庫の部分で
sub または Functionが定義されていません。エラーが出ましたが、
これは材料登録という別のモジュールを作成する必要があるということでしょうか。
前回教えていただいた、
Sub 食料庫の在庫(食糧庫 As Scripting.Dictionary)
を呼び出すのでしょうか?
材料登録 食糧庫
For i = 1 To 3 Set cmb = Me.Controls("ComboBox" & i) Set txt = Me.Controls("TextBox" & i)
If cmb.Text = "" Then txt.Text = "" Else txt.Text = 調理(食糧庫, cmb.Text) End If Next End Sub
(ayu) 2014/10/30(木) 10:47
前回のコードが標準モジュールにある前提です。 (Mook) 2014/10/30(木) 10:54
前回のコードは標準モジュールに存在しますが、
sub または Functionが定義されていません。
とエラーが出てしまいます。
材料登録 食糧庫の部分は前のモジュールを呼び出しているのでしょうか??
(ayu) 2014/10/30(木) 15:57
計算更新 の先頭で Dim 食糧庫 As New Scripting.Dictionary を追加する必要はありますね。
そのあたりは、マクロの中身を理解してご自身で修正できるようになっておけるとよいですね。
(Mook) 2014/10/30(木) 17:12
下記なんですが、
Sub 計算更新()
Dim 調理 As Scripting.Dictionary Dim 食糧庫 As Scripting.Dictionary
Dim i As Long Dim cmb As Con trol Dim txt As Control
食料庫の在庫 食糧庫 For i = 1 To 3 Set cmb = Me.Controls("ComboBox" & i) Set txt = Me.Controls("TextBox" & i)
If cmb.Text = "" Then txt.Text = "" Else txt.Text = 調理(食糧庫, cmb.Text) End If Next End Sub
下記なんですが、
引数の数が一致していません。または不正なプロパティを指定しています。
とエラーがでてしまいました。
計算更新の部分に誤りがあるのでしょうか??
初歩的な質問で申し訳ないのですが、教えていただけないでしょうか。
Private Sub ComboBox1_Change()
計算更新 食糧庫 End Sub
(ayu) 2014/10/31(金) 12:27
すみません辺りもよくわからないので教えてください。
Dim cmb As Control
Dim txt As Control
(ayu) 2014/11/05(水) 11:17
計算更新 には引数を渡していないと思いますので、処理を呼び出すところ、 呼び出されるところの形が一致しているかを確認してください。
Sub 計算更新() が引数を持つ場合は Sub 計算更新( 何かの引数, ... ) となっているはずですが、そうなっていないということは、 計算更新 は引数を持たない ということです。
Set cmb = Me.Controls("ComboBox" & i) Set txt = Me.Controls("TextBox" & i)
は For のループの中の処理になっていますので、 i が 1 のときは、 cmb は ConboBox1、txt は TextBox1 i が 2 のときは、 cmb は ConboBox2、txt は TextBox2 i が 3 のときは、 cmb は ConboBox3、txt は TextBox3 として動作します。
マクロを覚えるのであれば、まずステップ実行の仕方を覚えて、ワンステップずつ 実行して、変数の中身やシートの結果を確認しながら実行してみると良いと思います。
(Mook) 2014/11/05(水) 12:45
Sub 計算更新(材料登録 As Scripting.Dictionary)
Dim 食糧庫 As Scripting.Dictionary Dim i As Long Dim cmb As Control Dim txt As Control
材料登録 食糧庫 For i = 1 To 3 Set cmb = Me.Controls("ComboBox" & i) Set txt = Me.Controls("TextBox" & i)
If cmb.Text = "" Then txt.Text = "" Else txt.Text = 調理(食糧庫, cmb.Text) End If Next End Sub ’−−−−−−−−−−−−−−−−−−−−
Private Sub ComboBox1_Change() Dim 計算更新 As New Scripting.Dictionary
計算更新 材料登録
End Sub
(ayu) 2014/11/07(金) 13:08
やはり最低限の VBA の基礎知識は必要です。 (変数とは何か、プロシージャとは何か、関数とは何か、引数の受渡し、 基本制御構文(IF、WHILE、SELECT CASE 程度だけでも)など) 後はマクロの記録とステップ実行ですね。
この質問で提示されているコードは、ちょっとめちゃくちゃになっています。
ComboBox1_Change の Dim 計算更新 As New Scripting.Dictionary は削除(計算更新 はプロシージャです。変数ではありません)。 Sub 計算更新 の Dim 調理 As Scripting.Dictionary は削除(調理は関数名です。変数ではありません)。
Sub 計算更新(材料登録 As Scripting.Dictionary) は Sub 計算更新() に戻して、標準モジュールに前の質問の Sub 材料登録(...) があることを確認してください。
ComboBox1_Change の呼び出しは 計算更新 だけにしてください。
ステップ実行はしてみたでしょうか。 エラーの場所で、なぜエラーなのか、エラーメッセージも出ていると思うので、 >今でもエラーはかかるんですが、 だけでなく、エラーメッセージも提示してください。 わからなくても一応は検索してみてくださいね。
(Mook) 2014/11/07(金) 16:26
があることを確認してください。 とありますが、材料登録はないです。ということは作成しなければいけないということでしょうか。
確かに基礎がなってません。
とても簡単なコードなら理解できるのですが、架空に値をおいとくようなものは作成したことがなく
チンプンカンプンです。本当にスキルが全然できてない上で質問してしまっているのでご迷惑かと思います。申し訳ないです。
前回のコードでよくわからないところがありまして、その辺りを教えていただきたいです。
自分でコードの中身をコメント入れてみたのですが、
理解はあっているでしょうか?
レシピ(料理名)(.Cells(行, "B").Value) = .Cells(行, "C").Value
この部分が理解できないので解説してもらえないでしょうか。
=の前に値を入れるところはわかるのですが。
.Cells(行, "C").Value
の前に入るものはなんでしょうか?
Sub レシピ読込(レシピ As Scripting.Dictionary) '//--------------------------------------------------------- '// 「レシピ」シートに A列:料理名、B列:材料名、C列:個数 '// A列:料理名は材料内の先頭行にのみ記載 '//--------------------------------------------------------- Dim 行 As Long Dim 料理名 As String With Worksheets("レシピ") 'レシピを開く For 行 = 1 To .Cells(Rows.Count, "B").End(xlUp).Row 'B列の材料名がどこまであるか見に行く If .Cells(行, "A").Value <> "" Then 'もしA列(料理名)に値が入っていたら 料理名 = .Cells(行, "A").Value '料理名を取得 If レシピ.Exists(料理名) = False Then 'もしレシピに料理名を取得できていなかったら Set レシピ(料理名) = New Scripting.Dictionary 'レシピに料理名をセットする。 End If End If レシピ(料理名)(.Cells(行, "B").Value) = .Cells(行, "C").Value Next End With End S (ayu) 2014/11/13(木) 15:27
はーい。 理解しようとするための質問でしたら、喜んで答えますよ。
> レシピ(料理名)(.Cells(行, "B").Value) = .Cells(行, "C").Value
そうですね、これはちょっと(だいぶ?)難解ですね。
配列の概念がわかっていれば、連想配列(VBA では Dictionary)はその拡張なのですけれど、 「レシピ」 が 連想配列名です。 レシピ(料理名) 実際は レシピ("イチゴジャム")、レシピ("リンゴジャム") がさらに連想配列になっています。
ですので、各行のセルの値によって、上記の式は内容としては、
レシピ("イチゴジャム")("いちご") = 10 レシピ("イチゴジャム")("砂糖") = 5 レシピ("イチゴジャム")("レモン") = 1
レシピ("リンゴジャム")("りんご") = 3 レシピ("リンゴジャム")("砂糖") = 4 レシピ("リンゴジャム")("レモン") = 1 のように処理されます。 最初の行は、イチゴジャムを作るのにいちごは 10 個必要です、ということの登録です。
これは Dim リンゴジャム As Scripting.Dictionary Dim イチゴジャム As Scripting.Dictionary とすれば、下記のようにもかけますが、 イチゴジャム("いちご") = 10 イチゴジャム("砂糖") = 5 イチゴジャム("レモン") = 1
リンゴジャム("りんご") = 3 リンゴジャム("砂糖") = 4 リンゴジャム("レモン") = 1 これだと、作るメニューが固定になってしまって、メニューが変わるとコードも変更 しないといけないですよね。 ですので、メニューも自由に変えられるようにしたのが、そこも配列にしています。
詳しくはこの辺りを見てください。 http://www.eurus.dti.ne.jp/~yoneyama/Excel/vba/vba_dictionary.html
まずはここまで。
(Mook) 2014/11/13(木) 19:03
上の解説ですと
Sub 食料庫の在庫(食糧庫 As Scripting.Dictionary)と
Sub レシピ読込(レシピ As Scripting.Dictionary)はそれぞれ
レシピの内容を架空に登録しておくというような感じでしょうか?
イチゴジャムはこういう材料と数でできます。というのを一つ一つ登録しておくような感じでしょうか?
食糧庫の材料も食糧庫のシートに材料がどれだけあるか架空に登録しておくのでしょうか?
次にまた調理のところのFunctionがよくわからないところがあります。
まず最大数=-1とありますが、なぜまず最大数は-1と登録するのでしょうか?
はじめのイチゴが-1で次のさとうから値が入るような気がするのですが、、、
その辺りがよく理解できていなく、解釈もまちがっているかもしれないので、
教えていただきたいです。
For Each 材料 In レシピ.Keys '実際ある材料の数にレシピの数が当てはまる数までループする。
と解釈していますが、
あっていますでしょうか?
'//---------------------------------------------------------
Function 調理(食糧庫 As Scripting.Dictionary, レシピ As Scripting.Dictionary) As Long '//--------------------------------------------------------- Dim 最大数 As Double 最大数 = -1 Dim 材料 For Each 材料 In レシピ.Keys '実際ある材料の数にレシピの数が当てはまる数までループする。 If 最大数 = -1 Then '最大数は-1とする。 最大数 = 食糧庫(材料) / レシピ(材料) '-1=食糧庫の材料の数÷レシピの材料の数 Else If 食糧庫(材料) = 0 Then 'もし食糧庫の材料が0だった場合 調理 = 0 '調理はしない Exit Function Else '↑ではなかった場合 If レシピ.Exists(材料) = False Then 'もしレシピに材料のを取得できていなかったら 調理 = 0 '調理はしない Exit Function End If 最大数 = Application.Min(最大数, (食糧庫(材料) / レシピ(材料))) '最大数=食糧庫の材料の数÷レシピの材料の数 End If End If Next 調理 = CLng(Application.Floor(最大数, 1))
For Each 材料 In レシピ.Keys 食糧庫(材料) = 食糧庫(材料) - レシピ(材料) * 調理 '食料庫の材料名=食糧庫の材料の数-レシピの材料の数 Next End Function
(ayu) 2014/11/14(金) 10:06
紛らわしかったかもしれませんが、-1 は特別な意味を持つ状態(まだ最大値が設定されていない)を示すために使っています。
食料庫の在庫 は調理に使用できる食材を登録する処理です。 「今はりんごが10個、イチゴが20個砂糖が5kg あるよ」とか、そういう目的です。
レシピ読込 はそれぞれの料理に、どれだけ材料が必要かを登録するための処理です。 (Mook) 2014/11/14(金) 18:58
[ 一覧(最新更新順) ]
YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki.
Modified by kazu.