View Full Version : Compile error: User-defined type not defined

11-14-2007, 08:18 PM
:think: I've found the code below, which will find all combinations of cells that add up to a certain number in Excel, but I'm getting the compile error regarding "Dictionary". It doesn't appear to be defined and I'm a newbie and not sure what I need to do to get it to work. See code below and thanks in advance.

Sub findsums()
'This *REQUIRES* VBAProject references to
'Microsoft Scripting Runtime
'Microsoft VBScript Regular Expressions 1.0 or higher
Const TOL As Double = 0.000001 'modify as needed
Dim c As Variant
Dim j As Long, k As Long, n As Long, p As Boolean
Dim s As String, t As Double, u As Double
Dim v As Variant, x As Variant, y As Variant
Dim dc1 As New Dictionary, dc2 As Dictionary
Dim dcn As Dictionary, dco As Dictionary
Dim re As RegExp
re.Global = True
re.IgnoreCase = True
On Error Resume Next
Set x = Application.InputBox( _
Prompt:="Enter range of values:", _
Title:="findsums", _
Default:="", _
Type:=8 _
If x Is Nothing Then
Exit Sub
End If
y = Application.InputBox( _
Prompt:="Enter target value:", _
Title:="findsums", _
Default:="", _
Type:=1 _
If VarType(y) = vbBoolean Then
Exit Sub
t = y
End If
On Error GoTo 0
Set dco = dc1
Set dcn = dc2
Call recsoln
For Each y In x.Value2
If VarType(y) = vbDouble Then
If Abs(t - y) < TOL Then
recsoln "+" & Format(y)
ElseIf dco.Exists(y) Then
dco(y) = dco(y) + 1
ElseIf y < t - TOL Then
dco.Add Key:=y, Item:=1
c = CDec(c + 1)
Application.StatusBar = "[1] " & Format(c)
End If
End If
Next y
n = dco.Count
ReDim v(1 To n, 1 To 3)
For k = 1 To n
v(k, 1) = dco.Keys(k - 1)
v(k, 2) = dco.Items(k - 1)
Next k
qsortd v, 1, n
For k = n To 1 Step -1
v(k, 3) = v(k, 1) * v(k, 2) + v(IIf(k = n, n, k + 1), 3)
If v(k, 3) > t Then dcn.Add Key:="+" & _
Format(v(k, 1)), Item:=v(k, 1)
Next k
On Error GoTo CleanUp
Application.EnableEvents = False
Application.Calculation = xlCalculationManual
For k = 2 To n
swapo dco, dcn
For Each y In dco.Keys
p = False
For j = 1 To n
If v(j, 3) < t - dco(y) - TOL Then Exit For
x = v(j, 1)
s = "+" & Format(x)
If Right(y, Len(s)) = s Then p = True
If p Then
re.Pattern = "\" & s & "(?=(\+|$))"
If re.Execute(y).Count < v(j, 2) Then
u = dco(y) + x
If Abs(t - u) < TOL Then
recsoln y & s
ElseIf u < t - TOL Then
dcn.Add Key:=y & s, Item:=u
c = CDec(c + 1)
Application.StatusBar = "[" & Format(k) & "] " & _
End If
End If
End If
Next j
Next y
If dcn.Count = 0 Then Exit For
Next k
If (recsoln() = 0) Then _
MsgBox Prompt:="all combinations exhausted", _
Title:="No Solution"
Application.EnableEvents = True
Application.Calculation = xlCalculationAutomatic
Application.StatusBar = False
End Sub
Private Function recsoln(Optional s As String)
Const OUTPUTWSN As String = "findsums solutions" 'modify to taste
Static r As Range
Dim ws As Worksheet
If s = "" And r Is Nothing Then
On Error Resume Next
Set ws = ActiveWorkbook.Worksheets(OUTPUTWSN)
If ws Is Nothing Then
Application.ScreenUpdating = False
Set ws = ActiveSheet
Set r = Worksheets.Add.Range("A1")
r.Parent.Name = OUTPUTWSN
Application.ScreenUpdating = False
Set r = ws.Range("A1")
End If
recsoln = 0
ElseIf s = "" Then
recsoln = r.Row - 1
Set r = Nothing
r.Value = s
Set r = r.Offset(1, 0)
recsoln = r.Row - 1
End If
End Function
Private Sub qsortd(v As Variant, lft As Long, rgt As Long)
'ad hoc quicksort subroutine
'translated from Aho, Weinberger & Kernighan,
'"The Awk Programming Language", page 161
Dim j As Long, pvt As Long
If (lft >= rgt) Then Exit Sub
swap2 v, lft, lft + Int((rgt - lft + 1) * Rnd)
pvt = lft
For j = lft + 1 To rgt
If v(j, 1) > v(lft, 1) Then
pvt = pvt + 1
swap2 v, pvt, j
End If
Next j
swap2 v, lft, pvt
qsortd v, lft, pvt - 1
qsortd v, pvt + 1, rgt
End Sub
Private Sub swap2(v As Variant, i As Long, j As Long)
'modified version of the swap procedure from
'translated from Aho, Weinberger & Kernighan,
'"The Awk Programming Language", page 161
Dim t As Variant, k As Long
For k = LBound(v, 2) To UBound(v, 2)
t = v(i, k)
v(i, k) = v(j, k)
v(j, k) = t
Next k
End Sub
Private Sub swapo(a As Object, b As Object)
Dim t As Object
Set t = a
Set a = b
Set b = t
End Sub

11-14-2007, 08:32 PM
Welcome to the VBA-X forum ...

I still use Office 2K, but I think this is correct ...

Since this is the Excel area, I assume you are using Excel as the base application. Dictionary is not a defined object for Excel nor is it an object for any of the VBA standard libraries that would be loaded by default for an Excel VBA project (VB for Applications, etc). You can use the Object Browser in the VB editor and search for Dictionary to verify my hypothesis for your version of VB stuff.

You can add the Word VBA library to your application in the VBA Editor:

Tools | References check the box for MS Word obj library

Then search again for Dictionary and it should be there.

11-15-2007, 02:39 AM
What you need to do is

- go ot the VBIDE

- menu Tools>references

- scroll down until you find the item marked Microsoft Scripting Runtime and check that

- then scroll down/up until you find the item marked Microsoft VBScript Regular Expresssions, and check that

- exit and try again

11-15-2007, 11:45 AM
This might be a stupid question, but what's VBIDE?

I do see a Tools\References in Microsoft Visual Basics where I placed the code, but the References is grayed out.

11-15-2007, 01:13 PM
The VBIDE is what you are referring too.

Greyed out? Probably means the project is password protected. Get hold of the author anbd get the password off of him.

11-15-2007, 01:23 PM
Ok, I was able to do what you suggested. After running it again, I'm getting a different error: Object variable or With block variable not set

11-15-2007, 03:28 PM
Change this line:
Dim re As RegExp to this:
Dim re As RegExp
Set re = New RegExp

11-15-2007, 04:23 PM
Made the change and had some progress, the macro actually performed two of the steps (prompt to ask for range and prompt to enter target value), and then, same error: Object variable or With block variable not set

11-15-2007, 05:39 PM
On which line? (if you hit Debug you should see a line highlighted)
YOu may need to change this:
Dim dc1 As New Dictionary, dc2 As Dictionary
to this:
Dim dc1 As New Dictionary, dc2 As New Dictionary

Incidentally, where did you get this code from? It might be easier to ask the author why it doesn't work!

11-15-2007, 06:05 PM
That did the trick. Thanks!!!:clap: