[[20170105105520]] 『テキストボックス連動について』(真由美) ページの最後に飛ぶ

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

 

『テキストボックス連動について』(真由美)

いつも大変お世話になっております
教えて頂けたら幸いです

下記の様にComboBox3にTextboxを紐つけていますが
新規入力の場合 textboxを空白にする方法を教えて下さい
現在は タイトル行が表示されてしまいます

お手数ですが宜しくお願いいたします

Private Sub ComboBox3_Change()

Dim 行

    行 = ComboBox3.ListIndex + 1
    TextBox6.Text = Worksheets("LIST").Cells(行 + 1, 3)
    TextBox7.Text = Worksheets("LIST").Cells(行 + 1, 2)

End Sub

< 使用 Excel:Excel2010、使用 OS:Windows7 >


textbox6.text=""ですか
(HARA) 2017/01/05(木) 11:45

HARA様
教えていただいて有難う御座います
教えていただいたように書いてしまうと

ComboBoxの利便性が消えてしまいます

ComboBoxをlistboxのように普段は使用しています
リストに無いものをわざわざ リストに追加しなくても
良い様にComboBoxを使用していますので

リスト選択で無い場合
キーボード使用による新規に入力の場合に
紐つくtextboxを空白にしたいのです

(真由美) 2017/01/05(木) 11:59


 新規入力 ということは、コンボボックスのリストからの選択ではなく、ボックスに手入力ということですね。

 Changeイベントを使う問題点は後回しにして

 ComboBox3.LisnIndex が < 0 (0未満、実際には-1) の場合はリストにないということで
 TextBox の値を "" にしてやればいいと思います。

 で、結果オーライですけど、Changeイベントの注意点を。

 たとえばリストが aaaa と abcd の2件だったとして、リストから選ばずにボックス内に入力する場合、
 a とタイプすると、プロパティ設定が規定値であれば、ボックス内は aaaa が選ばれたことになります。
 ListIndex は 0 、Value は aaaa。

 次に a のあとに b をタイプすると、ボックス内は abcd が選ばれた状態で、ListIndexが1、Valueは abcd。

 結果オーライなんですが、1文字タイプのたびにイベントが発生します。

 このボックスに xyz をいれたとします。

 x で発生。ListIndex は -1。続いて、y。Value が xy で発生。ListIndex は -1。さらに z。Valueがxyzで発生。
 ListIndex は -1。

 繰り返しますが、今回のテーマでは『結果オーライ』です。
 でも、ユーザーフォームの TextBox や ComboBox では 1文字タイプごとに Changeイベントが発生します。

 このことは、ロジックによっては、重大な不具合の原因になる可能性があります。
 十分注意して使うとともに、できれば Changeイベントではなく AfterUpdate や BeforeUpdate という
 Exit系のイベントを使うことをおすすめします。

(β) 2017/01/05(木) 12:10


 >ComboBoxの利便性が消えてしまいます 

あれ?じゃぁなんでテキストボックスとコンボボックスを連動させるなんてめんどくさい
ことやってるんですか?

コンボボックスの機能だけで間に合いませんか?

まぁ、いまのままでいくなら、
手入力時に、

ComboBox3.ListIndex
が何を返すかによってIf文で条件分岐したらいいのですが、
コンボボックスに必要な列数を表示するだけで、
十分用が足りると思いますが。。。。

(まっつわん) 2017/01/05(木) 12:37


 失礼します。

 >>コンボボックスに必要な列数を表示するだけで、 
 >>十分用が足りると思いますが。。。。 

 確かにドロップダウンリストには表示されていますけど、別コントロールに移ると
 これらが何であったか、見えなくなりますね。

 なので、操作者に対する利便性ということもあるんだろうと思いますよ。
 βであれば、そういった場合は、TextBox ではなく Label に表示しますけど。

 ただ、まっつわんさんの提言は、重要ですね。リスト内に格納しておけば、シート上のセルからの抽出ではなく
 リスト内の値参照で可能ですから。微々たる差とはいえ、メモリー内参照とオブジェクト参照の効率の差異は
 ありますね。

(β) 2017/01/05(木) 12:45


β様
コメント有難う御座います

 >十分注意して使うとともに、できれば Changeイベントではなく AfterUpdate や BeforeUpdate という
 Exit系のイベントを使うことをおすすめします。

