3

CODE WORKS CORRECTLY. MODIFIED BASED ON HELP FROM RESPONSES.

I have the following code to remove duplicates from a array, MyArray. The code gets a debugging error at: d(MyArray(i)) = 1. The error is subscript out of range. Not sure what is causing this and what is wrong with my code.

Sub DataStats1()
Dim Range1 As Range
Dim MyArray As Variant

Set Range1 = Application.InputBox("Select Range1:", Title:="Set Data Range", Type:=8)

Range1.Select
MyArray = Application.Transpose(Application.Transpose(Range1.Value))



Dim d As Object
Set d = CreateObject("Scripting.Dictionary")

For Each el In MyArray
   d(el) = 1
Next

Dim v As Variant
v = d.Keys()


For i = 1 To UBound(v)
MsgBox v(i)
Next i
End Sub
9
  • 1
    @simoco thanks I didn't realize I could do that. I thought I couldn't select an answer because of my low reputation. I just went back and selected answers for many of them. Commented May 5, 2014 at 21:17
  • about your Q: MyArray is always 2D array, even if you select single row/column range. E.g. for single column range you should use d(MyArray(i,1)) = 1 instead d(MyArray(i)) = 1. But I suggets you to change For i = LBound(MyArray) To UBound(MyArray) to say For Each el in MyArray and then d(el) = 1 Commented May 5, 2014 at 21:20
  • @simoco I've made your suggested changes and am getting v as an empty array. updated code above. Commented May 5, 2014 at 21:31
  • You never add anything to v. Perhaps you mean v = d.Keys(). Commented May 5, 2014 at 21:42
  • 1
    I was looking at your initial code (second line). Anyhow, check your locals window and use debug.print to debug your code. Check the content of your dictionary for instance. Then assign the values from your dictionary to your array. Not sure if this is the most obvious way though. If you want to remove duplicates from an array, check for example: stackoverflow.com/questions/11870095/… Commented May 5, 2014 at 22:26

2 Answers 2

2

You should learn to stop relying on Selection (this is after all why you have declared your variables...). You can do MyArray = Range1.Value instead.

Now, a Range Array is always going to be 2-dimensional, you instead of that, you will acutally need to do this if you are selecting a COLUMN range:

MyArray = Application.Transpose(Range1.Value)

Or this, if you are selecting a ROW range:

MyArray = Application.Transpose(Application.Transpose(Range1.Value)

You may need to do other operations if it is multi-dimensional range. I haven't tested.

Here are some ideas:

Sub DataStats1()
Dim Range1 As Range
Dim MyArray As Variant
Dim v As Variant
Dim d As Object

Set Range1 = Application.InputBox("Select Range1:", Title:="Set Data Range", Type:=8)

MyArray = Application.Transpose(Application.Transpose(Range1.Value))

Set d = CreateObject("Scripting.Dictionary")

For Each el In MyArray
   d(el) = 1
Next

'## Assign the Keys to an array:
v = d.Keys

'## At this point, v is an array of unique values.
'   Do whatever you want with it:
'
'Print the list to a COLUMN new sheet:
Sheets.Add
Range("A1").Resize(UBound(v) + 1).Value = Application.Transpose(v)


'Or print the list to a msgBox:
MsgBox Join(v, ", ")

'Or print to the console:
Debug.Print Join(v, ", ")

End Sub
Sign up to request clarification or add additional context in comments.

2 Comments

Why do you have to transpose both ranges. My understanding is a array is 2D with a width of one and a height of any number. Shouldn't you only need to tranpose a column range?
Range arrays area always 2-dimensional and that is why you have to transpose them to get a one-dimensional array (if you don't believe me, try it out for yourself :)). Alternatively, you can work with the multi-dimensional arrays. As for why? I don't know why, that's just how it is. Probably to mimic the Cells(_row_, _column_) construct of the Range object. It would be confusing if MyRange.Cells(1,1) was not the same as MyArray(1,1). But I am not sure about that, it just seems like the likely reason to me.
1

Something like this (for a single column or single row given you use Transpose)

Sub DataStats1()
Dim Rng1 As Range
Dim MyArray As Variant
Dim MyArray2 As Variant
Dim el
Dim d As Object

On Error Resume Next
Set Rng1 = Application.InputBox("Select Range1:", Title:="Set Data Range", Type:=8)
On Error GoTo 0

If Rng1 Is Nothing Then Exit Sub

MyArray = Application.Transpose(Application.Transpose(Rng1.Value))
Set d = CreateObject("Scripting.Dictionary")

For Each el In MyArray
If Not d.exists(el) Then d.Add el, 1
Next

MyArray2 = d.items

End Sub

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.