如何使用单个组合框元素引用不同工作表中的单元格?

How do I reference cells from different sheets with single combo box element?

假设我有 2 张:companiespersons。我将公司和个人的姓名放入一个组合框中,因此组合框中的项目如下所示:

*CompanyName1
*CompanyName2
*CompanyName3
...
*CompanyNameN
*PersonName1
*PersonName2
*PersonName3
...
*PersonNameN

我希望 ComboBox 在选择时引用相应的单元格,但是如果条目来自 2 个不同的单元格,我该怎么办?我只这样看:

  1. Companies

  2. 中的项目填充组合框
  3. 创建一个变量来保持Persons

    的起始索引
     dim PersonsIndexStart as Integer
    PersonsIndexStart = ComboBox.ListCount + 1
    
  4. Persons

  5. 中的项目填充组合框
  6. 选择项目后,计算项目的 "true index"。

    dim TrueIndex as integer
    
    If ComboBox.ListIndex >= PersonsIndexStart Then
        TrueIndex = ComobBox.ListIndex - PersonsIndexStart
        Else TrueIndex = ComboBox.ListIndex
    End If
    

这个方法看起来很笨拙,还有别的方法吗?例如,我可以将一些额外的数据附加到 ComboBox 项目而不是它的名称吗?

如果您的第二个数据在 A20:A50 范围内,那么您可以使用

Range("A20").Offset(ComboBox.ListIndex,0)

直接进入正确的单元格。所以你只需要知道你的第二个列表从哪里开始。

我可以将一些额外的数据附加到 ComboBox 吗? (示例代码假定用户窗体)

当然可以用二维数据块填充ComboBox;多列由其 .ColumnCount.ColumnWidths 属性定义。您甚至可以通过定义零宽度来隐藏列 - c.f。 UserForm_Layout。此外,我演示了一种通过所谓的数组方法将数据分配给 ComboBox 的 .List 属性 的快速方法。为了满足您的额外信息需求,第 2 列和第 3 列(均隐藏为零宽度)预填充了对 sheet no 1 or 2 的引用及其在引用中的 "true" 行索引工作sheet.

Private Sub UserForm_Initialize()
  ' Purpose: populate ComboBox with data from 2 sheets
    doFillCombo Me.ComboBox1, Sheet1, Sheet2   ' sheets reference via their CodeName here !
End Sub

Private Sub UserForm_Layout()
  ' Purpose: layout combobox including hidden columns
    With Me.ComboBox1
        .ColumnCount = 3                   ' << provide for 3 columns assigned via .List
        .ColumnWidths = .Width & ";0;0"    ' << hide last columns by ZERO widths
    End With
End Sub

子调用doFillCombo()(从UserForm_Initialize调用)

Private Sub doFillCombo(cbo As MSForms.ComboBox, _
            ws1 As Worksheet, ws2 As Worksheet, _
            Optional ByVal ColWs1 = "A", Optional ByVal ColWs2 = "A")
' assign data from both sheets to temporary arrays
  Dim tmp1, tmp2
  tmp1 = getData(ws1, ColWs1)
  tmp2 = getData(ws2, ColWs2)

' provide for a container array
  ReDim arr(1 To UBound(tmp1) + UBound(tmp2), 1 To 3)

' read 1st data block to container
  Dim i&
  For i = 1 To UBound(tmp1)
      arr(i, 1) = tmp1(i, 1)
      arr(i, 2) = 1                   ' refers to 1st worksheet
      arr(i, 3) = i                   ' item count in the sheet's data column
  Next i
' read 2nd data block to container
  Dim StartRow&: StartRow = UBound(arr) - UBound(tmp2) + 1
  For i = StartRow To UBound(arr)
      arr(i, 1) = tmp2(i - UBound(tmp1), 1)
      arr(i, 2) = 2                   ' refers to 2nd worksheet
      arr(i, 3) = i - UBound(tmp1)    ' item count in the sheet's data column
  Next i

' Assign data to combobox'es list property by one code line
  cbo.List = arr
End Sub

*过程调用的辅助函数doFillCombo

    Private Function getData(ws As Worksheet, ByVal col, Optional ByVal StartRow& = 2) As Variant()
    ' Purpose: assign column data to variant array
    If IsNumeric(col) Then col = Split(ws.Cells(1, col).Address, "$")(1)
    Dim LastRow&
    LastRow = ws.Range(col & Rows.Count).End(xlUp).Row
    getData = ws.Range(col & StartRow & ":" & col & LastRow).Value2
    End Function

可能的测试显示以获取信息

假定标签控件(例如 Label1)显示引用的 sheet 编号以及隐藏组合框列中预填充的行索引:

Private Sub ComboBox1_Click()
' Purpose: display sheet related counters
' Note:    index reference to .List is zero-based (1st column = 0, 2nd = 1, ...)
  With Me.ComboBox1
      If .ListIndex < 0 Then Exit Sub
      Me.Label1 = "Sheet" & .List(.ListIndex, 1) & " " & _
                  "Item " & .List(.ListIndex, 2) ' optional test display via e.g. Label1
  End With
End Sub

顺便说一句,无论如何你都不会避免一些计算;在你的情况下,我什至建议坚持你选择的方法,但要通过用户定义的函数获取索引——不必认为这是笨拙的:-)。