2011-08-09 251 views
8

我有一个全局数组,prLst(),它可以是可变长度的。它需要数字作为字符串"1"Ubound(prLst)。但是,当用户输入"0"时,我想从列表中删除该元素。我写了下面的代码来执行此操作:如果元素是某个值,删除数组中的元素VBA

count2 = 0 
eachHdr = 1 
totHead = UBound(prLst) 

Do 
    If prLst(eachHdr) = "0" Then 
     prLst(eachHdr).Delete 
     count2 = count2 + 1 
    End If 
    keepTrack = totHead - count2 
    'MsgBox "prLst = " & prLst(eachHdr) 
    eachHdr = eachHdr + 1 
Loop Until eachHdr > keepTrack 

这不起作用。如果元素是"0",如何有效地删除数组prLst中的元素?


注:这是一个更大的程序,对此的描述可以在这里找到的一部分:Sorting Groups of Rows Excel VBA Macro

回答

28

数组是具有一定尺寸的结构。您可以使用vba中的动态数组,您可以使用ReDim进行缩小或增长,但不能删除中间的元素。这不是从你的样品清楚如何你的阵列功能上工作或你如何确定索引位置(eachHdr),但你基本上有3个选择

(A)编写自定义“删除”功能,为您的阵列状(未经测试)

Public Sub DeleteElementAt(Byval index As Integer, Byref prLst as Variant) 
     Dim i As Integer 

     ' Move all element back one position 
     For i = index + 1 To UBound(prLst) 
      prLst(i - 1) = prLst(i) 
     Next 

     ' Shrink the array by one, removing the last one 
     ReDim Preserve prLst(Len(prLst) - 1) 
End Sub 

(B)只需设置一个“虚拟”的值作为值,而不是实际删除元件

If prLst(eachHdr) = "0" Then   
    prLst(eachHdr) = "n/a" 
End If 

(C)停止使用阵列并将其转换为一个VBA.Collection。集合是一个(唯一的)键/值对的结构,你可以自由地从

Dim prLst As New Collection 
+0

对于集合,集合的长度是否必须指定或“ReDimmed”?另外,您是否可以通过元素逐个元素循环,按特定顺序排列元素?另外,你是否必须循环删除,或者有没有办法说“所有这些都是'这个',删除!” ? – H3lue

+1

不,收集的长度不必由您(用户)“重做”。这使得集合比需要添加和删除项目的任务的数组方便得多。请参阅[文档](http://msdn.microsoft.com/en-US/library/yb7y698k%28v=VS.80%29.aspx)。 –

+1

很多问题:)无需redim。是的,你可以遍历它们,并在其他元素之前或之后插入元素。元素可以通过它们的索引号(如数组中的索引)或按键的名称来访问。进一步查看http://msdn.microsoft.com/en-us/library/aa164019(v=office.10).aspx#odc_tentipsvba_topic4和http://msdn.microsoft.com/en-us/library/a1y8b3b3( v = vs.80).aspx – Eddy

-1

添加或删除元素来创建数组的时候,为什么不跳过的0和保存自己不必担心时间他们以后?如上所述,数组不适合删除。

+0

此代码是我在此处创建的较大代码的一部分:http://stackoverflow.com/questions/6671273/excel-vba-macro-sorting-with-groups-or-linked-rows此代码是sub EstSortPriorities的一部分。由于程序不知道在页面顶部排序的标题,用户必须指定。我已经选择了用户应该输入一个“0”,如果给定一个特定的头不需要排序优先级。 – H3lue

0

我是很新,VBA & Excel中 - 只有做这个做了3个月左右 - 我想我会在这里分享我的阵列重复数据删除方法,这个职位似乎是有关它:

这如果是分析管道数据的较大应用程序的一部分,则编码 - 管道在xxxx.1,xxxx.2,yyyy.1,yyyy.2 ....格式的数字表中列出。所以这就是为什么所有的字符串操作存在。 基本上它只收集一次管道号,而不是.2或.1部分。

 With wbPreviousSummary.Sheets(1) 
' here, we will write the edited pipe numbers to a collection - then pass the collection to an array 
     Dim PipeDict As New Dictionary 

     Dim TempArray As Variant 

     TempArray = .Range(.Cells(3, 2), .Cells(3, 2).End(xlDown)).Value 

     For ele = LBound(TempArray, 1) To UBound(TempArray, 1) 

      If Not PipeDict.Exists(Left(TempArray(ele, 1), Len(TempArray(ele, 1) - 2))) Then 

       PipeDict.Add Key:=Left(TempArray(ele, 1), Len(TempArray(ele, 1) - 2)), _ 
                 Item:=Left(TempArray(ele, 1), Len(TempArray(ele, 1) - 2)) 

      End If 

     Next ele 

     TempArray = PipeDict.Items 

     For ele = LBound(TempArray) To UBound(TempArray) 
      MsgBox TempArray(ele) 
     Next ele 

    End With 
    wbPreviousSummary.Close SaveChanges:=False 

    Set wbPreviousSummary = Nothing 'done early so we dont have the information loaded in memory 

