[[20120308182553]] 『データをコピーして一部の内容を変更して挿入する』(ふーさん) ページの最後に飛ぶ

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

 

『データをコピーして一部の内容を変更して挿入するマクロ』(ふーさん)

 工場で生産指示したものをどこに出荷したかを記入するファイルがあります。

   A    B    C    D   E   F   G   H   I   J    K   ・・・ P    Q    R    S
 1
 2    開始日  指示No 部署1 部署2 部署3 担当 商品ID 品名 指示数量 完成数量   完了日  出荷日  出荷先 出荷数
 3      2012/3/1 12345678 AA   BB  CC  鈴木  1111 ●●● 50000  
 4      2012/3/2 23456789 AA   DD  EE  加藤  2222 □□□  6000

 このように入力されていたものを、生産が終わって出荷した時に次のようにデータを追加します。

   A    B    C    D   E   F   G   H   I   J    K   ・・・ P    Q    R    S
 1
 2    開始日  指示No 部署1 部署2 部署3 担当 商品ID 品名 指示数量 完成数量   完了日  出荷日  出荷先 出荷数
 3      2012/3/1 12345678 AA   BB  CC  鈴木  1111 ●●● 50000  50000    2012/3/7 2012/3/8 あ社  10000
 4      2012/3/1 12345678 AA   BB  CC  鈴木  1111 ●●●  *    *     2012/3/7 2012/3/9 い社  40000
 5      2012/3/2 23456789 AA   DD  EE  加藤  2222 □□□  6000

 同じものでも出荷先が一か所の場合と複数の場合があり、複数の場合は上記のように元のデータをコピーし、
 一部を * にしたり出荷日・出荷先・数量を変更してそのデータに追加・挿入します。

 この結果入力をユーザーフォームを使ってできないかと言われました。
 ただ、稀に「指示No」が元から重複しているものもあります(商品などは違う)

 なので「指示No」をテキストボックスか何かに打ち込んで、商品IDと商品名をリストボックスに表示、
 表示されたリストから該当データを選んで出荷結果を入力、出荷先が複数の場合は上記のように
 行を挿入してデータを追加…

 ということをやりたいのですが、ユーザーフォームはただ単純にテキストボックスに入力して
 転記するだけのものしか作ったことがなく、どのようなコードにしたらいいのか途方にくれております。

 元のデータの呼び出し方と、データの間に追加のデータを挿入する方法をお教えください。

 複数出荷については了解なんだけど、それとは別に、追加出荷分も含めて
 入力済みのものの修正・取消ということは考えなくてもいいね?

 追記)データ件数は、おおよそ、どれぐらい?
   ざくっとでいいので。数百?数千?数万?

 (ぶらっと)

 ぶらっと様
 修正・取消は多分目視の方が確実なのでこの場合考えなくて大丈夫です。
 データ件数は2〜3千ぐらいです。

 あと、リストボックスに表示する時に商品IDと商品名だけでは特定できないかもしれないので「開始日」または「指示数量」まで表示したいです。

 (ふーさん)

 面白そうなので作って見ました
 上手く行かなかったらゴメン

 AdvancedFilter(フィルタオプション)を使いますので作業用シートを用意します
 (上手く動く様なら後で非表示にすれば善いと思います)
 シート名は「抽出」と言う名前を付けて下さい
 「抽出」シートに

   A    B    C    D   E    F   G
 1    指示No  商品ID  品名 指示数量    指示No

 B1 :「指示No」、C1:「商品ID」、D1:「品名」、E1:「指示数量」、G1:「指示No」の列見出しを
 「出荷したか」を記入しているシートから列見出しをCopyして下さい
 (フィルタオプションが神経質な様で、手で記入しない方が善いと思います)

 次にUserFormを用意します
 各コントロールの配置は以下の様にします
 指示No   :ComboBox1   開始日   :TextBox1   部署1    :TextBox2    部署2    :TextBox3
 部署3    :TextBox4    担当     :TextBox5   商品ID   :ComboBox2   品名     :TextBox6
 指示数量 :TextBox7    完成数量 :TextBox8   完了日   :TextBox9    出荷日   :TextBox10
 出荷先   :TextBox11   出荷数   :TextBox12  更新/追加:CommandButton1  閉じる   :CommandButton2
  L列〜O列は解らないのでコントロールを配置していません

 UserFormのコードモジュールに以下を記述して下さい
 尚、出荷シートの名前、列数、列見出し「開始日」の位置を実際のシートに合わせて下さい(★印)

 Option Explicit

 Private Const cstrMaster As String = "Sheet1"   '★出荷マスタのシート名(実際の名前に変更)
 Private Const clngColumns As Long = 18          '★出荷マスタの列数
 Private Const cstrTop As String = "B2"          '★出荷マスタの見出し先頭セル位置(「開始日」の位置)

 Private rngList As Range                        'マスタの列見出し先頭セル位置
 Private rngWork As Range                        '作業用シートの抽出範囲
 Private rngCrit As Range                        '作業用シートの条件範囲
 Private lngRows As Long                         'List行数(最終行位置)
 Private dicItemList As Object                   '商品IDをKeyとした品名List

 Private Sub UserForm_Initialize()

    Const cstTempNo As String = "Temporarily"

    Dim vntData As Variant

    'Listの先頭セル位置を基準とする(先頭列の列見出しのセル位置)
    Set rngList = Worksheets(cstrMaster).Range(cstrTop)

    '抽出用シートの抽出範囲
    Set rngWork = Worksheets("抽出").Range("A1:E1")
    rngWork.Item(1, 1).Value = cstTempNo

    '抽出用シートの条件範囲
    Set rngCrit = rngWork.Parent.Range("G1:G2")

    With rngList
        '行数の取得
        lngRows = .Offset(Rows.Count - .Row).End(xlUp).Row - .Row
        If lngRows <= 0 Then
            lngRows = 0
        Else
            '最終列の後ろに仮のレコード番号を入力
            .Offset(, clngColumns).Value = cstTempNo
            .Offset(1, clngColumns).Resize(lngRows).Formula = "=Row()-" & .Row
        End If
    End With

    '「指示No」を無重複で取得
    vntData = GetNumb
    If Not VarType(vntData) = vbBoolean Then
        ComboBox1.List = vntData
    End If

    ComboBox2.ColumnCount = 2

    'Dictionaryオブジェクトを取得
    Set dicItemList = CreateObject("Scripting.Dictionary")
    'Dictionaryに品名Listを取得
    GetItemList

 End Sub

 Private Sub UserForm_Terminate()

    '最終列の後ろに仮のレコード番号を破棄
    rngList.Offset(, clngColumns).EntireColumn.ClearContents

    Set dicItemList = Nothing
    Set rngList = Nothing
    Set rngWork = Nothing
    Set rngCrit = Nothing

 End Sub

 Private Sub ComboBox1_Enter()

    '各コントロールをクリア
    ClearControls

 End Sub

 Private Sub ComboBox1_Exit(ByVal Cancel As MSForms.ReturnBoolean)

    '指示No

    Dim i As Long
    Dim vntData As Variant
    Dim lngRow As Long

    If ComboBox1.ListIndex > -1 Then
        '商品IDのデータを取得
        vntData = ExtractID(ComboBox1.Text, lngRow)
        With ComboBox2
            '抽出行数が0で無いなら
            If lngRow > 0 Then
                'ComboBox2にListを設定
                .List = vntData
                .ListIndex = 0
            Else
                'ComboBox2と各コントロールをクリア
                .Clear
                ClearControls
            End If
        End With
    Else
        'Dictionaryから商品IDと品名を取り出しComboBox2に設定
        vntData = dicItemList.Keys
        With ComboBox2
            .Clear
            For i = 0 To UBound(vntData)
                .AddItem vntData(i)
                .List(.ListCount - 1, 1) = dicItemList(vntData(i))
            Next i
        End With
    End If

 End Sub

 Private Sub ComboBox2_Click()

    '商品ID

    If ComboBox1.ListIndex > -1 Then
        With ComboBox2
            If .ListIndex > -1 Then
                '各コントロールにデータ読み込み
                GetLitData rngWork.Cells(2, 1).Offset(.ListIndex).Value
            End If
        End With
    End If

 End Sub

 Private Sub ComboBox2_Exit(ByVal Cancel As MSForms.ReturnBoolean)

    With ComboBox2
        '商品IDの選択が無い場合
        If .ListIndex = -1 Then
            'TextBox部に入力が在る場合
            If .Text <> "" Then
                '商品IDListを探し在ったら
                If dicItemList.Exists(.Text) Then
                    'TextBox6に品名を代入
                    TextBox6.Text = dicItemList.Item(.Text)
                Else
                    TextBox6.Text = ""
                End If
            Else
                TextBox6.Text = ""
            End If
        Else
            TextBox6.Text = .List(.ListIndex, 1)
        End If
    End With

 End Sub

 Private Sub CommandButton1_Click()

    '更新/追加

    Dim lngRow As Long
    Dim vntData As Variant
    Dim lngIndex As Long
    Dim lngButtons As Long
    Dim strPrompt As String

    '商品IDの選択位置を取得
    lngIndex = ComboBox2.ListIndex

    '指示Noが選ばれている場合
    If ComboBox1.ListIndex > -1 Then
        '商品IDが選択されている場合
        If lngIndex > -1 Then
            '「指示数量」に「*」が入力されていなかったら
            If StrComp(Trim(TextBox7.Text), "*", vbTextCompare) <> 0 Then
                strPrompt = "レコードを更新します"
                If MsgBox(strPrompt, vbQuestion + vbYesNo) = vbYes Then
                    '既存のレコードを更新
                    PutLitData rngWork.Cells(2, 1).Offset(lngIndex).Value
                End If
            Else
                strPrompt = "レコードを追加します"
                If StrComp(rngWork.Cells(2, 5).Offset(lngIndex).Value, "*", vbTextCompare) = 0 Then
                    strPrompt = strPrompt & vbLf & "はい:レコード追加" _
                                & vbLf & "いいえ:レコード更新"
                    lngButtons = vbQuestion + vbYesNoCancel
                Else
                    lngButtons = vbQuestion + vbYesNo
                End If
                Select Case MsgBox(strPrompt, lngButtons)
                    Case vbNo
                        '既存のレコードを更新
                        lngRow = rngWork.Cells(2, 1).Offset(lngIndex).Value
                        PutLitData lngRow
                    Case vbYes
                        'レコードを追加
                        lngRow = rngWork.Cells(2, 1).Offset(lngIndex).Value + 1
                        rngList.Offset(lngRow).EntireRow.Insert
                        PutLitData lngRow
                        lngIndex = lngIndex + 1
                        lngRows = lngRows + 1
                End Select
            End If
        Else
            'TextBox部には入力が在る場合
            If ComboBox2.Text <> "" Then
                strPrompt = "新規レコードを追加します"
                If MsgBox(strPrompt, vbQuestion + vbYesNo) = vbYes Then
                    'レコードを追加
                    lngIndex = ComboBox2.ListCount
                    lngRow = rngWork.Cells(2, 1).Offset(lngIndex - 1).Value + 1
                    rngList.Offset(lngRow).EntireRow.Insert
                    PutLitData lngRow
                    lngRows = lngRows + 1
                    'Dictionaryに登録
                    dicItemList.Item(ComboBox2.Text) = TextBox6.Text
                End If
            End If
        End If
    Else
        '指示Noと商品IDに入力が在る場合
        If ComboBox1.Text <> "" And ComboBox2.Text <> "" Then
            strPrompt = "List最終行に新規レコードを追加します"
            If MsgBox(strPrompt, vbQuestion + vbYesNo) = vbYes Then
                'List最終行にレコードを追加
                lngRows = lngRows + 1
                lngIndex = 0
                lngRow = lngRows
                If ComboBox2.ListIndex = -1 Then
                    'Dictionaryに登録
                    dicItemList.Item(ComboBox2.Text) = TextBox6.Text
                End If
                'データを転記
                PutLitData lngRow
                '「指示No」を無重複で取得
                vntData = GetNumb
                If Not VarType(vntData) = vbBoolean Then
                    ComboBox1.List = vntData
                End If
            End If
        End If
    End If

    '商品IDのデータを取得
    vntData = ExtractID(ComboBox1.Text, lngRow)
    With ComboBox2
        '抽出行数が0で無いなら
        If lngRow > 0 Then
            'ComboBox2にListを設定
            .List = vntData
            'ListIndexを再設定
            .ListIndex = lngIndex
        End If
    End With

 End Sub

 Private Sub CommandButton2_Click()

    '閉じる

    Unload Me

 End Sub

 Private Sub DoFilter(rngScope As Range, _
                    rngCriteria As Range, _
                    rngCopyTo As Range, _
                    Optional blnUnique As Boolean)

 '  AdvancedFilterを実行

    rngScope.AdvancedFilter _
            Action:=xlFilterCopy, _
            CriteriaRange:=rngCriteria, _
            CopyToRange:=rngCopyTo, _
            Unique:=blnUnique

 End Sub

 Private Function GetNumb() As Variant

    Dim i As Long
    Dim lngRow As Long
    Dim vntData As Variant

    '「指示No」を無重複で取得
    DoFilter rngList.Cells(1, 2).Resize(lngRows + 1), _
                rngCrit.Cells(1, 1).Offset(, 1), _
                rngWork.Cells(1, 2), True

    With rngWork.Cells(1, 2)
        '行数の取得
        lngRow = .Offset(Rows.Count - .Row).End(xlUp).Row - .Row
        If lngRows > 0 Then
            vntData = .Offset(1).Resize(lngRow, 2).Value
            For i = 1 To lngRow
                vntData(i, 1) = CStr(vntData(i, 1))
            Next i
            ReDim Preserve vntData(1 To lngRow, 1 To 1)
            GetNumb = vntData
        Else
            GetNumb = False
        End If
    End With

 End Function

 Private Sub GetItemList()

    Dim i As Long
    Dim lngRow As Long
    Dim vntData As Variant

    '「商品ID」「品名」を無重複で取得
    DoFilter rngList.Cells(1, 7).Resize(lngRows + 1, 2), _
                rngCrit.Cells(1, 1).Offset(, 1), _
                rngWork.Cells(1, 3).Resize(, 2), True

    With rngWork.Cells(1, 3)
        '行数の取得
        lngRow = .Offset(Rows.Count - .Row).End(xlUp).Row - .Row
        If lngRows > 0 Then
            vntData = .Offset(1).Resize(lngRow, 2).Value
            'Dictionaryに商品IDをKeyとして品名を登録
            For i = 1 To lngRow
                dicItemList.Item(CStr(vntData(i, 1))) = vntData(i, 2)
            Next i
        End If
    End With

 End Sub

 Private Function ExtractID(vntCrit As Variant, lngRow As Long) As Variant

    Dim i As Long
    Dim vntData As Variant

    '条件範囲にComboBoxの値を代入(式の形で)
    rngCrit.Cells(2, 1).Value = "=""" & vntCrit & """"

    'AdvancedFilterを実行
    DoFilter rngList.Resize(lngRows + 1, clngColumns + 1), rngCrit, rngWork

    '抽出範囲から
    With rngWork.Cells(1, 1)
        '抽出行数を取得
        lngRow = .Offset(Rows.Count - .Row).End(xlUp).Row - .Row
        '列見出し以上の行が在るなら
        If lngRow > 0 Then
            'データを配列に取得
            vntData = .Offset(1, 2).Resize(lngRow, 2).Value
            '「商品ID」を文字列に変換
            For i = 1 To lngRow
                vntData(i, 1) = CStr(vntData(i, 1))
            Next i
            '戻り値として「商品ID」「品名」を配列で返す
            ExtractID = vntData
        End If
    End With

 End Function

 Private Sub ClearControls()

    TextBox1.Text = "" '開始日
    TextBox2.Text = "" '部署1
    TextBox3.Text = "" '部署2
    TextBox4.Text = "" '部署3
    TextBox5.Text = "" '担当
    ComboBox2.Text = "" '商品ID
    TextBox6.Text = "" '品名
    TextBox7.Text = "" '指示数量
    TextBox8.Text = "" '完成数量
    TextBox9.Text = "" '完了日
    TextBox10.Text = "" '出荷日
    TextBox11.Text = "" '出荷先
    TextBox12.Text = "" '出荷数

 End Sub

 Private Sub GetLitData(lngRow As Long)

    '出荷マスタ指定位置因り
    With rngList
        TextBox1.Text = .Offset(lngRow, 0).Value    '開始日
        'ComboBox1.Text = .Offset(lngRow, 1).Value  '指示No 使わない
        TextBox2.Text = .Offset(lngRow, 2).Value    '部署1
        TextBox3.Text = .Offset(lngRow, 3).Value    '部署2
        TextBox4.Text = .Offset(lngRow, 4).Value    '部署3
        TextBox5.Text = .Offset(lngRow, 5).Value    '担当
        'ComboBox2.Text = .Offset(lngRow, 6).Value   '商品ID 使わない
        TextBox6.Text = .Offset(lngRow, 7).Value    '品名
        TextBox7.Text = .Offset(lngRow, 8).Value    '指示数量
        TextBox8.Text = .Offset(lngRow, 9).Value    '完成数量
        TextBox9.Text = .Offset(lngRow, 14).Value   '完了日
        TextBox10.Text = .Offset(lngRow, 15).Value  '出荷日
        TextBox11.Text = .Offset(lngRow, 16).Value  '出荷先
        TextBox12.Text = .Offset(lngRow, 17).Value  '出荷数
    End With

 End Sub

 Private Sub PutLitData(lngRow As Long)

    '入荷マスタを更新
    With rngList
        .Offset(lngRow, 0).Value = TextBox1.Text    '開始日
        .Offset(lngRow, 1).Value = ComboBox1.Text   '指示No
        .Offset(lngRow, 2).Value = TextBox2.Text    '部署1
        .Offset(lngRow, 3).Value = TextBox3.Text    '部署2
        .Offset(lngRow, 4).Value = TextBox4.Text    '部署3
        .Offset(lngRow, 5).Value = TextBox5.Text    '担当
        .Offset(lngRow, 6).Value = ComboBox2.Text   '商品ID
        .Offset(lngRow, 7).Value = TextBox6.Text    '品名
        .Offset(lngRow, 8).Value = TextBox7.Text    '指示数量
        .Offset(lngRow, 9).Value = TextBox8.Text    '完成数量
        .Offset(lngRow, 14).Value = TextBox9.Text   '完了日
        .Offset(lngRow, 15).Value = TextBox10.Text  '出荷日
        .Offset(lngRow, 16).Value = TextBox11.Text  '出荷先
        .Offset(lngRow, 17).Value = TextBox12.Text  '出荷数
        .Offset(lngRow, clngColumns).Formula _
                = "=Row()-" & rngList.Row           '仮番号
    End With

 End Sub

 尚、操作する出荷シートのT列をUserFormが開いている間は、作業列として使い
 仮の行番号を数式で入れる状態と成ります、またUserFormが閉じられる時にこの列は消去されます
 操作は、UserFormを表示して、「指示No」のComboBox1に指示Noを入力するか、プルダウンで選択して下さい
 ComboBox1からフォーカスが移ると、出荷シートから指定の指示Noを抽出して、抽出したレコードの
 商品IDがComboBox2のListに設定されますので、Listから選択されたレコードがUserFormのコントロールに表示されます

 表示されたら、各コントロールの値を修正し更新/追加ボタンを押します
 この時、「指示数量」に「*」だけが入った場合、現在ComboBox2で選択されたレコードを更新するか、
 表示されているデータで新規レコードを追加するか、キャンセルをするかを聞いて来ますので、此れに答えます
 「はい」を選択すると、現在ComboBox2で選択されたレコードの下に新規レコードが追加されます
 「いいえ」を選択すると、現在ComboBox2で選択されたレコードが更新されます
 「キャンセル」の場合、何も行いません
 また、「指示数量」に「*」以外が入った場合は、レコードの更新だけが行われます
 尚、「指示No」のComboBox1に出荷シート無い指示Noを入力し、商品IDも入力されていれば
 出荷シートの最終行の下に、ComboBox1の番号の新規レコードが作成されます

 (Bun)


 Bunさま

 ありがとうございます。
 試してみたところほぼ希望通りにできました。

 申し訳ありません、追加なんですが…

 ・上に書いたのですが、
 > あと、リストボックスに表示する時に商品IDと商品名だけでは特定できないかもしれないので「開始日」または「指示数量」まで表示したいです。
 これは今ComboBox2に商品名が表示されて選ぶようにとのことですが、できればキーとして
 「商品名」
 「部署3」
 「指示数量」
 で特定したいです(すみません、開始日ではなく部署に変えました)

 ・レコードの更新と追加ですが、
 >この時、「指示数量」に「*」だけが入った場合、現在ComboBox2で選択されたレコードを更新するか、
 >表示されているデータで新規レコードを追加するか、キャンセルをするかを聞いて来ますので、此れに答えます
 レコード追加の際に「指示数量」に必ず「*」が入るとは限らないケースも有り得るので、できればコマンドボタンを2個用意するか
 オプションボタンなどの選択で「更新」か「追加」かを選びたいです。
 (人の入力ミスで「指示数量」を「*」に変更するのを忘れたまま登録→OKすることも考えられるので)

 ・あとこれはこちらで変更しただけですが、「出荷先」を顧客マスターシートから選択するために「ComboBox3」に変更しました。
 (プルダウンから選ぶコードはできたのでコントロールの変更だけです)

 何か色々欲を言って申し訳ありません

 (ふーさん)

 すみません、もう一つ追加です。

 データを「追加」する際に、元のデータのL列〜O列の部分をコピーして挿入したいです。
 (N列には計算式が入っています)

 (ふーさん)

 横から失礼。
コードを書いていたら、すでにBunさんから(同じような方法での)コードがアップされたので、
こちらのアップは控えます。

 1点のみ。入力項目はテキストボックスを使うわけだけど、(さわってほしくない)表示項目はラベルにしたほうが無難。
(というか、ラベルにすべきだと)

 (ぶらっと)

 >・上に書いたのですが、
 >> あと、リストボックスに表示する時に商品IDと商品名だけでは特定できないかもしれないので「開始日」または「指示数量」まで表示したいです。
 >これは今ComboBox2に商品名が表示されて選ぶようにとのことですが、できればキーとして
 >「商品名」
 >「部署3」
 >「指示数量」
 >で特定したいです(すみません、開始日ではなく部署に変えました)

 此れ、使い方を勘違いして居ませんか?
 上記の項目をKeyとしてどうやって使うの?
 現状のコードでは先ず、「指示No」のComboBox1に手入力若しくは、List選択してフォーカスが移れば(Enterすれば)、
 出荷シートから選択された「指示No」に該当するレコードの位置と商品ID、品名等が抽出され
 その、抽出された商品IDのListがComboBox2のListに設定され、先頭の商品IDが自動的に選択されます
 と同時に、選択されたレコードの値が各コントロールに表示されます
 次に、フォーカスをComboBox2に移し、↓↑Keyを押せば次々にレコードの値が各コントロールに表示されます
 因って、「商品名」も「部署3」も「指示数量」も全て確認出来る筈ですので、態々キーを設定して云々は必要無いと思いますが?

  >レコード追加の際に「指示数量」に必ず「*」が入るとは限らないケースも有り得るので、できればコマンドボタンを2個用意するか
 >オプションボタンなどの選択で「更新」か「追加」かを選びたいです。

 >データを「追加」する際に、元のデータのL列〜O列の部分をコピーして挿入したいです。
 >(N列には計算式が入っています)

 此れに就いては、最後に変更したコードをUpします
 尚、新規データの入力は行わない様ですが「L列〜O列の部分をコピーする」を行うので、
 Listにデータの無い状態で新規データの入力を行うとL列〜O列に列見出しがCopyされるので注意して下さい

 また、今回のコードでは、商品マスタ(商品IDと品名の対比表)が在るのかが解らないので
 出荷データの中の商品IDと品名を全てUserFormの立ち上げ時に読み込んで持っていますので
 レコード追加等でComboBox2のListに無い商品IDをComboBox2に手打ちすれば、出荷データに在る商品IDなら
 品名が表示される様に成っています
 もし、商品マスタ(商品IDと品名の対比表)が在るならそちらを持たせる様に変更した方が善いと思います

 ぶらっとさんの

 >1点のみ。入力項目はテキストボックスを使うわけだけど、(さわってほしくない)表示項目はラベルにしたほうが無難。
 >(というか、ラベルにすべきだと)

 ご忠告ごもっともだと思いますが?
 上司と言う物は気まぐれな物で、いつ何時に入力や修正をUserFormでやれと言う事に成るかも解りませんので
 TextBox、ComboBoxで作って置いて、使わない(弄られたくない)コントロールは「Locked プロパティ」を
 Trueにして置けば編集出来なくなりますの、デザイン画面で此れを設定すれば善いと思います

 コードの変更点をUpします
 コントロールは、CommandButton3を追加して置きます
 以下のプロシージャを差し替えて下さい

 Private Sub CommandButton1_Click()

    '更新

    Dim lngRow As Long
    Dim vntData As Variant
    Dim lngIndex As Long
    Dim strPrompt As String

    '商品IDの選択位置を取得
    lngIndex = ComboBox2.ListIndex

    '指示Noが選ばれている場合
    If ComboBox1.ListIndex > -1 Then
        '商品IDが選択されている場合
        If lngIndex > -1 Then
            strPrompt = "レコードを更新します"
            If MsgBox(strPrompt, vbQuestion + vbYesNo) = vbYes Then
                '既存のレコードを更新
                lngRow = rngWork.Cells(2, 1).Offset(lngIndex).Value
                PutLitData lngRow, False
            End If
        End If
    End If

    '商品IDのデータを取得
    vntData = ExtractID(ComboBox1.Text, lngRow)
    With ComboBox2
        '抽出行数が0で無いなら
        If lngRow > 0 Then
            'ComboBox2にListを設定
            .List = vntData
            'ListIndexを再設定
            .ListIndex = lngIndex
        End If
    End With

 End Sub

 Private Sub CommandButton3_Click()

    '追加

    Dim lngRow As Long
    Dim vntData As Variant
    Dim lngIndex As Long
    Dim strPrompt As String

    '商品IDの選択位置を取得
    lngIndex = ComboBox2.ListIndex

    '指示Noが選ばれている場合
    If ComboBox1.ListIndex > -1 Then
        strPrompt = "新規レコードを追加します"
        '商品IDが選択されている場合
        If lngIndex > -1 Then
            If MsgBox(strPrompt, vbQuestion + vbYesNo) = vbYes Then
                'レコードを追加
                lngRow = rngWork.Cells(2, 1).Offset(lngIndex).Value + 1
                rngList.Offset(lngRow).EntireRow.Insert
                PutLitData lngRow, True
                lngIndex = lngIndex + 1
                lngRows = lngRows + 1
            End If
        Else
            'TextBox部には入力が在る場合
            If ComboBox2.Text <> "" Then
                If MsgBox(strPrompt, vbQuestion + vbYesNo) = vbYes Then
                    'レコードを追加
                    lngIndex = ComboBox2.ListCount
                    lngRow = rngWork.Cells(2, 1).Offset(lngIndex - 1).Value + 1
                    rngList.Offset(lngRow).EntireRow.Insert
                    PutLitData lngRow, True
                    lngRows = lngRows + 1
                    'Dictionaryに登録
                    dicItemList.Item(ComboBox2.Text) = TextBox6.Text
                End If
            End If
        End If
    Else
        '指示Noと商品IDに入力が在る場合
        If ComboBox1.Text <> "" And ComboBox2.Text <> "" Then
            strPrompt = "List最終行に新規レコードを追加します"
            If MsgBox(strPrompt, vbQuestion + vbYesNo) = vbYes Then
                'List最終行にレコードを追加
                lngRows = lngRows + 1
                lngIndex = 0
                lngRow = lngRows
                If ComboBox2.ListIndex = -1 Then
                    'Dictionaryに登録
                    dicItemList.Item(ComboBox2.Text) = TextBox6.Text
                End If
                'データを転記
                PutLitData lngRow, True
                '「指示No」を無重複で取得
                vntData = GetNumb
                If Not VarType(vntData) = vbBoolean Then
                    ComboBox1.List = vntData
                End If
            End If
        Else
            Exit Sub
        End If
    End If

    '商品IDのデータを取得
    vntData = ExtractID(ComboBox1.Text, lngRow)
    With ComboBox2
        '抽出行数が0で無いなら
        If lngRow > 0 Then
            'ComboBox2にListを設定
            .List = vntData
            'ListIndexを再設定
            .ListIndex = lngIndex
        End If
    End With

 End Sub

 Private Sub PutLitData(lngRow As Long, blnNewLine As Boolean)

    '入荷マスタを更新
    With rngList
        .Offset(lngRow, 0).Value = TextBox1.Text    '開始日
        .Offset(lngRow, 1).Value = ComboBox1.Text   '指示No
        .Offset(lngRow, 2).Value = TextBox2.Text    '部署1
        .Offset(lngRow, 3).Value = TextBox3.Text    '部署2
        .Offset(lngRow, 4).Value = TextBox4.Text    '部署3
        .Offset(lngRow, 5).Value = TextBox5.Text    '担当
        .Offset(lngRow, 6).Value = ComboBox2.Text   '商品ID
        .Offset(lngRow, 7).Value = TextBox6.Text    '品名
        .Offset(lngRow, 8).Value = TextBox7.Text    '指示数量
        .Offset(lngRow, 9).Value = TextBox8.Text    '完成数量
        .Offset(lngRow, 14).Value = TextBox9.Text   '完了日
        .Offset(lngRow, 15).Value = TextBox10.Text  '出荷日
        '.Offset(lngRow, 16).Value = TextBox11.Text  '出荷先
        .Offset(lngRow, 16).Value = ComboBox3.Text  '出荷先
        .Offset(lngRow, 17).Value = TextBox12.Text  '出荷数
        '追加の場合
        If blnNewLine Then
            .Offset(lngRow, clngColumns).Formula _
                    = "=Row()-" & rngList.Row        '仮番号
            '転記元レコードからL列〜O列をCopy
            .Offset(lngRow - 1, 10).Resize(, 4).Copy _
                    Destination:=.Offset(lngRow, 10)
        End If
    End With

 End Sub

 (Bun)


 >これは今ComboBox2に商品名が表示されて選ぶようにとのことですが、できればキーとして
 >「商品名」
 >「部署3」
 >「指示数量」
 >で特定したいです(すみません、開始日ではなく部署に変えました)

 上記に就いて、今朝思いついたのですが?、考え方を代えてコードを作り直しました

 先ず「抽出」シートのレイアウトを変更します
 「抽出」シートを以下に

   A    B    C    D   E    F    G   H 
 1    指示No  商品ID  品名 指示数量 部署3     指示No

 B1 :「指示No」、C1:「商品ID」、D1:「品名」、E1:「指示数量」、F1:「部署3」H1:「指示No」とします
 「出荷したか」を記入しているシートから列見出しをCopyして下さい

 次にUserFormを用意します
 各コントロールの配置は以下の様にします
 指示No   :ComboBox1   開始日   :TextBox1   部署1    :TextBox2    部署2    :TextBox3
 部署3    :TextBox4    担当     :TextBox5   商品ID   :ComboBox2   品名     :TextBox6
 指示数量 :TextBox7    完成数量 :TextBox8   完了日   :TextBox9    出荷日   :TextBox10
 出荷先   :ComboBox3   出荷数   :TextBox12  
 更新:CommandButton1  閉じる:CommandButton2  追加:CommandButton3

 此処にComboBox4:行選択を追加します、尚、ComboBox3は商品IDの選択だけの機能にします(ComboBox2と同じ)
 ComboBox4は複数列のComboで「商品ID」「品名」「部署3」「指示数量」と仮番号を表示し
 このComboの値に因り、指定した「指示No」の行選択を行います
 (コントロールを追加するのでタブオーダーの変更に注意して下さい)

 以下をUserFormのコードモジュールに記述して下さい

 Option Explicit

 Private Const cstrMaster As String = "Sheet1"   '★出荷マスタのシート名(実際の名前に変更)
 Private Const clngColumns As Long = 18          '★出荷マスタの列数
 Private Const cstrTop As String = "B2"          '★出荷マスタの見出し先頭セル位置(「開始日」の位置)

 Private rngList As Range                        'マスタの列見出し先頭セル位置
 Private rngWork As Range                        '作業用シートの抽出範囲
 Private rngCrit As Range                        '作業用シートの条件範囲
 Private lngRows As Long                         'List行数(最終行位置)

 Private Sub UserForm_Initialize()

    Const cstTempNo As String = "Temporarily"

    Dim vntData As Variant

    'Listの先頭セル位置を基準とする(先頭列の列見出しのセル位置)
    Set rngList = Worksheets(cstrMaster).Range(cstrTop)
    rngList.Parent.Activate

    '抽出用シートの抽出範囲
    Set rngWork = Worksheets("抽出").Range("A1:G1")
    rngWork.Item(1, 1).Value = cstTempNo

    '抽出用シートの条件範囲
    Set rngCrit = rngWork.Parent.Range("H1:H2")

    With rngList
        '行数の取得
        lngRows = .Offset(Rows.Count - .Row).End(xlUp).Row - .Row
        If lngRows <= 0 Then
            lngRows = 0
        Else
            '最終列の後ろに仮のレコード番号を入力
            .Offset(, clngColumns).Value = cstTempNo
            .Offset(1, clngColumns).Resize(lngRows).Formula = "=Row()-" & .Row
        End If
    End With

    '「指示No」を無重複で取得
    vntData = GetNumb
    If Not VarType(vntData) = vbBoolean Then
        ComboBox1.List = vntData
    End If

    '商品IDと品名を登録
    ComboBox2.ColumnCount = 2
    GetItemList ComboBox2

    '行選択用ComboBoxの設定
    With ComboBox4
        .ColumnCount = 6
        .ColumnWidths = "72;0;72;72;72;72"
    End With

 End Sub

 Private Sub UserForm_Terminate()

    '最終列の後ろに仮のレコード番号を破棄
    rngList.Offset(, clngColumns).EntireColumn.ClearContents
    rngList.Activate

    Set rngList = Nothing
    Set rngWork = Nothing
    Set rngCrit = Nothing

 End Sub

 Private Sub ComboBox1_Enter()

    ComboBox4.ListIndex = -1
    '各コントロールをクリア
    ClearControls

 End Sub

 Private Sub ComboBox1_Click()

    '指示No

    Dim i As Long
    Dim vntData As Variant
    Dim lngRow As Long

    If ComboBox1.ListIndex > -1 Then
        '行選択のデータを取得
        vntData = ExtractID(ComboBox1.Text, lngRow)
        With ComboBox4
            '抽出行数が0で無いなら
            If lngRow > 0 Then
                'ComboBox4にListを設定
                .List = vntData
                .ListIndex = 0
            Else
                'ComboBox4と各コントロールをクリア
                .Clear
                ClearControls
            End If
        End With
    End If

 End Sub

 Private Sub ComboBox2_Click()

    '商品ID

    With ComboBox2
        If .ListIndex > -1 Then
            TextBox6.Text = .List(.ListIndex, 1)
        Else
            TextBox6.Text = ""
        End If
    End With

 End Sub

 Private Sub ComboBox4_Change()

    If ComboBox1.ListIndex > -1 Then
        With ComboBox4
            If .ListIndex > -1 Then
                '各コントロールにデータ読み込み
                GetLitData rngWork.Cells(2, 1).Offset(.ListIndex).Value
            Else
                ClearControls
            End If
        End With
    End If

 End Sub

 Private Sub CommandButton1_Click()

    '更新

    Dim lngRow As Long
    Dim vntData As Variant
    Dim lngIndex As Long
    Dim strPrompt As String

    '行選択の選択位置を取得
    lngIndex = ComboBox4.ListIndex

    '指示Noが選ばれている場合
    If ComboBox1.ListIndex > -1 Then
        '商品IDが選択されている場合
        If lngIndex > -1 Then
            strPrompt = "レコードを更新します"
            If MsgBox(strPrompt, vbQuestion + vbYesNo) = vbYes Then
                '既存のレコードを更新
                lngRow = rngWork.Cells(2, 1).Offset(lngIndex).Value
                PutLitData lngRow, False
            End If
        End If
    End If

    '行選択のデータを取得
    vntData = ExtractID(ComboBox1.Text, lngRow)
    With ComboBox4
        '抽出行数が0で無いなら
        If lngRow > 0 Then
            'ComboBox2にListを設定
            .List = vntData
            'ListIndexを再設定
            .ListIndex = lngIndex
        End If
    End With

 End Sub

 Private Sub CommandButton2_Click()

    '閉じる

    Unload Me

 End Sub

 Private Sub CommandButton3_Click()

    '追加

    Dim lngRow As Long
    Dim vntData As Variant
    Dim lngIndex As Long
    Dim strPrompt As String

    '行選択の選択位置を取得
    lngIndex = ComboBox4.ListIndex

    '指示Noが選ばれている場合
    If ComboBox1.ListIndex > -1 Then
        strPrompt = "新規レコードを追加します"
        '行選択が選択されている場合
        If lngIndex > -1 Then
            If MsgBox(strPrompt, vbQuestion + vbYesNo) = vbYes Then
                'レコードを追加
                lngRow = rngWork.Cells(2, 1).Offset(lngIndex).Value + 1
                rngList.Offset(lngRow).EntireRow.Insert
                PutLitData lngRow, True
                lngIndex = lngIndex + 1
                lngRows = lngRows + 1
            End If
        End If
    Else
        '指示Noと商品IDに入力が在る場合
        If ComboBox1.Text <> "" Then
            strPrompt = "List最終行に新規レコードを追加します"
            If MsgBox(strPrompt, vbQuestion + vbYesNo) = vbYes Then
                'List最終行にレコードを追加
                lngRows = lngRows + 1
                lngIndex = 0
                lngRow = lngRows
                'データを転記
                PutLitData lngRow, True
                '「指示No」を無重複で取得
                vntData = GetNumb
                If Not VarType(vntData) = vbBoolean Then
                    ComboBox1.List = vntData
                End If
            End If
        Else
            Exit Sub
        End If
    End If

    '商品IDのデータを取得
    vntData = ExtractID(ComboBox1.Text, lngRow)
    With ComboBox4
        '抽出行数が0で無いなら
        If lngRow > 0 Then
            'ComboBox2にListを設定
            .List = vntData
            'ListIndexを再設定
            .ListIndex = lngIndex
        End If
    End With

 End Sub

 Private Sub DoFilter(rngScope As Range, _
                    rngCriteria As Range, _
                    rngCopyTo As Range, _
                    Optional blnUnique As Boolean)

 '  AdvancedFilterを実行

    rngScope.AdvancedFilter _
            Action:=xlFilterCopy, _
            CriteriaRange:=rngCriteria, _
            CopyToRange:=rngCopyTo, _
            Unique:=blnUnique

 End Sub

 Private Function GetNumb() As Variant

    Dim i As Long
    Dim lngRow As Long
    Dim vntData As Variant

    '「指示No」を無重複で取得
    DoFilter rngList.Cells(1, 2).Resize(lngRows + 1), _
                rngCrit.Cells(1, 1).Offset(, 1), _
                rngWork.Cells(1, 2), True

    With rngWork.Cells(1, 2)
        '行数の取得
        lngRow = .Offset(Rows.Count - .Row).End(xlUp).Row - .Row
        If lngRows > 0 Then
            vntData = .Offset(1).Resize(lngRow, 2).Value
            For i = 1 To lngRow
                vntData(i, 1) = CStr(vntData(i, 1))
            Next i
            ReDim Preserve vntData(1 To lngRow, 1 To 1)
            GetNumb = vntData
        Else
            GetNumb = False
        End If
    End With

 End Function

 Private Sub GetItemList(cboItems As MSForms.ComboBox)

    Dim i As Long
    Dim j As Long
    Dim lngRow As Long
    Dim vntData As Variant

    '「商品ID」「品名」を無重複で取得
    DoFilter rngList.Cells(1, 7).Resize(lngRows + 1, 2), _
                rngCrit.Cells(1, 1).Offset(, 1), _
                rngWork.Cells(1, 3).Resize(, 2), True

    With rngWork.Cells(1, 3)
        '行数の取得
        lngRow = .Offset(Rows.Count - .Row).End(xlUp).Row - .Row
        If lngRows <= 0 Then
            Exit Sub
        End If
        '商品IDと品名を取得
        vntData = .Offset(1).Resize(lngRow, 2).Value
    End With

    'ComboBoxに商品ID昇順に品名を登録
    With cboItems
        For i = 1 To lngRow
            For j = 0 To .ListCount - 1
                If .List(j, 0) > CStr(vntData(i, 1)) Then
                    Exit For
                End If
            Next j
            If j = .ListCount - 1 Then
                .AddItem CStr(vntData(i, 1)), j
                .List(j, 1) = vntData(i, 2)
            Else
                .AddItem CStr(vntData(i, 1))
                .List(.ListCount - 1, 1) = vntData(i, 2)
            End If
        Next i
    End With

 End Sub

 Private Function ExtractID(vntCrit As Variant, lngRow As Long) As Variant

    Dim i As Long
    Dim vntData As Variant

    '条件範囲にComboBoxの値を代入(式の形で)
    rngCrit.Cells(2, 1).Value = "=""" & vntCrit & """"

    'AdvancedFilterを実行
    DoFilter rngList.Resize(lngRows + 1, clngColumns + 1), rngCrit, rngWork

    '抽出範囲から
    With rngWork.Cells(1, 1)
        '抽出行数を取得
        lngRow = .Offset(Rows.Count - .Row).End(xlUp).Row - .Row
        '列見出し以上の行が在るなら
        If lngRow > 0 Then
            'データを配列に取得
            vntData = .Offset(1).Resize(lngRow, 6).Value
            '「仮番号」を文字列に変換
            For i = 1 To lngRow
                vntData(i, 1) = CStr(vntData(i, 1))
            Next i
            '戻り値として配列で返す
            ExtractID = vntData
        End If
    End With

 End Function

 Private Sub ClearControls()

    TextBox1.Text = "" '開始日
    TextBox2.Text = "" '部署1
    TextBox3.Text = "" '部署2
    TextBox4.Text = "" '部署3
    TextBox5.Text = "" '担当
    ComboBox2.Text = "" '商品ID
    TextBox6.Text = "" '品名
    TextBox7.Text = "" '指示数量
    TextBox8.Text = "" '完成数量
    TextBox9.Text = "" '完了日
    TextBox10.Text = "" '出荷日
    'TextBox11.Text = "" '出荷先
    ComboBox3.Text = "" '出荷先
    TextBox12.Text = "" '出荷数

 End Sub

 Private Sub GetLitData(lngRow As Long)

    '出荷マスタ指定位置因り
    With rngList
        TextBox1.Text = .Offset(lngRow, 0).Value    '開始日
        'ComboBox1.Text = .Offset(lngRow, 1).Value  '指示No 使わない
        TextBox2.Text = .Offset(lngRow, 2).Value    '部署1
        TextBox3.Text = .Offset(lngRow, 3).Value    '部署2
        TextBox4.Text = .Offset(lngRow, 4).Value    '部署3
        TextBox5.Text = .Offset(lngRow, 5).Value    '担当
        ComboBox2.Text = .Offset(lngRow, 6).Value   '商品ID
        TextBox6.Text = .Offset(lngRow, 7).Value    '品名
        TextBox7.Text = .Offset(lngRow, 8).Value    '指示数量
        TextBox8.Text = .Offset(lngRow, 9).Value    '完成数量
        TextBox9.Text = .Offset(lngRow, 14).Value   '完了日
        TextBox10.Text = .Offset(lngRow, 15).Value  '出荷日
        'TextBox11.Text = .Offset(lngRow, 16).Value  '出荷先
        ComboBox3.Text = .Offset(lngRow, 16).Value  '出荷先
        TextBox12.Text = .Offset(lngRow, 17).Value  '出荷数
        ComboBox4.Text = .Offset(lngRow, clngColumns).Value  '★追加 仮番号
        .Offset(lngRow).Resize(, clngColumns).Select '★追加 セル選択
    End With

 End Sub

 Private Sub PutLitData(lngRow As Long, blnNewLine As Boolean)

    '入荷マスタを更新
    With rngList
        .Offset(lngRow, 0).Value = TextBox1.Text    '開始日
        .Offset(lngRow, 1).Value = ComboBox1.Text   '指示No
        .Offset(lngRow, 2).Value = TextBox2.Text    '部署1
        .Offset(lngRow, 3).Value = TextBox3.Text    '部署2
        .Offset(lngRow, 4).Value = TextBox4.Text    '部署3
        .Offset(lngRow, 5).Value = TextBox5.Text    '担当
        .Offset(lngRow, 6).Value = ComboBox2.Text   '商品ID
        .Offset(lngRow, 7).Value = TextBox6.Text    '品名
        .Offset(lngRow, 8).Value = TextBox7.Text    '指示数量
        .Offset(lngRow, 9).Value = TextBox8.Text    '完成数量
        .Offset(lngRow, 14).Value = TextBox9.Text   '完了日
        .Offset(lngRow, 15).Value = TextBox10.Text  '出荷日
        '.Offset(lngRow, 16).Value = TextBox11.Text  '出荷先
        .Offset(lngRow, 16).Value = ComboBox3.Text  '出荷先
        .Offset(lngRow, 17).Value = TextBox12.Text  '出荷数
        '追加の場合
        If blnNewLine Then
            .Offset(lngRow, clngColumns).Formula _
                    = "=Row()-" & rngList.Row        '仮番号
            '転記元レコードからL列〜O列をCopy
            .Offset(lngRow - 1, 10).Resize(, 4).Copy _
                    Destination:=.Offset(lngRow, 10)
        End If
    End With

 End Sub

 (Bun)


 ありがとうございます。

 今試していたのですが、下記の現象についてお教えください。

 あるデータを選択し、完了日などを記入してコマンドボタン1でデータを更新しました。
 そのデータを元に、出荷先を変えたレコードをコマンドボタン3で行を挿入して追加しました。
 しかし追加したデータに入力ミスがあったので、追加したデータを選択してコマンドボタン1でデータを更新しました

 すると、L〜O列のデータが消えてしまいました…

 更新・追加のどちらの場合にもL〜O列に値(計算式も含めて)をセットするような形にしておくべきでしょうか…

 あとこちらでまた変更をしました。
 TextBox4→ComboBox5にしました。

 商品マスターはあります。
 ただ、一つの商品IDに対して複数の名前が存在することがあります。
 (クライアントが一つの商品IDで名前を変えて注文してくることがあるので)

 (ふーさん)

 >あるデータを選択し、完了日などを記入してコマンドボタン1でデータを更新しました。
 >そのデータを元に、出荷先を変えたレコードをコマンドボタン3で行を挿入して追加しました。
 >しかし追加したデータに入力ミスがあったので、追加したデータを選択してコマンドボタン1でデータを更新しました

 >すると、L〜O列のデータが消えてしまいました…
 >
 >更新・追加のどちらの場合にもL〜O列に値(計算式も含めて)をセットするような形にしておくべきでしょうか…

 成らないと思いますが?
 更新なので、選択されているレコードが先頭の場合、直上のレコードの「指示No」が違っている場合が有ります
 この時、その違う「指示No」の「L〜O列に値(計算式も含めて)」をCopyしても善いのか?どうかに因ると思います?

 もし、善いのなら以下をコメントアウトか削除すればCopyして来ますが?

 Private Sub PutLitData(lngRow As Long, blnNewLine As Boolean)

    '入荷マスタを更新
    With rngList
        .Offset(lngRow, 0).Value = TextBox1.Text    '開始日
        .Offset(lngRow, 1).Value = ComboBox1.Text   '指示No
        .Offset(lngRow, 2).Value = TextBox2.Text    '部署1
        .Offset(lngRow, 3).Value = TextBox3.Text    '部署2
        .Offset(lngRow, 4).Value = TextBox4.Text    '部署3
        .Offset(lngRow, 5).Value = TextBox5.Text    '担当
        .Offset(lngRow, 6).Value = ComboBox2.Text   '商品ID
        .Offset(lngRow, 7).Value = TextBox6.Text    '品名
        .Offset(lngRow, 8).Value = TextBox7.Text    '指示数量
        .Offset(lngRow, 9).Value = TextBox8.Text    '完成数量
        .Offset(lngRow, 14).Value = TextBox9.Text   '完了日
        .Offset(lngRow, 15).Value = TextBox10.Text  '出荷日
        '.Offset(lngRow, 16).Value = TextBox11.Text  '出荷先
        .Offset(lngRow, 16).Value = ComboBox3.Text  '出荷先
        .Offset(lngRow, 17).Value = TextBox12.Text  '出荷数
        '追加の場合
  '       If blnNewLine Then                          '★コメントアウト
            .Offset(lngRow, clngColumns).Formula _
                    = "=Row()-" & rngList.Row        '仮番号
            '転記元レコードからL列〜O列をCopy
            .Offset(lngRow - 1, 10).Resize(, 4).Copy _
                    Destination:=.Offset(lngRow, 10)
  '        End If                                      '★コメントアウト
    End With

 End Sub

 >商品マスターはあります。
 >ただ、一つの商品IDに対して複数の名前が存在することがあります。
 >(クライアントが一つの商品IDで名前を変えて注文してくることがあるので)

 此れは、運用の問題でComboBox2に表示する事は問題無いと思います
 ComboBox2は2列表示なので、商品IDを選ぶ際に、商品名も見て選べば善いと思います
  尚、商品IDのマスタからの読み込みの場合、「Private Sub GetItemList」を書き換えなければ成りません

 後、ComboBox2とComboBox4もそうですが?
 Upしたコードでは「ListWidth プロパティ」を設定した方が善かったのですが忘れていました
 「Private Sub UserForm_Initialize()」の中の以下の部分(★印)を変更して下さい

    '商品IDと品名を登録
    GetItemList ComboBox2       '★変更
    With ComboBox2              '★変更
        .ColumnCount = 2        '★変更
        .ListWidth = "144"      '★変更
        .ColumnWidths = "72;72" '★変更
    End With

    '行選択用ComboBoxの設定
    With ComboBox4
        .ColumnCount = 6
        .ListWidth = "360"      '★変更
        .ColumnWidths = "72;0;72;72;72;72"
    End With

 尚、「ListWidth プロパティ」の値と「.ColumnWidths」の値は実情に合わせて変更して下さい

 (Bun)


 書き忘れましたが?
 此れ、最後にUpしたコード(マクロ)の方ですよね?

 (Bun)


 あれ、今試したら再発しませんでした…(L〜O列が消える)
 さっきは確かに消えていたのによく分かりません…

 >此れ、最後にUpしたコード(マクロ)の方ですよね?
 はいそうです。

 あと、以前のコードの

 Private Sub ComboBox2_Exit(ByVal Cancel As MSForms.ReturnBoolean)

 この部分は不要なのでしょうか。

 (ふーさん)

 >あれ、今試したら再発しませんでした…(L〜O列が消える)
 >さっきは確かに消えていたのによく分かりません…

 コード的にはあり得ないと思いますが?
 此方でのTestでは、この現象は出ていませんので?

 >あと、以前のコードの
 >
 >Private Sub ComboBox2_Exit(ByVal Cancel As MSForms.ReturnBoolean)
 >
 >この部分は不要なのでしょうか。

 最後のコードの方では、ComboBox2は商品IDの入力と、TextBox6の品名の入力だけを荷っているので
 不必要です
 その代わり、以前のComboBox2の機能をComboBox4で行っています
 因って、ComboBox4のタブオーダーをComboBox1(指示No)の次にしては方が使い善いよ思います?

 (Bun)


 ありがとうございます。

 何度もすみません。

 ComboBox1、ComboBox4以外でこちらで追加したコンボボックスですが、ユーザーフォームを表示した時点では
 プルダウンでリストの先頭にカーソルが来ているのですが、ComboBox1でデータを呼び出した後、ComboBox3やComboBox5を
 見るとリストの最下行にカーソルが行ってしまいます。
 コンボボックスのプロパティで、TabIndexは0にしています。
 これは何故こうなるのかお教えいただけませんでしょうか?

 (ふーさん)

 >ComboBox1、ComboBox4以外でこちらで追加したコンボボックスですが、ユーザーフォームを表示した時点では
 >プルダウンでリストの先頭にカーソルが来ているのですが、ComboBox1でデータを呼び出した後、ComboBox3やComboBox5を
 >見るとリストの最下行にカーソルが行ってしまいます。

 ComboBox3やComboBox5に対し何かコードを書いているなら(例えば、「Private Sub ComboBox3_Change()」の様な?)
 其れにも因るので、其れを見なければ解りませんが?
 書いて無いとすれば、常に!!最下行が選択される事は無いと思います?
 何故なら、

 Private Sub GetLitData(lngRow As Long)

    '出荷マスタ指定位置因り
    With rngList
        TextBox1.Text = .Offset(lngRow, 0).Value    '開始日
        'ComboBox1.Text = .Offset(lngRow, 1).Value  '指示No 使わない
        TextBox2.Text = .Offset(lngRow, 2).Value    '部署1
        TextBox3.Text = .Offset(lngRow, 3).Value    '部署2
        'TextBox4.Text = .Offset(lngRow, 4).Value    '部署3
        ComboBox5.Text = .Offset(lngRow, 4).Value  '部署3
        TextBox5.Text = .Offset(lngRow, 5).Value    '担当
        ComboBox2.Text = .Offset(lngRow, 6).Value   '商品ID
        TextBox6.Text = .Offset(lngRow, 7).Value    '品名
        TextBox7.Text = .Offset(lngRow, 8).Value    '指示数量
        TextBox8.Text = .Offset(lngRow, 9).Value    '完成数量
        TextBox9.Text = .Offset(lngRow, 14).Value   '完了日
        TextBox10.Text = .Offset(lngRow, 15).Value  '出荷日
        'TextBox11.Text = .Offset(lngRow, 16).Value  '出荷先
        ComboBox3.Text = .Offset(lngRow, 16).Value  '出荷先
        TextBox12.Text = .Offset(lngRow, 17).Value  '出荷数
        ComboBox4.Text = .Offset(lngRow, clngColumns).Value  '★追加 仮番号
        .Offset(lngRow).Resize(, clngColumns).Select '★追加 セル選択
    End With

 End Sub

 の所でComboBox3やComboBox5に値を代入していますので、ComboBox3やComboBox5のListに値が有れば
 其の位置が選択されます

 >コンボボックスのプロパティで、TabIndexは0にしています。
 >これは何故こうなるのかお教えいただけませんでしょうか?

 此れも何か変ですよ?
 TabIndexプロパティは、確か排他処理されると思いますので2つに0は入れられないと思います
 また、TabIndexを0にすれば、そのコントロールが最初にフォーカスを得る事に成り入力順を狂わせてしまうのでは?
 尚、フォーカスを持たせない様にするならTabStopプロパティをFalseにします
 タブオーダーを変更するなら、直接TabIndexの値を変更しても善いのですが?
 VBEのデザイン画面で、変更するUserFormを選択して「表示」→「タブオーダー」でダイアログがでます
 此処で、タブオーダーを変更した方が簡単だと思います(ダイアログに表示された上から順にフオーカスが当たる)

 尚、今回のコードでは、タブオーダーがComboBox1が先頭、次にComboBox4とした方が使い勝手が善いと思います

 (Bun)


 ありがとうございます。

 タブオーダーは順番通りにしました。

 しかし、.ListIndex などを設定してもやはりコンボボックスの初期値がリストの最下行になります。
 試しにコンボボックスのリストを取得しているマスターシートを、

 見出し
 [空白]
 データ1
 データ2
  :

 のように最初に空白セルを置いたらリストの一番上を参照するようになりました。

 不思議なのはこのマスターシートは他のユーザーフォームでも参照しているのですが、そちらではこのような現象は起きないんです

 でもとりあえず現象が解決したので助かりました。

 ありがとうございました。

 (ふーさん)

コメント返信:

[ 一覧(最新更新順) ]


YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki. Modified by kazu.