I am trying to populate and then perform calculations based on a rather large array. This is to populate a binomial tree to calculate option price, so after populating the array I would need to perform repeated calculation so I'd prefer having 3 dimensions in my array for easy reference further down in the code. First dimension is the number of periods that have passed, second dimension is the number of price increases and the third is the number of price decreases.
Dim arr() As Double
Dim periods As Integer
Dim p As Long, i As Long
Dim u As Double, d As Double
Dim iniprice As Double
Let periods = 400
Let iniprice = 100
Let u = 1.1
Let d = 0.9
ReDim arr(0 To periods, 0 To periods, 0 To periods)
Let arr(0, 0, 0) = iniprice
For p = 1 To UBound(arr, 1)
For i = 0 To p
arr(p, i, p - i) = WorksheetFunction.RoundDown(arr(0, 0, 0) * u ^ i * d ^ (p - i), 2)
Next i
Next p
Is this a limitation stemming from the amount of RAM available on my PC (currently having 8Gb) or is this a limitation of VBA itself? Since one period is usually one day, a periods value of 1000 is normal (252 days = 1 trading year).
I also noticed that I have a lot of unused values, because I want to populate only values that have this format arr(p, i, p-i), values such as arr(10,10,10) will be 0. I'd greatly appreciate a workaround to this.
You can try using a single lookup column to represent the 3D array (not the best way but helps with the memory errors):
Dim periods As Integer
Dim p As Long, i As Long
Dim u As Double, d As Double
Dim iniprice As Double
Dim d1 As Long, d2 As Long, d3 As Long, someRow As Long
Dim fndRange As Range
Let periods = 400
Let iniprice = 100
Let u = 1.1
Let d = 0.9
' Col A will be your lookup in format "X-X-X", Col B will hold values
With Sheets("some sheet")
.Range("B1") = iniprice
For d1 = 0 To periods
For d2 = 0 To periods
For d3 = 0 To periods
.Range("A" & someRow).Value = d1 & "-" & d2 & "-" & d3
someRow = someRow + 1
Next
Next
Next
End With
For p = 1 To periods
For i = 0 To p
Set fndRange = Sheets("some sheet").Columns(1).Find(p & "-" & i & "-" & (p-1))
fndRange.Offset(0,1).Value = WorksheetFunction.RoundDown(iniprice * u ^ i * d ^ (p - i), 2)
Next i
Next p
Related
Suppose in column Z with 200 rows, are my optimal averages.
Now I want a macro that generates n random integers between a and b inclusive (n <= 20) so that difference between the average of numbers generated with optimal average is in (-0.15,+0.15).
Example:
Z1:optimal average1=5.5
Z2:optimal average2=5.3
Z200:optimal average200=6.3
n=8
a=1; b=10
numbers of generated:
A1:H1)5-9-4-3-7-4-9-3
A2:H2)10-7-3-2-5-4-3-9
.
.
.
A200:H200)4-8-9-6-6-6-10-2
Here is a hit-or-miss approach (which is often the only viable way to get random numbers which satisfy additional constraints in an unbiased way):
Function RandIntVect(n As Long, a As Long, b As Long, mean As Double, tol As Double, Optional maxTries As Long = 1000) As Variant
'Uses a hit-or-miss approach to generate a vector of n random ints in a,b inclusive whose mean is
'within the tolerance tol of the given target mean
'The function raises an error if maxTries misses occur without a hit
Dim sum As Long, i As Long, j As Long
Dim lowTarget As Double, highTarget As Double 'targets for *sums*
Dim vect As Variant
lowTarget = n * (mean - tol)
highTarget = n * (mean + tol)
For i = 1 To maxTries
ReDim vect(1 To n)
sum = 0
j = 0
Do While j < n And sum + a * (n - j) <= highTarget And sum + b * (n - j) >= lowTarget
j = j + 1
vect(j) = Application.WorksheetFunction.RandBetween(a, b)
sum = sum + vect(j)
Loop
If j = n And lowTarget <= sum And sum <= highTarget Then
'Debug.Print i 'uncomment this line to see how many tries required
RandIntVect = vect
Exit Function
End If
Next i
'error if we get to here
RandIntVect = CVErr(xlErrValue)
End Function
This could be used as a worksheet array formula. The target means were in column I and in A2:H2 I entered =RandIntVect(8,1,10,I2,0.15) (with ctrl+shift+enter as an array formula) and then copied down:
Note that array formulas are volatile, so these numbers would be recalculated every time the worksheet is. You could use the function in VBA to place the numbers directly in the ranges rather than using the function as a worksheet formula. Something like:
Sub test()
Dim i As Long
For i = 1 To 3
Range(Cells(i + 1, 1), Cells(i + 1, 8)).Value = RandIntVect(8, 1, 10, Cells(i + 1, 9).Value, 0.15)
Next i
End Sub
enter image description here
The difference between two means is not within range (0.15+, 0.15-)
I have a set which has an unknown number of objects. I want to associate a label to each one of these objects. Instead of labeling each object with a number I want to label them with letters.
For example the first object would be labeled A the second B and so on.
When I get to Z, the next object would be labeled AA
AZ? then BA, BB, BC.
ZZ? then AAA, AAB, AAC and so on.
I'm working using Mapbasic (similar to VBA), but I can't seem to wrap my head around a dynamic solution. My solution assumes that there will be a max number of objects that the set may or may not exceed.
label = pos1 & pos2
Once pos2 reaches ASCII "Z" then pos1 will be "A" and pos2 will be "A". However, if there is another object after "ZZ" this will fail.
How do I overcome this static solution?
Basically what I needed was a Base 26 Counter. The function takes a parameter like "A" or "AAA" and determines the next letter in the sequence.
Function IncrementAlpha(ByVal alpha As String) As String
Dim N As Integer
Dim num As Integer
Dim str As String
Do While Len(alpha)
num = num * 26 + (Asc(alpha) - Asc("A") + 1)
alpha = Mid$(alpha, 2,1)
Loop
N = num + 1
Do While N > 0
str = Chr$(Asc("A") + (N - 1) Mod 26) & str
N = (N - 1) \ 26
Loop
IncrementAlpha = str
End Function
If we need to convert numbers to a "letter format" where:
1 = A
26 = Z
27 = AA
702 = ZZ
703 = AAA etc
...and it needs to be in Excel VBA, then we're in luck. Excel's columns are "numbered" the same way!
Function numToLetters(num As Integer) As String
numToLetters = Split(Cells(1, num).Address(, 0), "$")(0)
End Function
Pass this function a number between 1 and 16384 and it will return a string between A and XFD.
Edit:
I guess I misread; you're not using Excel. If you're using VBA you should still be able to do this will the help of an reference to an Excel Object Library.
This should get you going in terms of the logic. Haven't tested it completely, but you should be able to work from here.
Public Function GenerateLabel(ByVal Number As Long) As String
Const TOKENS As String = "ZABCDEFGHIJKLMNOPQRSTUVWXY"
Dim i As Long
Dim j As Long
Dim Prev As String
j = 1
Prev = ""
Do While Number > 0
i = (Number Mod 26) + 1
GenerateLabel = Prev & Mid(TOKENS, i, 1)
Number = Number - 26
If j > 0 Then Prev = Mid(TOKENS, j + 1, 1)
j = j + Abs(Number Mod 26 = 0)
Loop
End Function
Beginner looper here...I am working on this well spacing project that looks at lat/longs and determines the next closest well. I think I may be creating an infinite loop or the program is just taking forever to run (It's looping through 15,000 rows). My main struggle has been trying to make sure each location is compared to every location in the dataset. From there I take the 2nd lowest distance (since the lowest will be zero when it compares to itself).
Sub WellSpacing()
Dim r As Integer, c As Integer, L As Integer, lastrow As Integer
Dim lat1 As Double, lat2 As Double, long1 As Double, long2 As Double
Dim distance As Double, d1 As Double, d2 As Double, d3 As Double
Dim PI As Double
PI = Application.WorksheetFunction.PI()
L = 2
r = 3
c = 10
lastrow = Sheets("Test").Cells(Rows.Count, "J").End(xlUp).Row
For L = 2 To lastrow
For r = 2 To lastrow
lat1 = Sheets("Test").Cells(L, c)
long1 = Sheets("Test").Cells(L, c + 1)
lat2 = Sheets("Test").Cells(r, c)
long2 = Sheets("Test").Cells(r, c + 1)
d1 = Sin((Abs((lat2 - lat1)) * PI / 180 / 2)) ^ 2 + Cos(lat1 * PI / 180) * Cos(lat2 * PI / 180) * Sin(Abs(long2 - long1) * PI / 180 / 2) ^ 2
d2 = 2 * Application.WorksheetFunction.Atan2(Sqr(1 - d1), Sqr(d1))
d3 = 6371 * d2 * 3280.84
Sheets("Working").Cells(r - 1, c - 9) = d3
Next r
Sheet2.Activate
Range("A:A").Sort Key1:=Range("A1"), Order1:=xlAscending
distance = Sheet2.Range("A2")
Sheets("Test").Cells(L, c + 2) = distance
Sheet2.Range("A:A").Clear
Sheet1.Activate
Next L
End Sub
I've been working with geo-location math (aka, coordinate geometry) a lot lately and wrote a sub to do pretty much the same thing you're seeking.
Your code probably isn't creating an infinite loop, but calculating distances between thousands of coordinates can be very processor-intensive and even minor changes to your code can have a huge impact on processing time.
Calculating closest coordinate pair: Brute Force Method
There are a number of algorithms for determining closest points however the easiest to code (therefore possibly best for one-time use) is known as the Brute Force Method.
For p1 = 1 to numPoints
For p2 = p1 + 1 to numPoints
...calculate {distance}
...if {distance} < minDistance then minDist = {distance}
Next p2
Next p1
Using this method, distance will be calculated between x * ( n - 1 ) / 2 pairs of points.
For example, a list of 5 points would require 10 comparisons:
Point 1 ↔ Point 2
Point 1 ↔ Point 3
Point 1 ↔ Point 4
Point 1 ↔ Point 5
Point 2 ↔ Point 3
Point 2 ↔ Point 4
Point 2 ↔ Point 5
Point 3 ↔ Point 4
Point 3 ↔ Point 5
Point 4 ↔ Point 5
Since additional points will increase execution time exponentially, this method can create some lengthy processing times, especially on a slower machine or with an excessive number of points.
The methods I use for calculating distances between points and for comparing distances between lists of points are far from the [code-heavier] most-efficient alternatives, but they work for my "one-off" needs.
Depending on my purposes, I'll switch (almost identical code) between Excel & Access, but Access is much faster, so you may want to move your list into a table and do it that way.
One of the lists of points I compare has 252 items, which requires 31,628 individual comparisons using this "easy-code" method. In Excel, the process completes in 1.12 seconds, which is Access it only takes 0.16 seconds.
This may not seem like a big difference until we starting working with longer lists of points: another list of mine (closer to the size of yours) has about 12,000 points, which requires 71,994,000 calculations using the Brute Force method. In Access, the process completes in 8.6 minutes, so I estimate it would take about an hour in Excel.
Of course, all of these times are based on my operating system, processing power, Office version, etc. VBA isn't ideal for this level of computation, and everything you can do to reduce length of code will make a big difference, including commenting-out the status bar updates, immediate-window output, turn off screen updates, etc.
This code is a little messy & un-commented since I slapped it together for my own purposes, but it works for me. Let me know if you have any questions about how it works. All calculations are in metric but can be easily converted.
Sub findShortestDist_Excel()
Const colLatitude = "C" ' Col.C = Lat, Col.D = Lon
Dim pointList As Range, pointCount As Long, c As Range, _
arrCoords(), x As Long, y As Long
Dim thisDist As Double, minDist As Double, minDist_txt As String
Dim cntCurr As Long, cntTotal As Long, timerStart As Single
timerStart = Timer
Set pointList = Sheets("Stops").UsedRange.Columns(colLatitude)
pointCount = WorksheetFunction.Count(pointList.Columns(1))
'build array of numbers found in Column C/D
ReDim arrCoords(1 To 3, 1 To pointCount)
For Each c In pointList.Columns(1).Cells
If IsNumeric(c.Value) And Not IsEmpty(c.Value) Then
x = x + 1
arrCoords(1, x) = c.Value
arrCoords(2, x) = c.Offset(0, 1).Value
End If
Next c
minDist = -1
cntTotal = pointCount * (pointCount + 1) / 2
'loop through array
For x = 1 To pointCount
For y = x + 1 To pointCount
If (arrCoords(1, x) & arrCoords(2, x)) <> (arrCoords(1, y) & arrCoords(2, y)) Then
cntCurr = cntCurr + 1
thisDist = Distance(arrCoords(1, x), arrCoords(2, x), _
arrCoords(1, y), arrCoords(2, y))
'check if this distance is the smallest yet
If ((thisDist < minDist) Or (minDist = -1)) And thisDist > 0 Then
minDist = thisDist
'minDist_txt = arrCoords(1, x) & "," & arrCoords(2, x) & " -> " & arrCoords(1, y) & "," & arrCoords(2, y)
End If
'Application.StatusBar = "Calculating Distances: " & Format(cntCurr / cntTotal, "0.0%")
End If
Next y
'DoEvents
Next x
Debug.Print "Minimum distance: " & minDist_txt & " = " & minDist & " meters"
Debug.Print "(" & Round(Timer - timerStart, 2) & "sec)"
Application.StatusBar = "Finished. Minimum distance: " & minDist_txt & " = " & minDist & "m"
End Sub
Note that the procedure above is dependent on the following (which has slightly different versions for Access vs. Excel):
Excel: Calculate distance between points
Public Function Distance(ByVal lat1 As Double, ByVal lon1 As Double, _
ByVal lat2 As Double, ByVal lon2 As Double) As Double
'returns Meters distance in Excel (straight-line)
Dim theta As Double: theta = lon1 - lon2
Dim Dist As Double: Dist = Math.Sin(deg2rad(lat1)) * Math.Sin(deg2rad(lat2)) + Math.Cos(deg2rad(lat1)) * Math.Cos(deg2rad(lat2)) * Math.Cos(deg2rad(theta))
Dist = rad2deg(WorksheetFunction.Acos(Dist))
Distance = Dist * 60 * 1.1515 * 1.609344 * 1000
End Function
Function deg2rad(ByVal deg As Double) As Double
deg2rad = (deg * WorksheetFunction.PI / 180#)
End Function
Function rad2deg(ByVal rad As Double) As Double
rad2deg = rad / WorksheetFunction.PI * 180#
End Function
...and alternative code, for Microsoft Access:
Access: Shortest Distance
Sub findShortestDist_Access()
Const tableName = "Stops"
Dim pointCount As Long, arrCoords(), x As Long, y As Long
Dim thisDist As Double, minDist As Double
Dim cntCurr As Long, cntTotal As Long, timerStart As Single
Dim rs As Recordset
timerStart = Timer
Set rs = CurrentDb.OpenRecordset("SELECT * FROM " & tableName)
With rs
.MoveLast
.MoveFirst
pointCount = .RecordCount
'build array of numbers found in Column C/D
ReDim arrCoords(1 To 2, 1 To pointCount)
Do While Not .EOF
x = x + 1
arrCoords(1, x) = !stop_lat
arrCoords(2, x) = !stop_lon
.MoveNext
Loop
.Close
End With
minDist = -1
cntTotal = pointCount * (pointCount + 1) / 2
SysCmd acSysCmdInitMeter, "Calculating Distances:", cntTotal
'loop through array
For x = 1 To pointCount
For y = x + 1 To pointCount
cntCurr = cntCurr + 1
thisDist = Distance(arrCoords(1, x), arrCoords(2, x), _
arrCoords(1, y), arrCoords(2, y))
'check if this distance is the smallest yet
If ((thisDist < minDist) Or (minDist = -1)) And thisDist > 0 Then
minDist = thisDist
End If
SysCmd acSysCmdUpdateMeter, cntCurr
Next y
DoEvents
Next x
SysCmd acSysCmdRemoveMeter
Debug.Print "Minimum distance: " & minDist_txt & " = " & minDist & " meters"
Debug.Print "(" & Round(Timer - timerStart, 2) & "sec)"
End Sub
Note that the procedure above is dependent on the following... (Access may handle mass-calculations more quickly, but we have to build some functions ourselves that are built-in to Excel)
Access: Calculate distance between points
Const pi As Double = 3.14159265358979
Public Function Distance(ByVal lat1 As Double, ByVal lon1 As Double, _
ByVal lat2 As Double, ByVal lon2 As Double) As Double
'returns Meters distance in Access (straight-line)
Dim theta As Double: theta = lon1 - lon2
Dim dist As Double
dist = Math.Sin(deg2rad(lat1)) * Math.Sin(deg2rad(lat2)) + Math.Cos(deg2rad(lat1)) _
* Math.Cos(deg2rad(lat2)) * Math.Cos(deg2rad(theta))
dist = rad2deg(aCos(dist))
Distance = dist * 60 * 1.1515 * 1.609344 * 1000
End Function
Function deg2rad(ByVal deg As Double) As Double
deg2rad = (deg * pi / 180#)
End Function
Function rad2deg(ByVal rad As Double) As Double
rad2deg = rad / pi * 180#
End Function
Function aTan2(x As Double, y As Double) As Double
aTan2 = Atn(y / x)
End Function
Function aCos(x As Double) As Double
On Error GoTo aErr
If x = 0 Or Abs(x) = 1 Then
aCos = 0
Else
aCos = Atn(-x / Sqr(-x * x + 1)) + 2 * Atn(1)
End If
Exit Function
aErr:
aCos = 0
End Function
Planar Case
Another method of calculating closer points is called Planar Case. I haven't seen any ready-to-use code samples and I don't need it bad enough to bother coding it, but the gist of it is this:
Read about this and more about the Closest pair of points problem on Wikipedia.
I would recommend using arrays as #Qharr said. I would also look to speed up the process by including some logic steps that avoid doing the complex math on every set of points.
What I mean is that you can do a Rough Estimate first to see whether or not to bother doing the actual calculations. I went with looking at whether or not either the Lat or Long of the current position is closer than the last closest point, but you could do anything you wanted.
I would change your code to something like:
Sub WellSpacing()
Dim R As Integer, C As Integer, L As Integer, LastRow As Integer, Shortest() As Integer
Dim Lats() As Double, Longs() As Double, Distances() As Double
Dim Distance As Double, D1 As Double, D2 As Double, D3 As Double
Dim PI As Double
On Error Resume Next
PI = Application.WorksheetFunction.PI()
L = 2
R = 3
C = 10
LastRow = Sheets("Test").Cells(Rows.Count, 10).End(xlUp).Row
ReDim Lats(1 To (LastRow - 1)) As Double
ReDim Longs(1 To (LastRow - 1)) As Double
ReDim Distances(1 To (LastRow - 1)) As Double
ReDim Shortest(1 To (LastRow - 1)) As Integer
For L = 2 To LastRow
Lats(L - 1) = Sheets("Test").Range("J" & L).Value
Longs(L - 1) = Sheets("Test").Range("K" & L).Value
Next L
For L = 1 To (LastRow - 1)
'This is a method of setting an initial value that can't be obtained through the caclucations (so you will know if any calcs have been done or not).
Distances(L) = -1
For R = 1 To (LastRow - 1)
'This minimises your calculations by 15,000 to begin with
If R = L Then GoTo Skip_This_R
'This skips checking the previous distances if it is the first calculation being checked.
If Distances(L) = -1 Then GoTo Skip_Check
'If there has already been a distance calculated, this does a rough check of whether the Lat or Long is closer. If neither
'the Lat or Long are closer than the current closest, then it will skip it. This reduces the code by 7 lines for most pairs.
If Abs(Lats(L) - Lats(R)) < Abs(Lats(L) - Lats(Shortest(L))) Or Abs(Longs(L) - Longs(R)) < Abs(Longs(L) - Longs(Shortest(L))) Then
Skip_Check:
D1 = Sin((Abs((Lats(R) - Lats(L))) * PI / 180 / 2)) ^ 2 + Cos(Lats(L) * PI / 180) * Cos(Lats(R) * PI / 180) * Sin(Abs(Longs(R) - Longs(L)) * PI / 180 / 2) ^ 2
D2 = 2 * Application.WorksheetFunction.Atan2(Sqr(1 - D1), Sqr(D1))
D3 = 6371 * D2 * 3280.84
If D3 < Distances(L) Or Distances(L) = -1 Then
Distances(L) = D3
'This stores the index value in the array of the closest Lat/Long point so far.
Shortest(L) = R
End If
End If
Skip_This_R:
Next R
'This puts the resulting closest distance into the corresponding cell.
Sheets("Test").Range("L" & (L + 1)).Value = Distances(L)
'This clears any previous comments on the cell.
Sheets("Test").Range("L" & (L + 1)).Comments.Delete
'This adds a nice comment to let you know which Lat/Long position it is closest to.
Sheets("Test").Range("L" & (L + 1)).AddComment "Matched to Row " & (Shortest(L) + 1)
Next L
End Sub
I have a list of distances that I would like to display like you would read off a tape measure, for example 144.125 would display as 144 1/8". I have the following formula
=TEXT(A1,"0"&IF(ABS(A1-ROUND(A1,0))>1/32,"0/"&CHOOSE(ROUND(MOD(A1,1)*16,0),16,8,16,4,16,8,16,2,16,8,16,4,16,8,16),""))&""""
I'd like to simplify it to a 1 argument function (for A1) so I could use it throughout the workbook, but the amount of " quotes and vba keywords is causing problems. Is there an easier way to get a UDF to insert a complicated formula?
If you want to use a UDF with visual basic then try this:
Public Function Fraction(ByVal x As Double, Optional ByVal tol As Double = 1 / 64#) As String
Dim s As Long, w As Long, d As Long, n As Long, f As Double
s = Sgn(x): x = Abs(x)
If s = 0 Then
Fraction = "0"
Exit Function
End If
w = CInt(WorksheetFunction.Floor_Precise(x)): f = x - w
d = CInt(WorksheetFunction.Floor_Precise(1 / tol)): n = WorksheetFunction.Round(f * d, 0)
Dim g As Long
Do
g = WorksheetFunction.Gcd(n, d)
n = n / g
d = d / g
Loop While Abs(g) > 1
Fraction = Trim(IIf(s < 0, "-", vbNullString) + CStr(w) + IIf(n > 0, " " + CStr(n) + "/" + CStr(d), vbNullString))
End Function
With results:
The TEXT function can do this directly:
A B
1 144,1250 144 1/8 "
Formula in B1:
=TEXT(A1;"# ??/??\""")
Greetings
Axel
Im trying to make a program that indefinitely generates rows of Pascal's triangle. I was using integers, singles, etc but kept getting overflows and values of "Infinity" so I tried using biginteger and now it gives me different results. I am using visual studio 2012
This was my output for the first few with integer data type:
1 ,
1 , 1 ,
1 , 2 , 1 ,
1 , 3 , 3 , 1 ,
This was my output for the first few with biginteger data type:
1 ,
1 , 1 ,
1 , 2 , 0 ,
1 , 3 , 3 , 0 ,
The ONLY thing i have changed is the data type. Here is the code for the relevant bit:
n = rows
val(0) = 1
For k = 1 To rows
val(k) = val(k - 1) * (n / k)
n -= 1
Next
rows is the current row (I have this on a timer_tick so that it can run indefinitely and rows increases by 1 each tick)
How can I get the biginteger data type to return the same values as the integer data type?
EDITED as I realized stackoverflow didnt make your linebreaks, Integer is 32 bit while bigint is 64 bit. Fractions can get rounded in different directions when more digits are involved.
To easily avoid rounding errors, you could eliminate division from your code.
e.g.) Here we have a running string and temp string. We split the temp string to calculate the next row only using addition and subtraction.
Dim c As String = "1"
Dim temp As New StringBuilder
Dim f As New StringBuilder
temp.Append(c)
f.Append(temp.ToString)
For n = 1 To 10
Dim a() As String = c.Split(",")
For x = LBound(a) To UBound(a)
If UBound(a) - LBound(a) >= 1 Then
If x = UBound(a) Then
Dim v1 As UInt32 = a(x - 1)
Dim v2 As UInt32 = a(x)
temp.Append((v1) + (v2) & "," & 1)
c = temp.ToString
f.Append(vbCrLf & temp.ToString)
temp.Remove(0, temp.Length)
ElseIf x = LBound(a) Then
Dim v1 As UInt32 = a(x)
Dim v2 As UInt32 = a(x + 1)
temp.Append(1 & "," & (v1) + (v2) & ",")
ElseIf x < UBound(a) - 1 Then
Dim v1 As UInt32 = a(x)
Dim v2 As UInt32 = a(x + 1)
temp.Append((v1) + (v2) & ",")
End If
Else
temp.Remove(0, temp.Length)
temp.Append("1,1")
f.Append(vbCrLf & temp.ToString)
temp.Remove(0, temp.Length)
temp.Append("1,2,1")
f.Append(vbCrLf & temp.ToString)
c = temp.ToString
temp.Remove(0, temp.Length)
End If
Next
Next
MsgBox(f.ToString)