简体   繁体   English

由于 redim 数组导致下标超出范围错误

[英]Subscript out of range error due to redim array

The basic mission of this code is to use a list as the source of data for my a listbox control...with a catch.这段代码的基本任务是使用列表作为我的列表框控件的数据源……有一个问题。 I only want the rows that have black cell in column 14 of the list.我只想要列表第 14 列中有黑色单元格的行。

To accomplish this, I attempted to assign an the cells to an array and assign the array using the list property.为此,我尝试将单元格分配给数组并使用列表属性分配数组。

I feel like I have read every refence document available and adhered to all the references, but I continually get this 'subscript out of range' error when 'redimming' the array in a preserved fashion after a for...next loop.我觉得我已经阅读了所有可用的参考文档并遵守了所有参考文献,但是在 for...next 循环之后以保留的方式“重新调暗”数组时,我不断收到此“下标超出范围”错误。

Before I use a temporary list to store my data construct, I really want to nail this dynamic array...but if it is too much work, then I'll have to settle for the easier option.在我使用一个临时列表来存储我的数据结构之前,我真的很想确定这个动态数组……但是如果工作量太大,那么我将不得不接受更简单的选择。 Also, this is a learning process.此外,这是一个学习过程。 Also, please forgive my sloppy indentations and everything else.另外,请原谅我马虎的缩进和其他一切。

Option Explicit

'This code initializes the frmEntry form and sets the list box control
' to list the active escorts (escort records that have blank values
' in the 'End' field of the visitor log (VLog tabl on Visitor Log worksheet).

Private Sub UserForm_Initialize()

Dim wksVisitorLog As Worksheet
Dim wbkVMS As Workbook
Dim Last_Row As Long
Dim objVisitorEscortList As ListObject
Dim objListRow As ListRows
Dim objListCols As ListColumns
Dim listCounter As Single
Dim rowCounter As Single
Dim listArray()
Dim ri As Single
Dim ci As Single
Dim c As Single


Set wbkVMS = ThisWorkbook
Set wksVisitorLog = wbkVMS.Worksheets("Visitor Log")
Set objVisitorEscortList = wksVisitorLog.ListObjects("tblVisitorEscortLog")
Set objListRow = objVisitorEscortList.ListRows
Set objListCols = objVisitorEscortList.ListColumns
rowCounter = 0
ri = 0
ci = 0
c = 0

'Prepares the list box.
With frmEntry
  
  .listboxActiveEscorts.Clear
  .listboxActiveEscorts.ColumnCount = "15"
  .listboxActiveEscorts.ColumnHeads = True
  .listboxActiveEscorts.ColumnWidths = "80,100,100,0,0,100,100,0,0,50,0,0,80,80,80"
    
End With

ReDim listArray(ri, 14)

'This section adds Escort/Visitor records to list box
For listCounter = 1 To objListRow.Count 'Increments based on the total rows on "Visitor Log"
  
    'Selects the row if the "End" field (14th column) is blank
    If objVisitorEscortList.Range.Cells(listCounter + 1, 14) = "" Then
    
      'Increments the row for the listbox array, and will only increment when the if condition is true

        For ci = 0 To 14 'Starts inner loop index for the listbox control column
      
             c = c + 1 'Increments the list range column of the "Visitor Log"
        
        'This portion of the code assigns the two dimensional array index
        listArray(ri, ci) = objVisitorEscortList.Range.Cells(listCounter + 1, c).Value
 
        Next ci
    
    End If
ReDim Preserve listArray(UBound(listArray, 1) + 1)

Next listCounter

'Assigns the entire array to list
listboxActiveEscorts.List = listArray

MsgBox "There are " & frmEntry.listboxActiveEscorts.ListCount & " total active escorts at this time", vbOKOnly

listCounter = 0

End Sub

welcome, the issue is that you declare a 2 dimensional array: ReDim listArray(ri, 14)欢迎,问题是您声明了一个二维数组:ReDim listArray(ri, 14)