使用一堆消息框来调试atm - 我确定你会改变它来适应你自己的工作。

我希望人们发现这很有用, 问候 乔

+0

请不要运行精确的代码 - 大量缺少的变量和一些字符串工作是错误的,当我发布它。 – AverageJoe

1
Sub DelEle(Ary, SameTypeTemp, Index As Integer) '<<<<<<<<< pass only not fixed sized array (i don't know how to declare same type temp array in proceder) 
    Dim I As Integer, II As Integer 
    II = -1 
    If Index < LBound(Ary) And Index > UBound(Ary) Then MsgBox "Error.........." 
    For I = 0 To UBound(Ary) 
     If I <> Index Then 
      II = II + 1 
      ReDim Preserve SameTypeTemp(II) 
      SameTypeTemp(II) = Ary(I) 
     End If 
    Next I 
    ReDim Ary(UBound(SameTypeTemp)) 
    Ary = SameTypeTemp 
    Erase SameTypeTemp 
End Sub 

Sub Test() 
    Dim a() As Integer, b() As Integer 
    ReDim a(3) 
    Debug.Print "InputData:" 
    For I = 0 To UBound(a) 
     a(I) = I 
     Debug.Print " " & a(I) 
    Next 
    DelEle a, b, 1 
    Debug.Print "Result:" 
    For I = 0 To UBound(a) 
     Debug.Print " " & a(I) 
    Next 
End Sub 
+2

仅有代码的答案很少。最好添加一些解释它的文字。 –

0

删除数组中的元素,如果元素有一定的价值VBA

数组中的王氏一定要删除元素条件,你可以这样编码

For i = LBound(ArrValue, 2) To UBound(ArrValue, 2) 
    If [Certain condition] Then 
     ArrValue(1, i) = "-----------------------" 
    End If 
Next i 

StrTransfer = Replace(Replace(Replace(join(Application.Index(ArrValue(), 1, 0), ","), ",-----------------------,", ",", , , vbBinaryCompare), "-----------------------,", "", , , vbBinaryCompare), ",-----------------------", "", , , vbBinaryCompare) 
ResultArray = join(Strtransfer, ",") 

我经常操纵1D-阵列与Join /拆分 ,但如果你要删除的多维一定的价值,我建议你改变这些阵列到一维数组这样

strTransfer = Replace(Replace(Replace(Replace(Names.Add("A", MultiDimensionArray), Chr(34), ""), "={", ""), "}", ""), ";", ",") 
'somecode to edit Array like 1st code on top of this comment 
'then loop through this strTransfer to get right value in right dimension 
'with split function. 
0

这里是一个代码示例使用CopyMemory函数来完成这项工作。

它被认为是“快得多”(取决于数组的大小和类型...)。

我不是作家,但我进行了测试:

Sub RemoveArrayElement_Str(ByRef AryVar() As String, ByVal RemoveWhich As Long) 

'// The size of the array elements 
'// In the case of string arrays, they are 
'// simply 32 bit pointers to BSTR's. 
Dim byteLen As Byte 

'// String pointers are 4 bytes 
byteLen = 4 

'// The copymemory operation is not necessary unless 
'// we are working with an array element that is not 
'// at the end of the array 
If RemoveWhich < UBound(AryVar) Then 
    '// Copy the block of string pointers starting at 
    ' the position after the 
    '// removed item back one spot. 
    CopyMemory ByVal VarPtr(AryVar(RemoveWhich)), ByVal _ 
     VarPtr(AryVar(RemoveWhich + 1)), (byteLen) * _ 
     (UBound(AryVar) - RemoveWhich) 
End If 

'// If we are removing the last array element 
'// just deinitialize the array 
'// otherwise chop the array down by one. 
If UBound(AryVar) = LBound(AryVar) Then 
    Erase AryVar 
Else 
    ReDim Preserve AryVar(LBound(AryVar) To UBound(AryVar) - 1) 
End If 
End Sub 
0

我知道这是旧的,但这里是我想出了的时候,我不喜欢,我发现的那些解决方案。

-loop通过添加各元件和部分分隔为一个字符串,所述阵列(变体),除非它匹配要删除 - 然后拆分在分隔

tmpString="" 
For Each arrElem in GlobalArray 
    If CStr(arrElem) = "removeThis" Then 
     GoTo SkipElem 
    Else 
     tmpString =tmpString & ":-:" & CStr(arrElem) 
    End If 
SkipElem: 
Next 
GlobalArray = Split(tmpString, ":-:") 

显然使用该字符串的一个的字符串会产生一些限制,比如需要确保数组中已有的信息,并且原因是此代码使第一个数组元素变为空白,但它确实满足了我的需要,并且稍微多了一些工作就可以使用更多功能。