Connecting Tech Pros Worldwide Forums | Help | Site Map

Help with Function to return Array - Type Mismatch

Newbie
 
Join Date: Mar 2009
Posts: 3
#1: Mar 3 '09
I've never posted a question on any site before, but after racking my head over this hurdle for days, I've caved. I'm working on a program that creates a kml file and exports it to Google Earth. In that file, I want to create a 5 mile radius circle around the placemark. To do that, I worked with the kml circlegen source I found online in php. It calculates the latitudes and longitudes of the points that make up the circle. The calculation works correrctly (as shown by printing to the immediate window or by calling the sub), but I can't get the function to return the array. As many different ways I've structured it, I keep getting a 'type mismatch'. Any help would be GREATLY appreciated! I believe I've included all the necessary function code:
Expand|Select|Wrap|Line Numbers
  1. Option Explicit
  2.  
  3. Private Const Radius5mls As Double = 8046.72           'in meters
  4. Private Const PI As Double = 3.14159265358979
  5.  
  6.  
  7. Public Sub FiveMileRadius(lat1 As Double, lon1 As Double)
  8.     Dim Arr As Variant
  9.     Dim i As Integer
  10.     Arr = FiveMileCircleGen(lat1, lon1)
  11.     If IsArrayAllocated(Arr:=Arr) = True Then
  12.         For i = LBound(Arr) To UBound(Arr)
  13.             Debug.Print Arr(i)
  14.         Next i
  15.     Else
  16.         MsgBox ("Not Allocated")
  17.     End If
  18.  
  19. End Sub
Expand|Select|Wrap|Line Numbers
  1. Public Function FiveMileCircleGen(lat1 As Double, lon1 As Double) As Variant()
  2. Dim ResultArray() As Variant
  3. Dim i As Integer
  4. Dim radial As Double, angle As Double
  5. Dim iNumSides As Integer
  6. Dim lat2 As Double
  7. Dim lon2 As Double
  8. Dim dlon As Double
  9. Dim modNum As Double
  10. Dim modDiv As Double
  11. Dim distance As Double
  12.  
  13. 'convert coordinates to radians
  14. lat1 = Deg2Rad(lat1)
  15. lon1 = Deg2Rad(lon1)
  16.  
  17. iNumSides = 360
  18.  
  19. distance = Radius5mls / 6378137   'divided by radius of earth at the equator, in meters
  20.  
  21.     ' Create an array to hold all of the points:
  22.     ReDim ResultArray(i To (iNumSides / 2))
  23.  
  24.     ' trigonometry to calculate circles lat/lon points:
  25.     For i = 0 To iNumSides Step 2
  26.         angle = i
  27.         radial = Deg2Rad(angle)
  28.         lat2 = fnArcSineRad(sIn(lat1) * Cos(distance) + Cos(lat1) * sIn(distance) * Cos(radial))
  29.         dlon = ATan2(sIn(radial) * sIn(distance) * Cos(lat1), Cos(distance) - (sIn(lat1) * sIn(lat2)))
  30.         modNum = (lon1 + dlon + PI)
  31.         modDiv = 2 * PI
  32.         lon2 = (modNum - modDiv * Int(modNum / modDiv)) - PI
  33.  
  34.         lat2 = CStr(Rad2Deg(lat2))
  35.         lon2 = CStr(Rad2Deg(lon2))
  36.  
  37.         ResultArray(i) = lon2 & "," & lat2 & ",0 "
  38.         'Debug.Print lon2 & "," & lat2 & ",0 "
  39.  
  40.     Next i
  41.  
  42.     FiveMileCircleGen = ResultArray        ' remove this line and the resultarray(i) line and open the debug line to work
  43.  
  44. End Function