this would be similar to: ReDim listArray(0 to ri, 0 to 14)这类似于: ReDim listArray(0 to ri, 0 to 14)

meaning that there are 0 to ri rows and 0 to 14 columns in each row.这意味着每行有 0 到 ri 行和 0 到 14 列。

then you attempt to redim preserve it by only listing the row section: ReDim Preserve listArray(UBound(listArray, 1) + 1)然后您尝试通过仅列出行部分来重新保留它: ReDim Preserve listArray(UBound(listArray, 1) + 1)

in order to redim a 2 dimensional array you must transpose the array before adding any extra rows.为了重新调整二维数组,您必须在添加任何额外行之前转置数组。 If you want to add another column, you do not have to transpose the array.如果要添加另一列,则不必转置数组。

you can use the function:您可以使用 function:

Function varTransposeArray(varInput As Variant) As Variant
' brief, will transpose, flip the row and columns for a 2 dimensional array
' argument, varInput, the array that should be transpose, it can be oany type array, string, integer, varaint, etc, but function will return a variant.
    Dim lRow As Long, lColumn As Long
    Dim vTemporaryArray As Variant

    ' redim vTemporaryArray to the dimensions of varInput
    ' must specify both lbound and uBound for both dimensions otherwise the output might not be correct, for example, it might have a lBound of 0 instead of 1
    ReDim vTemporaryArray(LBound(varInput, 2) To UBound(varInput, 2), LBound(varInput, 1) To UBound(varInput, 1))
    
    ' loop through all values of varInput
    For lRow = LBound(varInput, 2) To UBound(varInput, 2)
        For lColumn = LBound(varInput, 1) To UBound(varInput, 1)
            
            ' transpose, or flip, the row and column of varInput into vTemporaryArray
            If Not VarType(varInput(lColumn, lRow)) = vbObject Then
                vTemporaryArray(lRow, lColumn) = varInput(lColumn, lRow)
            Else
                Set vTemporaryArray(lRow, lColumn) = varInput(lColumn, lRow)
            End If
            
        Next lColumn
    Next lRow

    varTransposeArray = vTemporaryArray

end function

then you can use:然后你可以使用:

listArray = varTransposeArray(listArray)
                    ReDim Preserve listArray(LBound(listArray, 1) To UBound(listArray, 1), LBound(listArray, 2) To UBound(listArray, 2) + 1)
                    listArray = varTransposeArray(listArray)

                

If this answers your question, click thumbs up, thanks.如果这回答了您的问题,请点击竖起大拇指,谢谢。

I was able to get my ListBox to populate using a filtered range from an Excel WorkSheet by using a dynamic array...without transposing rows and columns.通过使用动态数组,我能够使用来自 Excel 工作表的过滤范围来填充我的列表框...无需转置行和列。 The data seems intact.数据似乎完好无损。 I am able to select an item(row) in the list, which populates in assigned controls.我能够 select 列表中的一个项目(行),它填充在分配的控件中。 Here is the code I used:这是我使用的代码:

Private Sub UserForm_Initialize()

'Workbook and Worksheets
Dim wbkVMS As Workbook: Set wbkVMS = ThisWorkbook
Dim wksVisitorLog As Worksheet, wksAcctInfo As Worksheet

'List Objects and List Object Properties
Dim objVisitorEscortList As ListObject, loVisBadge As ListObject
Dim objListRow As ListRows
Dim objListCols As ListColumns ':Set objListCols = objVisitorEscortList.ListColumns
Dim objVIDType As ListObject

'Variables and Arrays
Dim vbArray() As Variant, listArray() As Variant, arrVIDType() As String
Dim vbArrayCount As Single, rowCount As Integer, listCounter As Integer, iVID As Integer
Dim ivb As Integer, ri As Integer, ci As Integer, c As Integer, i As Single, arrayColumnIndex As Integer
Dim cVID As Integer

