如何在listBox中上下移动项目访问VBA?

时间:2014-05-21 13:49:34

标签: vba access-vba ms-access-2010

我有一个包含10次的列表框。我有向上和向下按钮来上下移动项目。仅当我将listbox multiselect属性设置为“无”时,我的VBA才有效。对于multiselect = simple选项,它会抛出错误,就像在这行代码中有效使用null一样

     sText = lbfNames.Column(0, iIndex)

我的VBA

    Private Sub cmdUP_Click() 
    Dim sText As String
       Dim iIndex As Integer
       iIndex = lbfNames.ListIndex
       'check: only proceed if there is a selected item
       If lbfNames.ListCount > 1 Then
         'index 0 is top item which can't be moved up!
        If iIndex <= 0 Then
            MsgBox ("Can not move the item up any higher.")
            Exit Sub
        End If
        ' If iIndex = -1 Or lbfNames.ListCount > 1 Then
        'save items text and items indexvalue
        sText = lbfNames.Column(0, iIndex)
        lbfNames.RemoveItem iIndex
        'place item back on new position
        lbfNames.AddItem sText, iIndex - 1
        'if you keep that item selected
        'you can keep moving it by pressing cmdUp
        lbfNames.Selected(iIndex - 1) = True
        iIndex = iIndex - 1
   End If
   End sub

我试图将下面的C#代码(在stackoverflow中找到)转换为Access VBA抛出错误。找不到某些数据成员。

     public void MoveUp()
 {
     MoveItem(-1);
 }

 public void MoveDown()
 {
    MoveItem(1);
 }

 public void MoveItem(int direction)
 {
    // Checking selected item
    if (listBox1.SelectedItem == null || listBox1.SelectedIndex < 0)
        return; // No selected item - nothing to do

    // Calculate new index using move direction
    int newIndex = listBox1.SelectedIndex + direction;

    // Checking bounds of the range
    if (newIndex < 0 || newIndex >= listBox1.Items.Count)
        return; // Index out of range - nothing to do

    object selected = listBox1.SelectedItem;

    // Removing removable element
    listBox1.Items.Remove(selected);
    // Insert it in new position
    listBox1.Items.Insert(newIndex, selected);
    // Restore selection
    listBox1.SetSelected(newIndex, true);
}

无论如何都要在访问vba中执行此操作。

3 个答案:

答案 0 :(得分:0)

我实际上重建了这个设置,但永远不会得到你提到的错误。我确实玩过代码来调整它以适应你想要做的事情。试试这个:

Private Sub cmdup_Click()
Dim sText As String
Dim iIndex As Variant
Dim selection() As Integer
Dim n, topSelection As Integer

' save the indexes of the selected items,
' they will be deselected after the first removal
For Each iIndex In lbfnames.ItemsSelected
    ReDim Preserve selection(0 To n)
    selection(n) = iIndex
    n = n + 1
Next

'loop through all the selected indexes
'this will also ensure you will only proceed if there is a selected item
For n = LBound(selection) To UBound(selection)
    'save items text and items indexvalue
    sText = lbfnames.Column(0, selection(n))

    If selection(n) <= topSelection Then 'index topSelection is top item which can't be moved up!
        MsgBox ("Can not move item '" & sText & "' up any higher.")
        topSelection = topSelection + 1
    Else
        'first remove item from old position
        lbfnames.RemoveItem selection(n)
        'place item back on new position
        lbfnames.AddItem sText, selection(n) - 1
        'change the index of the selected value to the new index (for reselection)
        selection(n) = selection(n) - 1
    End If
Next
'loop through the selection again to reselect
For n = LBound(selection) To UBound(selection)
    lbfnames.Selected(selection(n)) = True
Next
End Sub

我认为代码和注释不言自明,但这是一个快速的贯穿:

  1. 我首先保存所选元素索引,因为我注意到了 删除/添加选择的元素后 不见了。
  2. 然后我完成了这个选择,我在这里重用了你的代码。 更改了弹出消息的条件,因为如果选择 例如,前2个元素(例如1和2),你不想只 获取消息框为1,然后在下一个循环中将2放在1之前。 (除非这是您想要的,然后将此条件更改回0)
  3. 再次在所选元素中添加结束I循环以再次选择它们,以便将它们进一步向上移动。
  4. 注意:示例C#代码显示了两个移动方向的更通用的功能。我没有调整它,我认为这是一个好主意,但留给你实现(总是一个很好的练习来理解代码)。

答案 1 :(得分:0)

以下代码是安全的,可以使用枚举指示方向。 该解决方案允许在列表中上下移动。 解决方案将移动内容包裹起来(例如,如果位于列表顶部,然后尝试向上移动,则将项目包裹到底部。

Private Enum directions
    down = -1
    up = 1
End Enum

Private Sub cmdDown_Click()
    moveListItem (down)
End Sub

Private Sub cmdMvUp_Click()
    moveListItem (up)
End Sub

Private Sub moveListItem(direction As directions)
    With Me.ListBox1
        Select Case .ListIndex

            ' at bottom and moving down then wrap around to top
        Case Is >= .ListCount + direction
            .AddItem .Column(0, .ListCount - 1), 0
            .RemoveItem (.ListCount - 1)
            .Selected(0) = True

            ' at top and moving up then wrap around to bottom
        Case Is < direction
            .AddItem .Column(0, 0), .ListCount
            .RemoveItem (0)
            .Selected(.ListCount - 1) = True

        Case Else
            .AddItem .Column(0, .ListIndex - direction), .ListIndex + ((direction + 1) / 2)
            .RemoveItem (.ListIndex - direction)
        End Select

    End With
End Sub

答案 2 :(得分:0)

如果您不希望使用环绕式功能,请修改上述解决方案。

Option Explicit
Private Enum directions
    down = -1
    up = 1
End Enum

Private Sub cmdDown_Click()
    moveListItem (down)
End Sub

Private Sub cmdMvUp_Click()
    moveListItem (up)
End Sub

Private Sub moveListItem(direction As directions)
    With Me.ListBox1
        Select Case .ListIndex
            ' at bottom and moving down then wrap around to top
        Case Is >= .ListCount + direction

            ' at top and moving up then wrap around to bottom
        Case Is < direction

        Case Else
            .AddItem .Column(0, .ListIndex - direction), .ListIndex + ((direction + 1) / 2)
            .RemoveItem (.ListIndex - direction)
        End Select
    End With
End Sub