次の所にカーソルを持って行かないと イベントが発生しないって
文句言われて 致し方なく Changeイベントで逃げています

 >ComboBox3.LisnIndex が < 0 (0未満、実際には-1) の場合はリストにないということで
 TextBox の値を "" にしてやればいいと思います。  

IF条件で頑張って作ってみます

>TextBox ではなく Label に表示しますけど。
labelだと直接入力が出来なくなりますから 無理だと思います
ただ表示させるだけでなく 別シートに転記させてます

まっつわん様
コメント有難う御座います

>テキストボックスとコンボボックスを連動させるなんてめんどくさい
ことやってるんですか?

製品名             製品コード   ロッド
カットレタス ( 6入り)   3292416   6
ケールサラダ(4入り)       3932560   4
千切りキャベツ (12入り)   3943109   12

このようなリストで 製品名をCombBoxに割り当てています
リストも100以上あるのですけどね
その時に 製造コード ロッドをtextboxに表示させています
新製品等が出れば当然リストにはありません
そのためのリスト更新を行ってくれる担当者もいない為
新規入力が絶対不可欠で 又リスト更新の役割
又 入力ミスを防ぐ為の連動を取っています

IFに関しては有難う御座います
考えてみます

皆様本当に有難う御座います
出来なかったら もう一度質問させていただきます
今後とも宜しくお願いいたします

(真由美) 2017/01/05(木) 13:41


最終的には下記のような処理をしています
リストの更新及び 報告書の作成

笑われそうな 駄作ですけど

Private Sub CommandButton1_Click()
If Me.ComboBox3.Value = "" Then

 MsgBox "製品名が未記入", 16
 Me.ComboBox3.SetFocus
 Exit Sub
 End If
If Me.ComboBox6.Value = "" Then
 MsgBox "ケース数が未記入", 16
 Me.ComboBox6.SetFocus
 Exit Sub
  End If
 If Me.ComboBox7.Value = "" Then
 MsgBox "端数が未記入", 16
 Me.ComboBox7.SetFocus
 Exit Sub
  End If
 If Me.ComboBox1.Value = "" Then
 MsgBox "製造工場が未記入", 16
 Me.ComboBox1.SetFocus
 Exit Sub
  End If
 If Me.ComboBox2.Value = "" Then
 MsgBox "移管先が未記入", 16
 Me.ComboBox2.SetFocus
 Exit Sub
 End If
 If Me.ComboBox5.Value = "" Then
 MsgBox "移管理由が未記入", 16
 Me.ComboBox5.SetFocus
 Exit Sub
 End If

Dim intRow, i, k, kl, kk, km
With Worksheets("報告書")
.Range("B3") = Format(TextBox3.Text, "≪YYYY年 M月分≫")

 End With
With Sheets("報告書")
 intRow = .Cells(Rows.Count, "I").End(xlUp).Row
 i = 1
            .Range("A" & i + intRow) = TextBox8.Text
            .Range("F" & i + intRow) = ComboBox3.Text
            .Range("E" & i + intRow) = TextBox7.Text
            .Range("B" & i + intRow) = ComboBox1.Text
            .Range("C" & i + intRow) = ComboBox2.Text
            .Range("D" & i + intRow) = TextBox1.Text
            .Range("G" & i + intRow) = ComboBox6.Text
            .Range("I" & i + intRow) = TextBox5.Text
            .Range("J" & i + intRow) = ComboBox5.Text
            .Range("H" & i + intRow) = ComboBox7.Text
    End With

With Worksheets("LIST")

    intRow = .Cells(Rows.Count, "F").End(xlUp).Row
    k = 1
    .Range("F" & k + intRow) = ComboBox5.Text
.Range("$F$1:$F$100").RemoveDuplicates Columns:=1, Header:=xlYes
 End With

With Worksheets("LIST")

    intRow = .Cells(Rows.Count, "B").End(xlUp).Row
    kl = 1
    .Range("B" & k + intRow) = TextBox7.Text
    .Range("A" & k + intRow) = ComboBox3.Text
    .Range("C" & k + intRow) = TextBox6.Text

.Range("A:C").RemoveDuplicates Columns:=Array(2), Header:=xlYes

 End With

 With Worksheets("LIST")
    intRow = .Cells(Rows.Count, "D").End(xlUp).Row
    kk = 1
    .Range("D" & kk + intRow) = ComboBox1.Text
.Range("$D$1:$D$100").RemoveDuplicates Columns:=1, Header:=xlYes
 End With

 With Worksheets("LIST")
    intRow = .Cells(Rows.Count, "D").End(xlUp).Row
    km = 1
    .Range("D" & kk + intRow) = ComboBox2.Text
.Range("$D$1:$D$100").RemoveDuplicates Columns:=1, Header:=xlYes
 End With

 Call リスト並び替え

    Dim r As Range
    Set r = Worksheets("LIST").Range("D2:D1000")
    ComboBox1.List = r.Value
    ComboBox2.List = r.Value
    ComboBox3.List = r.Offset(0, -3).Value
    ComboBox5.List = r.Offset(0, 2).Value
     ComboBox6.List = r.Offset(1, 4).Value
     ComboBox7.List = r.Offset(0, 4).Value
      ComboBox7.ListIndex = 0

      ComboBox3.Text = ""
 TextBox7.Text = ""
 TextBox6.Text = ""
 TextBox5.Text = ""
 ComboBox6.Text = ""
 ComboBox1.Text = ""
ComboBox2.Text = ""
ComboBox5.Text = ""
ComboBox7.Text = 0

Sheets("報告書").Select

End Sub
(真由美) 2017/01/05(木) 13:57


 >>次の所にカーソルを持って行かないと イベントが発生しないって 
 >>文句言われて 致し方なく Changeイベントで逃げています 

 そうなんですよね。いくら仕組みが云々といっても、特にComboBoxの場合は、操作者はリストから選択する場合が
 ほとんどですから、「ちゃんと選んでいるじゃないか!!」とクレームが入りますよね。

 なので、COmboBoxの場合は「十分に配慮したコード記述」を行うということが必要でしょうね。
 その最大のポイントは Changeイベントの最初に ListIndex が 0以上か未満かを判定することでしょうね。

 >>labelだと直接入力が出来なくなりますから 無理だと思います 
 >>ただ表示させるだけでなく 別シートに転記させてます 

 そういう要件であれば、もちろん TextBoxですね。

(β) 2017/01/05(木) 14:20


>新規入力が絶対不可欠で 又リスト更新の役割
なるほど。
リストを見るだけでなく更新も出来るようにしたいということなのですね^^
まぁ、やり方はさまざまありますが、一例を。。。

Option Explicit

Dim mEFlag As Boolean

Private Sub UserForm_Initialize()

    Dim rngList As Range

    With Worksheets("LIST").Range("A1").CurrentRegion
        Set rngList = Intersect(.Cells, .Offset(1))
    End With

    With Me.ComboBox1
        .RowSource = rngList.Address(, , , True)
        .ColumnCount = 1
        .ColumnWidths = "100"
        .ColumnHeads = False
    End With
End Sub

Private Sub ComboBox1_Change()

    Dim ix As Long
    Dim rngRow As Range

    If mEFlag = True Then Exit Sub

    ix = Me.ComboBox1.ListIndex
    With Application.Range(Me.ComboBox1.RowSource)

    If ix >= 0 Then
        Set rngRow = .Rows(ix + 1)
    Else
        Set rngRow = .Rows(.Rows.Count + 1)
    End If
    End With
    With rngRow
        Me.TextBox1.Text = .Cells(2).Value
        Me.TextBox1.Tag = .Cells(2).Address(, , , True)
        Me.TextBox2.Text = .Cells(3).Value
        Me.TextBox2.Tag = .Cells(3).Address(, , , True)
        Me.ComboBox1.Tag = .Cells(1).Address(, , , True)
    End With
End Sub

'登録ボタン押下
Private Sub CommandButton1_Click()

    mEFlag = True
    With Me.TextBox1
        Application.Range(.Tag).Value = .Text
    End With
    With Me.TextBox2
        Application.Range(.Tag).Value = .Text
    End With
    With Me.ComboBox1
        Application.Range(.Tag).Value = .Text
        .RowSource = Application.Range(.Tag).CurrentRegion.Address(, , , True)
    End With
    mEFlag = False
End Sub

おっと、並び替えも要るのか。。。
製品コードでいいのかな。。。
ちょっとテストしてみよ^^

(まっつわん) 2017/01/05(木) 15:05


β様

ご賛同有難う御座います

まっつわん様

いたせりつくせり状態でないと
私の体がいくつあっても足りません
笑い

コードまで有難う御座います
試してみて 使えるところは使わせていただきます
(真由美) 2017/01/05(木) 15:13


'登録ボタン押下
Private Sub CommandButton1_Click()
    mEFlag = True
    With Me.TextBox1
        Application.Range(.Tag).Value = .Text
        .Text = ""
        .Tag = ""
    End With
    With Me.TextBox2
        Application.Range(.Tag).Value = .Text
        .Text = ""
        .Tag = ""
    End With
    With Me.ComboBox1
        Application.Range(.Tag).Value = .Text
        .Text = ""
        .Tag = ""
        .ListIndex = -1
    End With
    With Application.Range(Me.ComboBox1.RowSource).CurrentRegion
        With Intersect(.Cells, .Offset(1))
            Me.ComboBox1.RowSource = .Address(, , , True)
            .Sort key1:=.Cells(2), Order1:=xlAscending, Header:=xlNo
        End With
    End With
    mEFlag = False
End Sub

>私の体がいくつあっても足りません
あぁ、調べながらだとそうなりますね。
まぁ、僕も調べながら書いてるのですが、
だいたいの構造っていうか、なんとなくある程度は覚えてないと、
調べるのがつらいかもですね。

コンボボックスに値をセットする方法も3つあるので、
RowSource
List
Add
みたいなのがあったよな〜。。。
というのは何回かやっぱ作ってみないと覚えないのかなぁとは思います。
RowSouceでセットすると、シート上の変更がそのまま反映されるようですね^^
並べ替えしたいときは便利そうです^^

アドレスをTagプロパティに記録しておいて利用してますが、
コンボボックスのListIndexがいつでも利用可能ですので、
無駄なことをしてます^^;

(まっつわん) 2017/01/05(木) 15:37


まっつわん様

有難う御座います
>RowSouceでセットすると、シート上の変更がそのまま反映されるようですね^^

って事は 毎回セットしなくてもいい

下記は不要ってことになりますね 毎回セットしてましたから   
チャレンジしてみます

  Dim r As Range
    Set r = Worksheets("LIST").Range("D2:D1000")
    ComboBox1.List = r.Value
    ComboBox2.List = r.Value
    ComboBox3.List = r.Offset(0, -3).Value
    ComboBox5.List = r.Offset(0, 2).Value
     ComboBox6.List = r.Offset(1, 4).Value
     ComboBox7.List = r.Offset(0, 4).Value
      ComboBox7.ListIndex = 0

本当に勉強になります
有難う御座います
(真由美) 2017/01/05(木) 15:55


 コード拝見。

 いくつか気になる点

 ・最後の、各ComboBoxにリストを再セットしているところですが、ComboBox7 が H2 からの H列、ComboBox6 が H3 からのH列。
 つまり、ComboBox6には H2 がリストにはセットされないのですが、これでいいのでしょうか?
 ちょっと不自然な感じがします。

 ・上記も含めて、シートのレイアウトというか実態が見えないのですが、報告書シートには、最終行の次の同じ1行にセット。
 一方、Listシートには、A:C列、D列、F列 それぞれ、別ものとして、それぞれの列の最終セルの次にセットした上で
 重複を削除していますね。
 まぁ、そういった性格のシートなんでしょうね。

 ・各ComboBox へのリストセットは Initialize でもあると思いますけど、アップされたコードの最後のものと
 共通サブルーティン化することもできますかね。

 と、まぁ見えないところもありますけど、コード記述の一例として、報告書シートと Listシートに転記する部分のみ。
 (17:00 ちょこっと変更)

    With Sheets("報告書")
        .Range("B3") = Format(TextBox3.Text, "≪YYYY年 M月分≫")
        With Cells(Rows.Count, "I").End(xlUp).Offset(1).EntireRow
            .Range("A1:J1").Value = Array(TextBox8.Text, ComboBox1.Text, ComboBox2.Text, TextBox1.Text, TextBox7.Text, _
                                          ComboBox3.Text, ComboBox6.Text, ComboBox7.Text, TextBox5.Text, ComboBox5.Text)
        End With
    End With

    With Worksheets("LIST")
        .Cells(Rows.Count, "F").End(xlUp).Offset(1).Value = ComboBox5.Text
        .Cells(Rows.Count, "B").End(xlUp).Offset(1).EntireRow.Range("A1:C1").Value = Array(ComboBox3.Text, TextBox7.Text, TextBox6.Text)
        With .Cells(Rows.Count, "D").End(xlUp)
            .Offset(1).Value = ComboBox1.Text
            .Offset(2).Value = ComboBox2.Text
        End With
        .Range("F1", .Range("F" & Rows.Count).End(xlUp)).RemoveDuplicates Columns:=1, Header:=xlYes
        .Range("B1", .Range("B" & Rows.Count).End(xlUp)).EntireRow.Columns("A:C").RemoveDuplicates Columns:=Array(2), Header:=xlYes
        .Range("D1", .Range("D" & Rows.Count).End(xlUp)).RemoveDuplicates Columns:=1, Header:=xlYes
    End With

(β) 2017/01/05(木) 16:06


β様
本当に有難う御座います

>・最後の、各ComboBoxにリストを再セットしているところですが、ComboBox7 が H2 からの H列、ComboBox6 が H3 からのH列。
 つまり、ComboBox6には H2 がリストにはセットされないのですが、これでいいのでしょうか?
 ちょっと不自然な感じがします。

気がつきませんでした (;゚д゚)ァ....

 
>・上記も含めて、シートのレイアウトというか実態が見えないのですが、報告書シートには、最終行の次の同じ1行にセット。
 一方、Listシートには、A:C列、D列、F列 それぞれ、別ものとして、それぞれの列の最終セルの次にセットした上で
 重複を削除していますね。
 まぁ、そういった性格のシートなんでしょうね。

リストの下のほうにあっても 直接入力してしまう方がいらっしゃるので
とりあえず 保険的にです

> ・各ComboBox へのリストセットは Initialize でもあると思いますけど、アップされたコードの最後のものと
 共通サブルーティン化することもできますかね。

一行入力した後 新規書き込みの場合 一度開きなおさないと リストに反映されない為
2行目以降にも同じものを使う可能性がある為
毎回リストを読み込ませる って感じの素人的発想です

こんな短いコードまで 有難う御座います

あくまでも  このファイルは テンプレートとして使用してまして
他の名前でで保存して終了みたいな感じです

Private Sub CommandButton2_Click()

 On Error Resume Next
 If Sheets("報告書").Range("B6") = "" Then
   MsgBox "データ未入力です", 16
  Exit Sub

 Else
 Dim Target
    Sheets("報告書").Select
    Cells.Select
    Selection.Copy
    Sheets.Add After:=Sheets(Sheets.Count)
    ActiveSheet.Paste

     Range("D6").Select
    Selection.Copy
    Range("I1").Select
    Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
        :=False, Transpose:=False
     Range("i1").NumberFormatLocal = "yyyymmdd"
    ActiveSheet.Name = Range("i1").Text

 Dim TargetPath As String
Dim myFname As String
Application.ScreenUpdating = False
Application.DisplayAlerts = False

TargetPath = ThisWorkbook.Path
ActiveWorkbook.SaveAs TargetPath & "\" & _

   Range("i1").Text & Range("B6").Text & Range("C6").Text

    With Application
        .DisplayAlerts = False
        Sheets("LIST").Delete
        Sheets("報告書").Delete
        .DisplayAlerts = True
    End With
   ActiveWorkbook.Save
  ActiveWorkbook.Close
  End If
End Sub

(真由美) 2017/01/05(木) 17:22


>あくまでも  このファイルは テンプレートとして使用してまして
>他の名前でで保存して終了みたいな感じです
添削してほしいってことなのかな?

Private Sub CommandButton2_Click()

    Dim wb As Workbook
    Dim sName As String

    If Sheets("報告書").Range("B6").Value = "" Then
        MsgBox "データ未入力です", vbCritical
        Exit Sub
    Else
        Sheets("報告書").Copy
        Set wb = Workbooks(Workbooks.Count)
        With wb.Sheets(1)
            sName = Format(.Range("D6").Value, "yyyymmdd")
            .Range("I1").Value = sName
            .Name = sName
            wb.Close TargetPath & "\" & sName _
                     & .Range("B6").Text & .Range("C6").Text
            Set wb = Nothing
        End With
    End If
End Sub
(まっつわん) 2017/01/05(木) 19:49

まっつわん様
おはよう御座います

たぶん突っ込みどころ満載かなって思って

あげてみました
本当に今回勉強になりました

有難う御座います
今後ともども宜しくお願いいたします
(真由美) 2017/01/06(金) 08:59


コメント返信:

[ 一覧(最新更新順) ]


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