'Variable assignments
Set wksVisitorLog = wbkVMS.Worksheets("Visitor Log")
Set objVisitorEscortList = wksVisitorLog.ListObjects("tblVisitorEscortLog8")
Set wksAcctInfo = wbkVMS.Worksheets("Account Information")
Set loVisBadge = wksAcctInfo.ListObjects("tblVisitorBadge")
Set objListRow = objVisitorEscortList.ListRows
vbArrayCount = loVisBadge.ListRows.Count
Set objVIDType = Worksheets("Supplemental Lists").ListObjects("tblVIDType")
iVID = objVIDType.ListRows.Count

'Prepares the Active Escorts list box.
ivb = 0
i = 0
With frmEntry
      
    .listboxActiveEscorts.Clear
    .listboxActiveEscorts.ColumnHeads = False
    .listboxActiveEscorts.ColumnCount = "15"
    .listboxActiveEscorts.ColumnWidths = "0,100,100,0,0,100,100,0,0,0,0,0,100,100,80"
    
    'Adds identification types of Visitor Identification Control
    ReDim arrVIDType(0 To iVID - 1)
    For i = 0 To iVID - 1
        cVID = cVID + 1
        arrVIDType(cVID - 1) = objVIDType.Range.Cells(i + 2, 1)
    Next i
    .cbxVIdentification.List = arrVIDType
    i = 0
        
    'Add badge #s to combobox
    ReDim vbArray(0 To vbArrayCount - 1)
    For i = 0 To vbArrayCount - 1
        ivb = ivb + 1
        vbArray(ivb - 1) = loVisBadge.Range.Cells(i + 2, 1).Value
    Next i
    .cbxVisitorBadgeNumber.List = vbArray
    
End With

'This section adds Escort/Visitor records to list box
i = 0
ri = 0
ci = 0
c = 0
rowCount = wksVisitorLog.Range("N1").Value
rowCount = rowCount - 1
ReDim listArray(rowCount, 14)
For listCounter = 1 To objListRow.Count 'Increments based on the total rows on "Visitor Log"
    'Selects the row if the "End" field (14th column) is blank
    If objVisitorEscortList.Range.Cells(listCounter + 1, 14) = "" Then
        ri = ri + 1
        For ci = 0 To 14 'Starts inner loop index for the listbox control column
            c = c + 1 'Increments the list range column of the "Visitor Log"
            listArray(ri - 1, ci) = objVisitorEscortList.Range.Cells(listCounter + 1, c).Value
        Next ci
    End If
    c = 0
Next listCounter
'Assigns the entire array to list
listboxActiveEscorts.List = listArray

MsgBox "There are " & frmEntry.listboxActiveEscorts.ListCount & " total active escorts at this time", vbOKOnly

End Sub

在此处输入图像描述

The outer loop cycles through an Excel range, and while cycling through the loop checks for a condition.外循环在 Excel 范围内循环,并在循环中循环检查条件。 If that condition is true, the code executes an inner loop which cycles through each column of the Excel row that met the condition.如果该条件为真,代码将执行一个内部循环,循环遍历满足条件的 Excel 行的每一列。

Then, basically, I have an iterator and a counter.然后,基本上,我有一个迭代器和一个计数器。 The counter increments inside the loop independently of the increments of the array, keeping the indexes succinct.计数器在循环内递增,独立于数组的递增,保持索引简洁。 After assigning values to the array index using the loop, the dynamic array is assigned to the ListBox array.使用循环将值分配给数组索引后,动态数组将分配给 ListBox 数组。 The ListBox will grow or shrink depending the on the filtered items in the range. ListBox 将根据范围内过滤的项目而增大或缩小。

I have to figure out how to clear the array from the ComboBoxes...another problem I have to solve.我必须弄清楚如何从 ComboBoxes 中清除数组……我必须解决的另一个问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM