質問者には無理でも、WEB照会などで、このテーマの疑問を持つ人用に、
名前定義による方法をVBAでやってみました。
WEBなどの記事を寄せ集めて、VBAでやってみました。
VBAでやれば、この程度の行数になるという、目安です。
シートやデータ例は私の前回答通りのものを使っています。
ーー
標準モジュールに
Sub test01()
Set sh = Worksheets("顧客リスト")
lr = sh.Range("B10000").End(xlUp).Row
'MsgBox lr
For i = 3 To lr
lc = sh.Cells(i, 1000).End(xlToLeft).Column
'MsgBox lc
sh.Range(sh.Cells(i, 4), sh.Cells(i, lc)).Name = sh.Cells(i, "B").Value
Next i
End Sub
これを実行すると、顧客リストのB列から、会社名の名称の、名前定義を自動で作れます。
ーーー
2回目以後の実行時には、名前定義の全部を一旦抹消をした後、前記Test01を実行することになるでしょう。ご破算をする。
Sub DeleteDefinedNames()
Dim n As Name
For Each n In ActiveWorkbook.Names
n.Delete
Next
End Sub
手操作でもできるでしょうが。
ーー
最後に、シートに、入力規則を、シート「入力表」のE列に設定します。
見ている会社名の列は、C列です。C列に会社名を入力後に操作すると、その会社の製品名がリストに出ます。
E2の1セルしか設定しておりませんが、+インジケータをだし、下方向に引っ張れば(関数の式複写と同じ要領)、E10までもそれより下まででも、入力規則が設定できます。
Sub Sample1()
'入力表のE列に、入力規則ーリストを設定
'C列に会社名入力後にE列をクリックし▼をクリックして、リストから選択
Set sh = Worksheets("入力表")
With Range("E2:E10").Validation
.Delete
.Add Type:=xlValidateList, _
AlertStyle:=xlValidAlertStop, _
Operator:=xlBetween, _
Formula1:="=IF(C2="""",C2,INDIRECT(C2))"
.IgnoreBlank = True
.InCellDropdown = True
.InputTitle = ""
.ErrorTitle = ""
.InputMessage = ""
.ErrorMessage = ""
.IMEMode = xlIMEModeNoControl
.ShowInput = True
.ShowError = True
End With
End Sub
簡単なテスト済みです。
==
質問者に言いたいのは、難しいのは、いろんな時点(日次、月次、随時)で
、Updatingな、顧客リストのデータを、作ることです。これは多分VBAや、他のデータベースソフトの使いこなしができないと、機動的にできないでしょう。
それらができないなら、当面はこの課題は、独力では無理でしょう。
>E列を変えるとエラーが出るので、もう少しなら今少しご指導お願いします。
もう少しと思いますし、
このVBAでのアプローチは間違っていないと思います。
まず、
>>「コンパイルエラー:定数式が必要です」と出ました
このエラーが???ではあるんですが、ともあれ、
シート名が
一方が「顧客リスト」、他方が「入力表」になっていること
続いて
入力表シートのE列が顧客名の列であること
入力表シートのF列が入力候補群をセットする列であること
を確認してください。
私の提示したコードを、単にコピペしているんですよね?
それでも解決できない場合は
シートの1枚目が「顧客リスト」、2枚目が「入力表」であることを確認し
以下のコードに置き換えて試してみてください。
■以下を入力表シートオブジェクトに
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Cells.Count > 1 Then Exit Sub
If ((Target.Row > 11) And (Target.Column = 5)) Then '12行目以下、5列目なら
SelListSet Target.Offset(0, 1), Target.Value '右側のセルにセット
End If
End Sub
■以下を標準モジュールに
Option Explicit
'//選択候補をセットするサブルーチン
Sub SelListSet(tgRange As Range, Companyname As String)
Dim RowCount As Long
Dim SelList As String
Dim ColCount As Long
SelList = ""
RowCount = 5
With ThisWorkbook.Sheets(1)
Do
If .Cells(RowCount, 2).Value = "" Then Exit Do
If .Cells(RowCount, 2).Value = Companyname Then
SelList = .Cells(RowCount, 4).Value 'D列
For ColCount = 5 To 18 'E列~R列
SelList = SelList & "," & _
.Cells(RowCount, ColCount).Value
Next ColCount
End If
RowCount = RowCount + 1
Loop
End With
If SelList = "" Then Exit Sub
With tgRange.Validation
.Delete
.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Operator:= _
xlBetween, Formula1:=SelList
.IgnoreBlank = True
.InCellDropdown = True
.InputTitle = ""
.ErrorTitle = ""
.InputMessage = ""
.ErrorMessage = ""
.IMEMode = xlIMEModeNoControl
.ShowInput = True
.ShowError = True
End With
End Sub
シート構成、使い方から判断して、
セル範囲の範囲名を使うよりも、
入力表のE列が変化したタイミングで、
その右隣りのセルの入力候補群に期待の一覧をセットするほうが
わかりやすく、使いやすいだろうと思います。
以下のコードでいかがでしょうか。
■以下を入力表シートオブジェクトに
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Cells.Count > 1 Then Exit Sub
If ((Target.Row > 11) And (Target.Column = 5)) Then '12行目以下、5列目なら
SelListSet Target.Offset(0, 1), Target.Value '右隣のセルにセット
End If
End Sub
■以下を標準モジュールに
Option Explicit
Const CCTblName = "顧客リスト" '会社名、製品名一覧シート名
Const SLSetName = "入力表" '入力表のシート名
Const inttl = "製品の選択"
Const inmsg = "製品を選択してください"
Const erttl = "選択エラー"
Const ermsg = "選択を間違えています"
'//選択候補をセットするサブルーチン
Sub SelListSet(tgRange As Range, Companyname As String)
Dim RowCount As Long
Dim SelList As String
Dim ColCount As Long
SelList = ""
RowCount = 5
With ThisWorkbook.Sheets(CCTblName)
Do
If .Cells(RowCount, 2).Value = "" Then Exit Do
If .Cells(RowCount, 2).Value = Companyname Then
SelList = .Cells(RowCount, 4).Value 'D列
For ColCount = 5 To 18 'E列~R列
SelList = SelList & "," & _
.Cells(RowCount, ColCount).Value
Next ColCount
End If
RowCount = RowCount + 1
Loop
End With
If SelList = "" Then Exit Sub
With tgRange.Validation
.Delete
.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Operator:= _
xlBetween, Formula1:=SelList
.IgnoreBlank = True
.InCellDropdown = True
.InputTitle = inttl
.ErrorTitle = erttl
.InputMessage = inmsg
.ErrorMessage = ermsg
.IMEMode = xlIMEModeNoControl
.ShowInput = True
.ShowError = True
End With
End Sub
お礼
>名前の設定はいりません。 >最初からこう質問すればいいのに。 これが思いつかないレベルなのが悲しいかな実力です。 OFFSETとMATCH関数で出来るとは。 知識の無さからご回答だけからだと検証方法が分からず大変失礼しました。#3さんの説明で理解しました。 一番最初のご回答であったこととお詫びの意味でBSにさせていただきますのでご容赦!
補足
早々のご回答ありがとうございます。 ご回答だと社名が決まれば製品名が自動で一意に決定されるような気がするのですが。 A社には色んな製品(A-1、A-2、・・・)があるので、それを製品名の列(E列)で選択できるようにしたいのですが。 有るセルで社名を選択したらその横のセルでその社名に対応した複数の製品名をリストから選択できるようにするのが目的です。 もし当方の大勘違いならご容赦ください。