Excel (VBA)

Excel VBAに関するフォーラムです。
  • 解決済みのトピックにはコメントできません。
このトピックは解決済みです。
質問

 
(Windows 7 Home Premium : Excel 2010)
ListBoxの項目名の修正
投稿日時: 20/02/26 18:31:08
投稿者: shimoichimabu

例えば、UserFormのListBoxの2行目の項目名(”B”)を ”ABC”に変更する場合、
通常、以下のプログラムで書かれています。
修正する項目名の行を削除し、修正したい新たな行を追加する2段階方式となっています。
そこで、VBAではもっと簡単に直接、修正したいListBoxの行を編集するコマンドはないでしようか?
 
Sub Macro2()
 
  With UserForm.ListBox
     .AddItem "A"
     .AddItem "B" ← 修正したい項目名。マウスで選択
     .AddItem "C"
  End With
 
  UserForm.Show
 
End Sub
 
--------------------------------------------------------------------
Private Sub OKButton_Click() ’UserForm上のOKボタンを押す
  修正用UserForm.Show  ’ここの修正用TextBox内に修正内容を書き込む
End Sub
 
--------------------------------------------------------------------
Private Sub OKButton_Click()  ’修正用UserForm上のOKボタンを押す
 
  With UserForm.ListBox
      項目番号 = .ListIndex
      .RemoveItem 項目番号
      .AddItem 修正用TextBox.Value, 項目番号
      .ListIndex = 項目番号
  End With
   
  Unload Me
 
End Sub

回答
投稿日時: 20/02/26 19:23:35
投稿者: sk

引用:
UserFormのListBoxの2行目の項目名(”B”)を ”ABC”に変更する

引用:
With UserForm.ListBox
   .AddItem "A"
   .AddItem "B" ← 修正したい項目名。マウスで選択
   .AddItem "C"
End With

引用:
With UserForm.ListBox
    項目番号 = .ListIndex
    .RemoveItem 項目番号
    .AddItem 修正用TextBox.Value, 項目番号
    .ListIndex = 項目番号
End With

With UserForm.ListBox
    If .ListIndex < 0 Then
        Exit Sub
    End If
    .List(.ListIndex, 0) = 修正用TextBox.Value
End With
 
-------------------------------------------------------------------
 
以上のように List プロパティを使用なさればよろしいかと。

投稿日時: 20/02/27 00:02:34
投稿者: shimoichimabu

sk さん回答ありがとうございます。
 
シンプルにスマートにできるのですね。
うまく、動作しました。
 
skさんのコードをヒントにさせてもらうと、
 
 .List(.ListIndex, 0) = 修正用TextBox.Value
      ↓
 .Column(0) = 修正用TextBox.Value
 
でもできましたが、これだと何か不都合が生じることがあるのでしようか?

回答
投稿日時: 20/02/27 05:34:40
投稿者: simple

> .Column(0) = 修正用TextBox.Value
> でもできました

そんなはずないと思います。
単なる記述ミスかと思いますが、
.Column(0, .ListIndex) = 修正用TextBox.Value
でしょうね。
 
.Column( column, row )は、.List(row, column) とパラレルに使えるはずです。
 
ちなみに、Columnのメリットは以下です。
・データは、行が増加する方向に持つことが多い、
・動的配列で要素を追加できるのは、最後の次元方向しか認められていない、
という二点を考えると、
動的配列を直接 .Column() に入力できるというメリットがあります。

回答
投稿日時: 20/02/27 09:30:26
投稿者: sk

shimoichimabu さんの引用:

.Column(0) = 修正用TextBox.Value
  
でもできましたが、これだと何か不都合が生じることがあるのでしようか?

件の目的を達成する分については特に問題ないと思います。
 
simple さんの引用:
.Column(0, .ListIndex) = 修正用TextBox.Value
でしょうね。

Column プロパティの第 2 引数 row は省略可能ですので、
この場合はどちらでもよいでしょう。
( List プロパティの場合は、第 1 引数 row も 第 2 引数 column も指定が必須)

回答
投稿日時: 20/02/27 09:46:10
投稿者: takesi

視点を変えて、マウス移動距離短くするのは?
ListBoxの選択した行の横にボタンとテキストボックスを持ってくる。
 

Private Sub CommandButton1_Click()

With UserForm1.ListBox1
    If .ListIndex < 0 Then
        Exit Sub
    End If
    .List(.ListIndex, 0) = TextBox1.Value
End With

TextBox1.Visible = False
CommandButton1.Visible = False

End Sub

Private Sub ListBox1_DblClick(ByVal Cancel As MSForms.ReturnBoolean)
Dim BoxOffset As Integer
BoxOffset = 5

With UserForm1.ListBox1
    
    CommandButton1.Top = .Top + (.ListIndex - .TopIndex) * .Font.Size - BoxOffset * 0.5
    CommandButton1.Height = .Font.Size * 1.5 + BoxOffset * 1.5
    CommandButton1.Left = .Left + .Width
    CommandButton1.Width = .Font.Size * 1.5
    
    TextBox1.Top = CommandButton1.Top
    TextBox1.Height = CommandButton1.Height
    TextBox1.Left = CommandButton1.Left + CommandButton1.Width
    TextBox1.Width = .Width + UfomOffset * 2
    
    If .ListIndex < 0 Then
        Exit Sub
    End If
    TextBox1.Value = .List(.ListIndex, 0)
    
    TextBox1.Visible = True
    CommandButton1.Visible = True
End With

End Sub

回答
投稿日時: 20/02/27 11:16:30
投稿者: simple

あ、そうでしたか、それは不勉強で失礼しました。

回答
投稿日時: 20/02/27 16:13:43
投稿者: mokutachi

    MsgBox Me.ListBox1.List(, 1)
    MsgBox Me.ListBox1.List(Me.ListBox1.ListIndex, 1)
 
ListプロパティもIndex側は書かなくても同じ動作っぽいです。

回答
投稿日時: 20/02/27 17:58:30
投稿者: sk

mokutachi さんの引用:
MsgBox Me.ListBox1.List(, 1)

mokutachi さんの引用:
ListプロパティもIndex側は書かなくても同じ動作っぽいです。

リストの要素の値を参照するだけなら問題ないですが、
その要素の値を書き換える場合は引数 row の指定が必要です。

投稿日時: 20/02/27 22:56:59
投稿者: shimoichimabu

沢山の回答ありがとうございます。
 
色々、勉強になります。
 
.Column(0) = 修正用TextBox.Value で気が付いたことですが、
 
上記でOKなのはListBoxのMultiSelectが単一行選択可の場合は、↑でOKでしたが、
複数行選択可能な設定にして、1行のみ選択していてもsimpleさんがおっしゃるように、
.Column(0,ListIndex) = 修正用TextBox.Value にしないと、エラーが出ます。
当然と言われるかもしれませんが、ややこしいですね。
結局、MultiSelectを無関係に実行しようと思えば、.Column(0,ListIndex)にしておけば、
万全ということでしようか? エラーが出ない。
 

回答
投稿日時: 20/02/28 09:57:33
投稿者: sk

引用:
結局、MultiSelectを無関係に実行しようと思えば、.Column(0,ListIndex)にしておけば、
万全ということでしようか?

MultiSelect プロパティを fmMultiSelectSingle 以外の値に設定されている場合、
そのリストボックスの ListIndex プロパティは
どの行が選択されているかにかかわらず
フォーカスがある行のインデックスを返しますので、
( List プロパティにせよ Column プロパティにせよ)
ListIndex プロパティの値を引数 row に渡すのは適切ではありません。
 
今回の件だと「選択された全ての行」が編集対象となるはずですので、
ListIndex プロパティではなく Selected プロパティを使用して
各行の選択状態を判定して下さい。
 
-------------------------------------------------------------
 
Dim i As Long
 
With UserForm.ListBox
    For i = 0 To .ListCount - 1
        If .Selected(i) Then
            .List(i, 0) = 修正用TextBox.Value
        End If
    Next
End With
 
-------------------------------------------------------------

投稿日時: 20/02/28 18:23:10
投稿者: shimoichimabu

skさん回答ありがとうございます。
 
>「選択された全ての行」が編集対象となるはずですので、
>ListIndex プロパティではなく Selected プロパティを使用して
>各行の選択状態を判定して下さい。
確かにこの場合は、.Selected(i)で対処しなければなりませんね。