[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]
『ユーザーフォームリストボックスの値をセル範囲へ入力する』(ひなの)
先日貴重な資料をありがとうございます。 資料を勉強している途中ですが、またわからないことが出てきました。 懲りずに教えていただけましたらうれしいです。
▼リストボックスの値をセル範囲へ入力する http://www.eurus.dti.ne.jp/~yoneyama/Excel/vba/vba_userform03.html#nyuryoku
で練習していましたが。不明な個所があります。
Q1. For i = 0 To 2 ここは列数に使ってるのはわかりました。この数はどこに連動していますか? 数を変更したのちエラーになったので、 どこかと数が合わないだろうと思って探しているのですが・・・・・
Q2. .Cells(lRow + 1, i + 2).Value = ListBox1.List(ListNo, i) ここもそうですが。「i+2」もよくわからず、数を追加したら減らしたリすると微妙にずれたり A1を1を換算すると都合が悪いのでしょうか?
Q3.書き出す際に商品名を書き出さずにするのも可能ですか?
Q4.[cs]で注文するときは[C]列へ、[pc]の注文の時は[E]列へ内容を転記したいときはどうすれば
Q5.オプションボタンにどちらのみ必ずチェックを入れる方法が知りたいです。
Q6.ユーザーフォーム上にあいまい検索をつけたいです
Q7.テキストボックスで名前あいまい検索応用できますね。
Q8.フォームメニューからフォーム商品検索を開く方法
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− (ひなのメモ) ▼相談結果
◆エクセル使用 商品シート [A] [B] [C] [D] [E] [F] [G] [H] [I] [2] NO 商品名前 容量 g cs容量 pc 価格 [3] A01 さとう 400 g × 30 pc \175
発注書シート [A] [B] [C] [D] [E] [F] [G] [H] [12] NO 品名 数量 単位 単価 金額 備考 KG [13] A07 みかん 5 24 30 13 [14] A08 リンゴ 10 50 13
◆フォーム コンボックス あいまい検索(A〜Zの値) リストBOXはエクセルの内容が テキストボックスは 数字入力 オプションボタンが2つ 入力ボタン 終了ボタン
◆コード Private Sub 終了_Click() Unload Me End Sub
'あいまい検索 Private Sub ComboBox1_Change() Dim r As Range With ListBox1 .RowSource = "" .ColumnHeads = False End With If ComboBox1.ListIndex < 0 Then Exit Sub With Sheets("商品") Set r = .Range("B2", .Range("B" & Rows.Count).End(xlUp)).Resize(, 10) End With With Sheets("作業") .UsedRange.ClearContents .Range("A1").Value = Sheets("商品").Range("B2").Value 'タイトル .Range("A2").Value = ComboBox1.Value r.AdvancedFilter Action:=xlFilterCopy, CriteriaRange:=.Range("A1:A2"), CopyToRange:=.Range("C1"), Unique:=False If Not IsEmpty(.Range("C2")) Then With .Range("C1").CurrentRegion ListBox1.RowSource = .Offset(1).Resize(.Rows.Count - 1).Address(External:=True) ListBox1.ColumnHeads = True End With End If End With End Sub
’エクセルに書き出す Private Sub 入力_Click() Dim lRow As Long, i As Long Dim ListNo As Long
ListNo = ListBox1.ListIndex
If ListNo < 0 Then MsgBox "いずれかの行を選択してください" Exit Sub End If
With Worksheets("発注書") lRow = .Range("A" & Rows.Count).End(xlUp).Offset(1).Row
With .Rows(lRow)
'listBoxは2次元配列なので、1列目は「0」から数える、エクセルは1列目[A]は[1]から数える .Columns("A").Value = ListBox1.List(ListNo, 0) .Columns("B").Value = ListBox1.List(ListNo, 1) .Columns("E").Value = ListBox1.List(ListNo, 9) .Columns("H").Value = ListBox1.List(ListNo, 8)
'箱のチェックボックスにチェックがある時 If op箱.Value = True Then .Columns("C").Value = TextBox1.Value .Columns("D").Value = ListBox1.List(ListNo, 5)
Else .Columns("D").Value = TextBox1.Value
End If
End With End With
End Sub
’フォーム上常に値を表示させるのと、列のサイズ指定 Private Sub UserForm_Initialize() Dim lRow As Long With Worksheets("商品") lRow = .Range("B" & Rows.Count).End(xlUp).Row End With
With ListBox1 .ColumnCount = 10 .ColumnWidths = "30;200;40;20;20;30;30;0;50;50" .RowSource = "商品!B3:k" & lRow 'A2の一行前の見出しを固定する .ColumnHeads = True End With TextBox1.Value = ""
CheckBox1 = False CheckBox2 = False
With ComboBox1 .List = Array("A", "B", "C", "D", "E", "F", "Z") .MatchRequired = True End With ComboBox1.Value = "A"
End Sub
< 使用 Excel:Excel2010、使用 OS:Windows7 >
とりあえず、Cellsの基本だけ書きます。これだけで全て理解できるように思います。
Cells(行, 列) のように指定します。行、列共に、最小値は1です。Cells(1, 1)は、Range("A1")と同じセルになります。
i のループは 0 からになっていますね。これはListBoxの要素番号が 0 から始まっているためです。
ListBoxは0から。Cellsは1から。 だから i = 0 のときは +1 して、Cellsの1番目にセットしているわけです。
でもって、商品名を付けるかどうかは、貴方が自由にコーディングすればよろしい。減らすだけなら簡単かと。
(???) 2016/06/21(火) 12:59
>作者無視は失礼というものですよ そうなんですか?質問できること自体知りませんでした。 しかし、よねさんは一人で回答されてるんですよね大変じゃないですか?
それに、いままで、 (γ) さまと(β)さまのご協力でここまできたので、 是非、引き続きをと思ったんですが ↓↓(%;´п`?V)
もう少し自分でやってみます。 (ひなの) 2016/06/21(火) 19:21
>>よねさんは一人で回答されてるんですよね大変じゃないですか?
よねさん、ほんとうにこまめに対応されていますね。頭が下がります。 なので、あちらの掲示板に質問されれば、回答がもらえると思いますが、 あちらに質問する前の予備知識として。
>>Q1. For i = 0 To 2 >> ここは列数に使ってるのはわかりました。この数はどこに連動していますか?
ここで使っているサンプルは、3列のリストでしたね。 で、リストは、2次元の配列なんですが、要素番号が 0 から始まります。(LBound が 0) なので、リスト内(配列内)に存在する列は 0 列目、1列目、2列目 です。 これ以外の列番号を指定して参照しようとすると、存在しないので、エラーになります。
>> Q2. .Cells(lRow + 1, i + 2).Value = ListBox1.List(ListNo, i)
リストの列だけではなく行も 0 から始まります。リストボックスの一番上の行は 0 行目ということになります。 で、リストボックスで選ばれた行番号は ListIndex に格納されています。 一番上の行なら 0、に行目なら 1 です。
なので左辺、.Cells(lRow + 1, i + 2).Value この lRow がシート上の B列の最終行という設定ですから lRow+1 は B列の最終データの次の行ということになりますね。 列は i + 2 になっています。i は リストボックスの列番号 0 〜 2 ですね。 ということは i + 2 は 2 〜 4 、つまり列記号でいうと B 〜 D ということになります。
書きこみ元の右辺は ListBox1.List(ListNo, i) 。i は 選ばれた行の0列目〜2列目。
したがって、リストボックスで選ばれたデータを B列最終データの行の次の行の B列、C列、D列に書きこんでいる というコードになっていますね。
>> Q3.書き出す際に商品名を書き出さずにするのも可能ですか?
はい、可能です。リストの中の 1列目からの転記をやめればよろしいんです。 ただ、参考にされたコード、すべてを書きこむということで、コードをコンパクトにするために順繰りのループ処理になっています。 0列目と2列目だけを 特定の列に書きこみたいなら、
With Worksheets("Sheet2") lRow = .Range("B" & Rows.Count).End(xlUp).Offset(1).Row With .Rows(lRow) .Columns("B").Value = ListBox1.List(ListNo, 0) .Columns("C").Value = ListBox1.List(ListNo, 2) End With End With
ループさせず、1つずつ、必要な項目を必要なセルに転記することになります。
(β) 2016/06/21(火) 20:00
(β) 様 回答に気づくの遅くなってすみません。 引き続き教えていただいてありがとうございます。
>2次元の配列の要素番号が 0 から始まります。(LBound が 0) >なので、リスト内(配列内)に存在する列は 0 列目、1列目、2列目 です。 なのるど「0」からなんですね。エクセルの1行ずつずれるので「+」したり「−」たりで 合わせてあげないといけないのですね。
丁寧な解説で大変勉強になりました。
>> Q3.書き出す際に商品名を書き出さずにするのも可能ですか? さっそく、ループさせず、1つずつ、必要な項目を必要なセルに転記する方法に変更しました。
おかげさまで、大分形にできました。 ただ、一個困ったことが・・・・・ 何かいい対策あれば、知恵を貸していただけると嬉しいです。
私が作っているのは発注書で、エクセルが苦手な方でも、簡単な作業ができるように したいと思ってユーザーフォーをチャレンジしたんです。
必要なデーターをフォームに取り組んで、必要なデーターのみエクセルに書き出す。 予定でしたが、ここで、少し困ったことになりまして。 注文の単位が全部1csごとなら問題ないですが、単品で注文するときもあるので、それ用のコードも作らないといけないかなと。 いまいち、うまくはいかないですが。IF関数でチャレンジして、挫折中です。
Q4.[cs]で注文するときは[C]列へ、[pc]の注文の時は[E]列へ内容を転記したいときはどうすれば。。
IF関数しか思い当たらないですが、どのあたりに入れればいいのやら ( ┰_┰)
ユーザーフォーム リストBOXはエクセルの内容が テキストボックスは 数字入力 コンボックス 「cs」か「pc」を選択 入力ボタン 終了ボタン
シート1 [A] [B] [C] [D] [E] [F] [G] [H] [I] [J] [12] NO 品名 数量 単位 単価 金額 備考 KG [13] A07 みかん 5 cs 30 pc 30 13 [14] A08 リンゴ 10 pc 50 13
Private Sub CommandButton1_Click() Dim lRow As Long, i As Long Dim ListNo As Long ListNo = ListBox1.ListIndex If ListNo < 0 Then MsgBox "いずれかの行を選択してください" Exit Sub End If With Worksheets("Sheet1") lRow = .Range("A" & Rows.Count).End(xlUp).Offset(1).Row End With
With .Rows(lRow) 'listBoxは2次元配列なので、1列目は「0」から数える、エクセルは1列目[A]は[1]から数える 'A列の値=listboxの0列目の値(NO) .Columns("A").Value = ListBox1.List(ListNo, 0) 'B列の値=listboxの1列目の値(商品名) .Columns("B").Value = ListBox1.List(ListNo, 1) 'C列の値=テキストボックスの値(CSの数) .Columns("C").Value = TextBox1.Value 'D列の値=コンボックスの値(csかpcの単位) .Columns("D").Value = ComboBox1.Value 'E列の値=listboxの6列目の値(1csの単位) .Columns("E").Value = ListBox1.List(ListNo, 5) 'F列の値=listboxの7列目の値(pc) .Columns("F").Value = ListBox1.List(ListNo, 6) 'G列の値=listboxの9列目の値(単価) .Columns("G").Value = ListBox1.List(ListNo, 8) 'J列の値=listboxの10列目の値(Kg) .Columns("J").Value = ListBox1.List(ListNo, 9) End With
End Sub ===================================================
Private Sub UserForm_Initialize() Dim lRow As Long With Worksheets("商品") lRow = .Range("B" & Rows.Count).End(xlUp).Row End With
With ListBox1 'リストBOXの中の列数と↓ここの列数が異なると実行後エラーになる .ColumnCount = 9 .ColumnWidths = "30;200;30;20;20;20;20;0;40;40" 'スクロールするのはA2から .RowSource = "商品!B3:k" & lRow 'A2の一行前の見出しを固定する .ColumnHeads = True End With TextBox1.Value = ""
With ComboBox1 .AddItem "cs" .AddItem "pc" End With ComboBox1.Value = "" End Sub
(ひなの) 2016/06/22(水) 23:00
アップされたCommandButton1_Clickの End With の場所がちょっとおかしいですね。 このままでは コンパイルエラ−になります。
それはさておき。
cs と pc の場合、それぞれ、どうセットするのか、説明文とサンプルとコード、それぞれで差異があって悩みますが、 以下のようなことでしょうか。
If ComboBox1.Value = "cs" Then 'C列の値=テキストボックスの値(CSの数) .Columns("C").Value = TextBox1.Value 'D列の値=コンボックスの値(csかpcの単位) .Columns("D").Value = ComboBox1.Value Else .Columns("E").Value = TextBox1.Value .Columns("F").Value = ComboBox1.Value End If
あと、これは好き好きですけど、cs と pc 、二者択一なら、βなら コンボボックスを使わず オプションボタンを2つ配置して、そのいずれかを(頻度の多いものを)デザインで、その値を True にして それを選択してもらう構えにしますね。
(β) 2016/06/23(木) 09:41
回答ありがとうございます。
≫アップされたCommandButton1_Clickの End With の場所がちょっとおかしいですね。 さっそくエラーになりました。消したら追加したりしたら、わけわからなくなりました。 指摘ありがとうございます。
≫オプションボタンを2つ配置して、そのいずれかを(頻度の多いものを)デザインで、 ≫その値を True にしてそれを選択してもらう構えにしますね。
ホントですね。たしかにこっちのほうがわかり易いですね。 ただ、勘違いしてCheckBox1 作ってしまったので、このまま使用させてください( ┰_┰)
あと、コードをコンパクトにするために、レイアウトを変更しました。
Q5.どちらのみ必ずチェックを入れる方法が知りたいです。 さもないと、とんでもないことに・・・・・
[A] [B] [C] [D] [E] [F] [G] [H] [12] NO 品名 数量 単位 単価 金額 備考 KG [13] A07 みかん 5 24 30 13 [14] A08 リンゴ 10 50 13
Private Sub CommandButton1_Click() Dim lRow As Long, i As Long Dim ListNo As Long
ListNo = ListBox1.ListIndex
If ListNo < 0 Then MsgBox "いずれかの行を選択してください" Exit Sub End If
With Worksheets("Sheet1") lRow = .Range("A" & Rows.Count).End(xlUp).Offset(1).Row
With .Rows(lRow)
'listBoxは2次元配列なので、1列目は「0」から数える、エクセルは1列目[A]は[1]から数える 'A列の値=listboxの0列目の値(NO) .Columns("A").Value = ListBox1.List(ListNo, 0)
'B列の値=listboxの1列目の値(商品名) .Columns("B").Value = ListBox1.List(ListNo, 1)
'E列の値=listboxの7列目の値(単価) .Columns("E").Value = ListBox1.List(ListNo, 7)
'H列の値=listboxの8列目の値(重量?s) .Columns("H").Value = ListBox1.List(ListNo, 8)
'箱のチェックボックスにチェックがある時 If CheckBox1.Value = True Then
'D列の値=テキストボックスの値(CSの数) .Columns("C").Value = TextBox1.Value
'D列の値=listboxの5列目の値(1csの単位) .Columns("D").Value = ListBox1.List(ListNo, 5)
'箱のチェックボックスにチェックがないとき Else
'D列の値=テキストボックスの値(CSの数) .Columns("D").Value = TextBox1.Value
End If
End With End With
End Sub (ひなの ) 2016/06/23(木) 19:54
>>Q5.どちらのみ必ずチェックを入れる方法が知りたいです。 >>さもないと、とんでもないことに・・・・・
OptionButtonの場合は、例えば OptionButton1とOptionButton2 があったとして 操作者が、どちらも選択しなかったら、どちらも選ばれていないことになりますね。 こういう場合は、両方とも選択がない場合にエラーメッセージをだす なんてことをしなければいけませんね。 なので、最初から、どちらかが選択された状態にしておく。
方法は、デザインで、どちらかのプロパティの Value を True にしておくか、Initializeルーティンで どちらかの Value を True にしておきます。
一方、CheckBox なら、2つから1つを選ぶ ということではなく、選ぶか選ばないかということですね。 たとえば 箱 という CheckBox が選ばれていなければ バラ ということですから、コード実行として とんでもないことにはなりませんね。
ただ、ほとんどが 箱 の場合は最初から チェックをつけておきたいですね。 方法は OptionButton と同じ。 プロパティで Value を True にしておくか、Initialize で Value を Trueにするかです。
なお、たとえば TextBox1、デザインでプロパティに特別に何か値を入れておかない限り ユーザーフォームが表示された時点では値がありませんので TextBox1.Value = "" は不要ですね。
(β) 2016/06/23(木) 21:30
ありがとうございます。言われたとおりに OptionButtonに使いましたら。問題ありませんでした。 OptionButton1 プロパティの Value を True (箱)のほうを
'箱のチェックボックスにチェックがある時
If OptionButton1.Value = True Then
'D列の値=テキストボックスの値(CSの数) .Columns("C").Value = TextBox1.Value
'D列の値=listboxの5列目の値(1csの単位) .Columns("D").Value = ListBox1.List(ListNo, 5)
'箱のチェックボックス1にチェックがなくて単品(pc)にチェックがあるとき Else
'D列の値=テキストボックスの値(CSの数) .Columns("D").Value = TextBox1.Value
End If
Q6.ユーザーフォーム上にあいまい検索をつけたいです。 商品が多いので、「A01」を「A*」であいまい検索をして、「A」の部類の商品のみフォーム上に表示させたいと思ったんです。
が、何かが違います( ┰_┰) ネットで見つけて使ったんですが、これはどういったものでしょうか?エクセルのフィルター機能を利用して あいまい検索するものと思ったのですが。
エクセルで絞った内容がフォームに表示されるイメージだったんですが。違ったのかしら?
Private Sub ComboBox1_Change() Worksheets("商品").AutoFilter Field:=2, Criteria1:=TextBox1.Value & "*" End Sub
Private Sub UserForm_Initialize() With ComboBox1 .AddItem "A" .AddItem "B" .AddItem "C" .AddItem "D" .AddItem "E" .AddItem "F" .AddItem "Z" End With ComboBox1.Value = "A"
商品シート [A] [B] [C] [D] [E] [F] [G] [H] [I] [2] NO 商品名前 容量 価格 [3] A01 さとう 400 g × 30 pc \175
(ひなの ) 2016/06/24(金) 14:43
3つのポイントで。
1.オートフィルターの設定
何かしらタイトル行とリストがあるシートでオートフィルターを設定。 これをマクロ記録してください。 できあがるコードは、領域.AutoFilter ・・・ といったものですね。 この領域 は、より正確に表すと シート.領域 ですから シート.領域.AutoFiler になります。 アップされたような シート.AutoFilter というコード記述は NG ですね。
2.オートフィルターの領域
提示された、商品シート、この A列が空白列なのかどうか、あるいは 1行目が空白行なのかどうか不明ですが、 このマクロとは離れ、オートフィルター設定がされていない商品シート上でオートフィルターを設定してみて下さい。 設定のための領域指定を、どうしたかにもよりますが、▼は、どのセルに表示されていますか?
もし、B列から表示されていたとしたら、リストの始まりはB列です。 このリストの Field:=2 は B列を 1 とした 2。つまり C列をフィルタリングすることになります。 もし、A列から表示されているとすれば、Field:=2 は B列になりますから、フィルター列としては正しくなります。
3.商品シートにオートフィルターを設定した後、B列に対して テキストフィルターで Aから始まる抽出を実行。 これをマクロ記録してみて下さい。抽出コードが生成されます。おおむね(?)そちらがアップしたコードに似ています。 アップされたコードのシート部分を領域部分にしてもらえれば オートフィルター処理としてはOKですね。 なぜ、この 3.をやってもらったかというと、コードをマクロ記録する目的もありますが、この操作結果、 何がどうなったか? これを、あらためて見てもらうためでした。 シート上で絞り込まれただけですね。でしから、ComboBox1_Change の中で、このコードを実行しても シート上の話であって ユーザーフォーム上のコントトロールのリストには、なんら反映しません。
★ この絞り込まれたものを、どこに反映させたいのか、説明いただければ、コード案をアップします。
(β) 2016/06/24(金) 15:52
おまけというか、追伸です。
絞り込み自体をオートフィルターを使って行うことは、悪くはない方法です。 ただし、オートフィルターで絞り込まれたものを、リストボックスなどのリストに取り込もうとすれば
オートフィルターによる絞り込みを行った後 If 絞り込み結果あり? Then オートフィルターのデータ1行目から(非表示になっているものを含めて)ループで取り出し If 抽出行か? Then リストボックスの List に AddItem End If 繰り返し End If
こんなコードになります。
これなら、オートフィルターを使わず データ領域の各行をループで取り出し If その行の該当のセル Like 比較文字列 & "*" Then リストボックスの List に AddItem End If 繰り返し
このほうが、効率がいいですね。
オートフィルターでも、作業域(作業シート等)をつかっていいなら
オートフィルターによる絞り込みを行った後 If 絞り込み結果あり? Then オートフィルターのデータ域を作業域にコピペ (結果、抽出されたものだけがコピペされます) そのコピぺされたものをループで取り出して AddItem もしくは コピペされた領域の必要部分を二次元配列としてリストボックスのListに格納 End If
こんなコードのほうがよろしいかも。 さらに、後者の方法の場合、フィルターオプション(フィルター詳細設定 AdvancedFilter)を使う手もあります。 そのほうが、オートフィルターより優れた処理方式だと思います。 別の板ですが、
http://excelfactory.net/excelboard/excelvba/excel.cgi?mode=all&namber=176671&rev=0
ここで appleさんという回答者さんが、この方式による処理コードをアップしておられますので 参考にしてください。
ちなみに、同じトピで βは Dictinary を使った処理を提示しています。 これは、難しいとは思いますが、余裕があれば眺めておかれたらいいかもしれません。
(β) 2016/06/24(金) 17:28
丁寧な説明をありがとうございます&お疲れ様です。 とってもわかり易かったです。
1.オートフィルターの設定
?T.この場合は Field:=2 B列で検索
Sheets("商品").Rows("2:2").Select
Selection.AutoFilter ActiveSheet.Range("$A$2:$O$87").AutoFilter Field:=2, Criteria1:="=A*", Operator:=xlO
?U.この場合は Field:=1 B列で検索
Range("A8").Select ActiveSheet.Range("$A$2:$O$87").AutoFilter Field:=1, Criteria1:="=*○*",Operator:=xlOr
?V.この場合は Field:=1 A列で検索
Sheets("商品").Rows("2:2").Select
Selection.AutoFilter ActiveSheet.Range("$B$2:$O$87").AutoFilter Field:=2, Criteria1:="=A*", Operator:=xlO ということでしょうか?
2.オートフィルターの領域 A列と1行目は空白です。Aは作業列として使ってました。「○」した商品のみフィルターかける作業です。 1行目は ボタンを置いているので、データーはありません。
エクセルのB2は題名?B3からがデーターあります。でもリストは「B3」からになってます。
3.商品シートにオートフィルターを設定した後、B列に対して テキストフィルターで Aから始まる抽出を実行。
フィルターを絞った後に、フォーム開いたら絞った結果のみ表示されてます ( ✧Д✧)
これは困りました、フォーム上にやりたかったのに・・・・・どうしましょう (◦`〜´◦)
4. なんとなく、こちらがシンプルそうですね。 データ領域の各行をループで取り出し If その行の該当のセル Like 比較文字列 & "*" Then リストボックスの List に AddItem End If 繰り返し
▲これを ▼こんな感じですか?
With Worksheets("商品") lRow = .Range("B" & Rows.Count).End(xlUp).Row For i = 1 To lRow If .Cells(i, 2).Value Like 比較文字列 & "*" Then ListBox1.List.AddItem Next i
PS. Dictinaryはどうも苦手意識があるので、克服するのは時間がかかりそうです ( ┰_┰) 癖を覚えると、シンプルコードより簡単に作れるとか・・・・処理速度が早いとか・・・・
(ひなの ) 2016/06/24(金) 21:11
いろいろコメントしましたが1つ失念していたことがあります。 リストボックスには タイトル行 を表示したかったんですよね。 となると、Listへの一括格納も、AddItemによる項目追加もNG。 RowSource を使う必要がありますね。
なので、方法は2つのみ。
1.商品シート上でオートフィルターで絞り込んで、別領域にコピペし その領域をRowSourceで指定。 2.商品シートからフィルターオプションで別領域に抽出し、その領域を RowSourceで指定。
いずれでもいいのですが、前者が同じ場所で抽出->別の場所にコピペ、後者が、直接、別の場所に抽出。 ひと手間少ないので、後者がベターでしょう。
以下は、そのサンプルです。関連するComboBox と ListBox だけの関係のコードです。 Initializeでのそのほかのコントロールに対する設定は、適宜、追加してください。
作業 という名前の作業シートを使います。このシートは非表示で構いません。
(2016/6/25 0:37 RowSource 指定に シート修飾を追加しました)
Private Sub UserForm_Initialize()
With ComboBox1 .List = Array("A", "B", "C", "D", "E", "F", "Z") .MatchRequired = True End With
With ListBox1 .ColumnCount = 9 .ColumnWidths = "30;200;30;20;20;20;20;0;40;40" End With
End Sub
Private Sub ComboBox1_Change() Dim r As Range
With ListBox1 .RowSource = "" .ColumnHeads = False End With
If ComboBox1.ListIndex < 0 Then Exit Sub
With Sheets("商品") Set r = .Range("B2", .Range("B" & Rows.Count).End(xlUp)).Resize(, 9) End With
With Sheets("作業") .UsedRange.ClearContents .Range("A1").Value = Sheets("商品").Range("B2").Value 'タイトル .Range("A2").Value = ComboBox1.Value r.AdvancedFilter Action:=xlFilterCopy, CriteriaRange:=.Range("A1:A2"), CopyToRange:=.Range("C1"), Unique:=False If Not IsEmpty(.Range("C2")) Then With .Range("C1").CurrentRegion ListBox1.RowSource = .Offset(1).Resize(.Rows.Count - 1).Address(External:=True) ListBox1.ColumnHeads = True End With End If End With
End Sub
(β) 2016/06/24(金) 23:28
回答ありがとうございます。
すみません。土日、検証する時間がなく、月曜日検証して、 返答しますね。少し時間をくださいませ
前回Dictinaryの話をされたのはもしかしてこういう時に必要なのでしょうか? 値をkeysに格納するので、作業列必要なく、うまく事が運ぶからかしら? (ひなの ) 2016/06/25(土) 23:41
β様 ありがとうございます。コンボックスで検索ばっちりです 検証する必要なかったです。
今後もいろんなところで使いたいと思っていますので、 コードのことで教えていただけますか?
Q7.コードの意味を教えてください。 これはテキストボックスで名前あいまい検索応用できますね。 その代り作業列をずらすだけで大丈夫そうですか?
疑問なのは、タイトル行でセルの結合の部分があり、その所がうまくいかなかったです。 結合を解除して、それぞれの行にタイトル入れたら問題なく内容も表示できました。
それは、そういうものですか?それとも、このコードがそうなってますか? 一応、コードの意味み調べたんですが、それらしいコードも見当たらずで ( ̄ ̄ ̄∇ ̄ ̄ ̄; アリャ? 見落としでしょか?
With Sheets("作業") ’作業シートへ書き出すコード .UsedRange.ClearContents .Range("A1").Value = Sheets("商品").Range("B2").Value 'タイトル .Range("A2").Value = ComboBox1.Value r.AdvancedFilter Action:=xlFilterCopy, CriteriaRange:=.Range("A1:A2"), CopyToRange:=.Range("C1"), Unique:=False ’フィルター結果をリストへ書き出す If Not IsEmpty(.Range("C2")) Then With .Range("C1").CurrentRegion ListBox1.RowSource = .Offset(1).Resize(.Rows.Count - 1).Address(External:=True) ListBox1.ColumnHeads = True End With End If
End With
Q8.フォームメニューからフォーム商品検索を開く方法
ほかのフォームをひらくことはまったく問題ないですが、 商品検索フォームだけはエラーになるんです。 「値がない」と表示されます。原因わかりませんか? 名前違うとか思ったんですが。違うようです。
Private Sub 商品検索_Click() 商品検索.Show vbModeles End Sub (ひなの ) 2016/06/27(月) 10:07
まず、フィルターオプション、これは古くからある機能ですが、オートフィルターより 機能も充実していますし、条件設定も柔軟かつバリエーションにとんだ優れものです。 (なのでメソッド名が オートフィルターより進んでいるという意味で AdvancedFilter になっています)
コードというより、その機能についてマスターすれば、おのずとコードの意味するところは理解できるのではと思います。
【フィルターオプション】で検索すると、図解付きの解説ページがたくさんでてきますので、わかりやすそうなページで そこに記載されている例をすべて試してみられたらいいと思いますね。
>>Q7 指定の列
フィルターオプションでは抽出条件は、列タイトルであたえます。 条件欄の1行目に記載された列タイトルと同じ列のタイトル文字列を、 条件欄の2行目から下に記載された条件で抽出します。
で、条件列は横にいくつでも指定できます。同じ列名を指定することもできます。 横に記載した条件が AND 条件です。1つの列の2行目から下に記載した条件が OR 条件です。 2行目以降に記載した条件は xl2002以外は【前方一致】になります。たとえば A と記載すると Aから始まるもの。 完全一致が必要なら '=A といったように指定します。このあたりは説明サイトを参照してください。
>>結合セル
オートフィルターやフィルターオプションや並び替えといった機能、結合セルとは相性がわるいですね。 結合されたセルがどこに、どのようにあるのかにもよりますが、うまくいく場合もあります。 具体的には、どの列が結合されていますか?
もしかして データ行は結合されていないけど、タイトル行が結合されているという意味ですか? であれば、結合されて裏に隠れた列タイトルは空白ですから、これはコードの問題ではなく 列タイトルを探しに行くというフィルター関連の機能というか、仕様の問題です。抽出はできません。
むりやりやろうとすれば、
・タイトル行の結合解除 ・空白になっている裏に隠れていたセルに、テンポラリーな項目名をセット ・その項目名を使って抽出 ・処理の最後に、タイトル行の必要セルを再結合
>>Q8.フォームメニューからフォーム商品検索を開く方法
想像ですけど、商品検索.Show vbModeles でエラーになっているのではなく、このユーザーフォームのInitialize の、 どこかのコードでエラーになっているのでは?
VBE画面の ツール -> オプション -> 全般タブ ここの エラートラップ を クラスモジュールで中断(R) にしてみてください。 そうすると、本当の犯人が見つかると思います。
(β) 2016/06/27(月) 10:36
>>Q7 指定の列
ありがとうございます。勉強してみます。 セルの結合はEFGHのタイトルのみです。でも解除して、各行にタイトルつけたら問題なく表示されました。
>>Q8.フォームメニューからフォーム商品検索を開く方法
エラーの犯人がわかりました。私です(+_+) テキスボックス等を違う名前に変えたので、わからなくなったんです。 元に戻したら、普通に開いてくれました。でも、違うところがエラーに
クラスモジュールで中断(R)にしたところ、今度は違うところがエラーになって・・・・・ 「list の値取得できません。因数が無効ですと。」
≫自己解決しました。
(β)様長々お付き合いいただきありがとうございました。
この質問はこれにて、おしまいです。おかげさまで、だいぶやりたいことができるようになりました。
いったん頂いたコードと教えていただいたところをおさらいして本データーに組み入れることにします。
本当にありがとうございました。また何かありましたら、懲りずによろしくお願いしました。
(ひなの ) 2016/06/27(月) 17:05
[ 一覧(最新更新順) ]
YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki.
Modified by kazu.