Expand|Select|Wrap|Line Numbers
  1. Public Function IsArrayAllocated(Arr As Variant) As Boolean
  2.     On Error Resume Next
  3.     IsArrayAllocated = Not (IsError(LBound(Arr))) And IsArray(Arr) And (LBound(Arr) <= UBound(Arr))
  4.  
  5. End Function
  6.  
  7.  
  8.  
  9. '        Name:      ARC SINE IN RADIANS
  10. '     Purpose:      This function determines the ArcSine of the passed argument.
  11. '      Inputs:      vntSine     The sine of an angle.
  12. ' Assumptions:      None.
  13. '     Effects:      Will raise "Overflow" error if vntSine is not a valid sine or
  14. '                   if any other error occurs during execution.
  15. '     Returns:      The angle in radians.
  16. '                   If an error occurs fnArcSine is indeterminate.
  17. '
  18. Public Function fnArcSineRad(vntSine As Variant) As Double
  19. On Error GoTo ERROR_ArcSine                                     ' Trap strangeness.
  20.  
  21. Const cOVERFLOW = 6                                             ' "Overflow" message #.
  22.  
  23. Dim blnEditPassed As Boolean                                    ' Edit results variable.
  24. Dim dblTemp       As Double                                     ' Temporary double.
  25.  
  26.     blnEditPassed = False                                       ' It hasn't passed yet!
  27.     If IsNumeric(vntSine) Then                                  ' Is arg numeric?
  28.         If vntSine >= -1 And vntSine <= 1 Then                  ' Yup, is it within limits?
  29.             blnEditPassed = True                                ' Yup, employ Derived Math Function:
  30.                                                                 ' Arcsin(X) = Atn(X / Sqr(-X * X + 1))
  31.             dblTemp = Sqr(-vntSine * vntSine + 1)               ' Calculate denominator.
  32.             If dblTemp = 0 Then                                 ' Is it 0?  Can only happen if arg is +1 or -1.
  33.                 fnArcSineRad = Sgn(vntSine) * PI / 2          ' Yup, assign +Pi/2 or -Pi/2 based on sign of arg.
  34.             Else
  35.                 fnArcSineRad = Atn(vntSine / dblTemp)           ' Complete derived math function.
  36.             End If
  37.         End If
  38.     End If
  39.  
  40. EXIT__ArcSine:
  41.     If Not blnEditPassed Then Err.Raise cOVERFLOW               ' Raise overflow error if arg failed edits.
  42.     Exit Function
  43.  
  44. ERROR_ArcSine:
  45.     On Error GoTo 0                                             ' Turn off error trapping.
  46.     blnEditPassed = False                                       ' Should never happen!
  47.     Resume EXIT__ArcSine                                        ' But if it does give overflow error.
  48.  
  49. End Function

FishVal's Avatar
Expert
 
Join Date: Jun 2007
Location: Israel
Posts: 2,584
#2: Mar 3 '09

re: Help with Function to return Array - Type Mismatch


Hello.

Variant type includes array.
So, just change FiveMileCircleGen function return value type to Variant. It should work.
Expand|Select|Wrap|Line Numbers
  1. Public Function FiveMileCircleGen(lat1 As Double, lon1 As Double) As Variant
  2.  
Regards,
Fish
Newbie
 
Join Date: Mar 2009
Posts: 3
#3: Mar 3 '09

re: Help with Function to return Array - Type Mismatch


Thanks Fish. When I remove the "()" from

Public Function FiveMileCircleGen(lat1 As Double, lon1 As Double) As Variant()

It then gives me a "Subscript out of range" error. To fix that I change the line to the following:

Redim ResultArray(i To iNumSides)

Now it gives me a 'run-time error 13, type mismatch'

Loren
NeoPa's Avatar
Administrator
 
Join Date: Oct 2006
Location: London - UK
Posts: 15,730
#4: Mar 3 '09

re: Help with Function to return Array - Type Mismatch


As far as I can tell, there is no way of defining a function explicitly to return an array.

However, it is possible to define it as a Variant, and set the return value as an array (Variants can handle arrays).

