[[20141009155423]] 『フォームでの在庫管理』(ayu) ページの最後に飛ぶ

[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]

 

『フォームでの在庫管理』(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


毎度ありがとうございます。
cmdとtxtで宣言している部分ですが、Controlはすべてのテキストボックスに適用されるとインターネットで検索すると出てきたのですが、cmdとtxtの変数はTextbox1〜3のものに結びつけをしなくてもいいのでしょうか?

すみません辺りもよくわからないので教えてください。

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


アドバイスありがとうございます。
前教えて頂いたVBと今回作っていただいたものの引数の受け渡し方がいまいちよくわからないのですが、、
計算更新の引数の受け渡し方は下記のようで合っていますでしょうか??
今でもエラーはかかるんですが、

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


回答有難うございます。
>Sub 材料登録(...)
 があることを確認してください。
とありますが、材料登録はないです。ということは作成しなければいけないということでしょうか。

確かに基礎がなってません。
とても簡単なコードなら理解できるのですが、架空に値をおいとくようなものは作成したことがなく
チンプンカンプンです。本当にスキルが全然できてない上で質問してしまっているのでご迷惑かと思います。申し訳ないです。

前回のコードでよくわからないところがありまして、その辺りを教えていただきたいです。
自分でコードの中身をコメント入れてみたのですが、

理解はあっているでしょうか?

 レシピ(料理名)(.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.