This quick function illustrates how this can be done :
Expand|Select|Wrap|Line Numbers
  1. Public Function Test() As Variant
  2.     Test = Split("A,B,C", ",")
  3. End Function
Some code to illustrate that this works (and that works from the Immediate pane) is :
Expand|Select|Wrap|Line Numbers
  1. For A=0 to 2:?Test()(A),:Next
NeoPa's Avatar
Administrator
 
Join Date: Oct 2006
Location: London - UK
Posts: 15,730
#5: Mar 3 '09

re: Help with Function to return Array - Type Mismatch


I suggest you may need to build up your array first, with all the flexibility available to properly defined variables, then simply assign this array to the function return value when done.
Site Addict
 
Join Date: Mar 2007
Location: Oakland, California, USA
Posts: 522
#6: Mar 3 '09

re: Help with Function to return Array - Type Mismatch


Why not pass the array to the function (now sub)?
Expand|Select|Wrap|Line Numbers
  1. Dim a(1 To 3) As Long
  2. Public Sub xx(ary As Variant)
  3.     ary(1) = 1
  4.     ary(2) = 2
  5.     ary(3) = 3
  6. End Sub
  7.  
  8. Call xx(a)
  9. Debug.Print a(1), a(2), a(3)
  10.  
NeoPa's Avatar
Administrator
 
Join Date: Oct 2006
Location: London - UK
Posts: 15,730
#7: Mar 3 '09

re: Help with Function to return Array - Type Mismatch


The dimensions may not be known in advance of running the code OB.

In any case, the logic of it would tend to be obscured by that rather than clarified (if that makes sense). The function should be in control of what it produces - rather than being dependant on outside code.
Site Addict
 
Join Date: Mar 2007
Location: Oakland, California, USA
Posts: 522
#8: Mar 3 '09

re: Help with Function to return Array - Type Mismatch


In this case, the dimensions are known. It is a single dimension array. True, long is not the correct type, but I only posted a simple example. I could have posted:
Expand|Select|Wrap|Line Numbers
  1. Dim a() As Double
  2. Public Sub xx(ary As Variant)
  3. ReDim a(0 To 2, 1 To 3)
  4.     ary(0, 1) = 1
  5.     ary(0, 2) = 2
  6.     ary(0, 3) = 3
  7. Debug.Print a(0, 1), a(0, 2), a(0, 3)
  8. End Sub
I may not understand, but I thought that when a function was called, any parameters passed "By Reference" were passed as a pointer to the variable. Because any memory is released when a function ends, the return value must be created by the compiler/VBA as workspace within the calling routine, and a pointer to that space passed to the function.
In other words, Call subX(a,b,c) would pass 3 pointers, ptr->a, ptr->b, ptr->c. c=funcX(a,b) would pass 3 pointers, ptr->a, ptr->b, ptr->workspace. Any function could be written as a subroutine if the last line of the subroutine were an assignment to the last argument.
My function is as much in control as any function. When I enter the function line
Expand|Select|Wrap|Line Numbers
  1. ... Function (arg1, arg2, ...) As Type
where type is a valid data type, I am I not telling the compiler what workspace it needs to generate before it invokes the function? The function is not in control, the calling code is.

I was looking for a solution to lasmith329's problem. There should be no error 13 mismatch with this. That was all I was attempting to do.
Newbie
 
Join Date: Mar 2009
Posts: 3
#9: Mar 3 '09

re: Help with Function to return Array - Type Mismatch


Thanks for everyone's input. With your help and finding just the right tutorial I was able to finally get the function to return an array. FYI, here's the final code:
Expand|Select|Wrap|Line Numbers
  1. Public Function FiveMileCircleGen(lat1 As Double, lon1 As Double) As String
  2.  
  3. Dim ArrayReturned As String
  4. Dim i As Integer
  5. Dim radial As Double, angle As Double
  6. Dim lat2 As Double
  7. Dim lon2 As Double
  8. Dim dlon As Double
  9. Dim modNum As Double
  10. Dim modDiv As Double
  11. Dim distance As Double
  12. Dim lngFN As Long
  13.  
  14.  
  15. 'convert coordinates to radians
  16. lat1 = Deg2Rad(lat1)
  17. lon1 = Deg2Rad(lon1)
  18.  
  19.  
  20. Const iNumSides = 360
  21.  
  22. distance = Radius5mls / 6378137   'divided by radius of earth at the equator, in meters
  23.  
  24.     '// Create an array to hold all of the points:
  25.     'ReDim ResultArray (361)
  26.     Dim ResultArray(iNumSides) As String
  27.  
  28.     ArrayReturned = ""
  29.     '// Use trigonometry to points:
  30.     For i = 1 To iNumSides
  31.         angle = i
  32.         radial = Deg2Rad(angle)
  33.         lat2 = fnArcSineRad(sIn(lat1) * Cos(distance) + Cos(lat1) * sIn(distance) * Cos(radial))
  34.         dlon = ATan2(sIn(radial) * sIn(distance) * Cos(lat1), Cos(distance) - (sIn(lat1) * sIn(lat2)))
  35.         modNum = (lon1 + dlon + PI)
  36.         modDiv = 2 * PI
  37.         lon2 = (modNum - modDiv * Int(modNum / modDiv)) - PI
  38.  
  39.         lat2 = Rad2Deg(lat2)
  40.         lon2 = Rad2Deg(lon2)
  41.  
  42.         ResultArray(i) = CStr(lon2 & "," & lat2 & ",0 ")
  43.         ArrayReturned = ArrayReturned & ResultArray(i)
  44.  
  45.     Next i
  46.  
  47.     FiveMileCircleGen = ArrayReturned
  48.  
  49. End Function
NeoPa's Avatar
Administrator
 
Join Date: Oct 2006
Location: London - UK
Posts: 15,730
#10: Mar 4 '09

re: Help with Function to return Array - Type Mismatch


Quote:

Originally Posted by OldBirdman View Post

Why not pass the array to the function (now sub)?

I'm sorry OB. I'm afraid I have a tendency to treat things very literally. In this case I took this as a Request For Comment.

My response was not intended to be critical, and certainly not to imply you shouldn't have posted it. It was simply my opinions of the general approach illustrated in your proposed solution (with supporting rationale).

It's not my habit to offer such opinions unrequested (unless I feel that somehow the code suggested may cause real issues - certainly not the case in this instance), but as I say, I am prone to treat things quite literally. Please ignore if not interested.
NeoPa's Avatar
Administrator
 
Join Date: Oct 2006
Location: London - UK
Posts: 15,730
#11: Mar 4 '09

re: Help with Function to return Array - Type Mismatch


Quote:

Originally Posted by lasmith329 View Post

Thanks for everyone's input. With your help and finding just the right tutorial I was able to finally get the function to return an array.

Loren, Let me start by saying thank you for posting your solution. It's always good to see, and furthermore allows us to relax somewhat, in the knowledge that your issue is resolved.

However, there seems to be some confusion, as I see a function which returns a string (not an array).

If that's good for you then we needn't worry about the complexities of returning array data from a function. I will also mention at this stage (it didn't seem relevant before, but now you're working with a string it could be) that there are two very handy functions :
Expand|Select|Wrap|Line Numbers
  1. Split(strData, strSeparator)
  2.      - Converts the data in a string
  3.        to an array using the separator
  4.        specified.
  5. Join(array, strSeparator)
  6.      - Converts the data in an array
  7.        to a string using the separator
  8.        specified.
These functions make working with arrays and strings so much more straightforward.

Welcome to Bytes!
Reply

Tags
access, array, function, mismatch, vba


Similar Microsoft Access / VBA bytes