This code looks for the column with header "Quantity Dispensed," then convert the strings in the column by treating the right three digits as decimals, e.i. 00009102" = 9.102
Sub ConvertDec()
Dim colNum As Integer
Dim i As Integer
Dim x As Integer
colNum = WorksheetFunction.Match("Quantity Dispensed", ActiveWorkbook.ActiveSheet.Range("1:1"), 0)
i = 2
Do While ActiveWorkbook.ActiveSheet.Cells(i, colNum).Value <> ""
x = Evaluate(Cells(i, colNum).Value)
Cells(i, colNum) = Int(x / 1000) + (x Mod 1000) / 1000
i = i + 1
Loop
End Sub
I'm getting Overflow error on the line "x = Evaluate..." while executing.
The values in the column are in string form. e.g. "0000120000".
120000 is greater than the maximum value of integer 32768. Use the Long type instead.
Simoco
Related
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
I'm am using the code example below to represent an integer as an alphabetic string
Private Function GetExcelColumnName(columnNumber As Integer) As String
Dim dividend As Integer = columnNumber
Dim columnName As String = String.Empty
Dim modulo As Integer
While dividend > 0
modulo = (dividend - 1) Mod 26
columnName = Convert.ToChar(65 + modulo).ToString() & columnName
dividend = CInt((dividend - modulo) / 26)
End While
Return columnName
End Function
I found the above example here:
Converting Numbers to Excel Letter Column vb.net
How do I get the reverse, for example:
123 = DS -- Reverse -- DS = 123
35623789 = BYXUWS -- Reverse -- BYXUWS = 35623789
Is it possible to get the number from the alphabetic string without importing Excel?
I found an answer from another post. This function below will work to get the reverse
Public Function GetCol(c As String) As Long
Dim i As Long, t As Long
c = UCase(c)
For i = Len(c) To 1 Step -1
t = t + ((Asc(Mid(c, i, 1)) - 64) * (26 ^ (Len(c) - i)))
Next i
GetCol = t
End Function
I have this code below, and I'm getting an overflow error at the line:
s = s + (x Mod 10) [first line in the Do Loop]
Why? I declared x and s to be of type Double. Adding two doubles, why is this not working?
Thanks for your help.
Public Sub bidon1()
Dim i As Double, x As Double, s As Double, k As Byte, h As Byte
Dim y(1 To 6) As Double
For i = 1 To 1000000
x = i ^ 3
Do
s = s + (x Mod 10)
x = x \ 10
Loop Until x = 0
If s = x Then
k = k + 1
y(k) = x
If y(6) > 0 Then
For h = 1 To 6
Debug.Print y(h)
Next
Exit Sub
End If
End If
Next
End Sub
The problem is that the VBA mod operator coerces its arguments to be integers (if they are not already so). It is this implicit coercion which is causing the overflow. See this question: Mod with Doubles
On Edit:
Based on your comments, you want to be able to add together the digits in a largish integer. The following function might help:
Function DigitSum(num As Variant) As Long
'Takes a variant which represents an integer type
'such as Integer, Long or Decimal
'and returns the sum of its digits
Dim sum As Long, i As Long, s As String
s = CStr(num)
For i = 1 To Len(s)
sum = sum + Val(Mid(s, i, 1))
Next i
DigitSum = sum
End Function
The following test sub shows how it can be used to correctly get the sum of the digits in 999999^3:
Sub test()
Dim x As Variant, y As Variant
Debug.Print "Naive approach: " & DigitSum(999999 ^ 3)
y = CDec(999999)
x = y * y * y
Debug.Print "CDec approach: " & DigitSum(x)
End Sub
Output:
Naive approach: 63
CDec approach: 108
Since 999999^3 = 999997000002999999, only the second result is accurate. The first result is only the sum of the digits in the string representation of the double 999999^3 = 9.99997000003E+17
I am banging my head against the wall for a while now trying different techniques.
None of them are working well.
I have two strings.
I need to compare them and get an exact percentage of match,
ie. "four score and seven years ago" TO "for scor and sevn yeres ago"
Well, I first started by comparing every word to every word, tracking every hit, and percentage = count \ numOfWords. Nope, didn't take into account misspelled words.
("four" <> "for" even though it is close)
Then I started by trying to compare every char in each char, incrementing the string char if not a match (to count for misspellings). But, I would get false hits because the first string could have every char in the second but not in the exact order of the second. ("stuff avail" <> "stu vail" (but it would come back as such, low percentage, but a hit. 9 \ 11 = 81%))
SO, I then tried comparing PAIRS of chars in each string. If string1[i] = string2[k] AND string1[i+1] = string2[k+1], increment the count, and increment the "k" when it doesn't match (to track mispellings. "for" and "four" should come back with a 75% hit.) That doesn't seem to work either. It is getting closer, but even with an exact match it is only returns 94%. And then it really gets screwed up when something is really misspelled. (Code at the bottom)
Any ideas or directions to go?
Code
count = 0
j = 0
k = 0
While j < strTempName.Length - 2 And k < strTempFile.Length - 2
' To ignore non letters or digits '
If Not strTempName(j).IsLetter(strTempName(j)) Then
j += 1
End If
' To ignore non letters or digits '
If Not strTempFile(k).IsLetter(strTempFile(k)) Then
k += 1
End If
' compare pair of chars '
While (strTempName(j) <> strTempFile(k) And _
strTempName(j + 1) <> strTempFile(k + 1) And _
k < strTempFile.Length - 2)
k += 1
End While
count += 1
j += 1
k += 1
End While
perc = count / (strTempName.Length - 1)
Edit: I have been doing some research and I think I initially found the code from here and translated it to vbnet years ago. It uses the Levenshtein string matching algorithm.
Here is the code I use for that, hope it helps:
Sub Main()
Dim string1 As String = "four score and seven years ago"
Dim string2 As String = "for scor and sevn yeres ago"
Dim similarity As Single =
GetSimilarity(string1, string2)
' RESULT : 0.8
End Sub
Public Function GetSimilarity(string1 As String, string2 As String) As Single
Dim dis As Single = ComputeDistance(string1, string2)
Dim maxLen As Single = string1.Length
If maxLen < string2.Length Then
maxLen = string2.Length
End If
If maxLen = 0.0F Then
Return 1.0F
Else
Return 1.0F - dis / maxLen
End If
End Function
Private Function ComputeDistance(s As String, t As String) As Integer
Dim n As Integer = s.Length
Dim m As Integer = t.Length
Dim distance As Integer(,) = New Integer(n, m) {}
' matrix
Dim cost As Integer = 0
If n = 0 Then
Return m
End If
If m = 0 Then
Return n
End If
'init1
Dim i As Integer = 0
While i <= n
distance(i, 0) = System.Math.Max(System.Threading.Interlocked.Increment(i), i - 1)
End While
Dim j As Integer = 0
While j <= m
distance(0, j) = System.Math.Max(System.Threading.Interlocked.Increment(j), j - 1)
End While
'find min distance
For i = 1 To n
For j = 1 To m
cost = (If(t.Substring(j - 1, 1) = s.Substring(i - 1, 1), 0, 1))
distance(i, j) = Math.Min(distance(i - 1, j) + 1, Math.Min(distance(i, j - 1) + 1, distance(i - 1, j - 1) + cost))
Next
Next
Return distance(n, m)
End Function
Did not work for me unless one (or both) of following are done:
1) use option compare statement "Option Compare Text" before any Import declarations and before Class definition (i.e. the very, very first line)
2) convert both strings to lowercase using .tolower
Xavier's code must be correct to:
While i <= n
distance(i, 0) = System.Math.Min(System.Threading.Interlocked.Increment(i), i - 1)
End While
Dim j As Integer = 0
While j <= m
distance(0, j) = System.Math.Min(System.Threading.Interlocked.Increment(j), j - 1)
End While
I am creating a function in Excel VBA. I am trying to set a variable equal to the first cell in a selection on the worksheet. Basically the equivalent of something like
x = Worksheets("Data").Range("D2").Offset(i - 1, 0)
y = Worksheets("Data").Range("E2").Offset(i - 1, 0)
z = Worksheets("Data").Range("F2").Offset(i - 1, 0)
except I want "Range("D2")" E2 and F2 to instead refer to the first, second and third cell of whatever I've got highlighted on the sheet, rather than a preset cell.
The specific code I've got is:
Function VarunModel(Table As Range, Optional EndCondition As Integer = 0) As Variant
Dim iNumCols As Integer, iNumRows As Integer
Dim i As Integer
Dim SelectedRange As Range
Set SelectedRange = Selection
iNumCols = Table.Columns.Count
iNumRows = Table.Rows.Count
maturity = Worksheets("KMV-Merton").Range("B2").Value
For i = 1 To iNumRows
equity(i) = SelectedRange.Cells(1).Value
debt(i) = SelectedRange.Cells(2).Value
riskFree(i) = Selection.Cells(3).Value
Next i
Dim equityReturn As Variant: ReDim equityReturn(2 To iNumRows)
Dim sigmaEquity As Double
Dim asset() As Double: ReDim asset(1 To iNumRows)
Dim assetReturn As Variant: ReDim assetReturn(2 To iNumRows)
Dim sigmaAsset As Double, meanAsset As Double
Dim x(1 To 1) As Double, n As Integer, prec As Double, precFlag As Boolean, maxDev As Double
For i = 2 To iNumRows: equityReturn(i) = Log(equity(i) / equity(i - 1)): Next i
sigmaEquity = WorksheetFunction.StDev(equityReturn) * Sqr(260)
sigmaAsset = sigmaEquity * equity(iNumRows) / (equity(iNumRows) + debt(iNumRows))
NextItr: sigmaAssetLast = sigmaAsset
For iptr = 1 To iNumRows
x(1) = equity(iptr) + debt(iptr)
n = 1
prec = 0.00000001
Call NewtonRaphson(n, prec, x, precFlag, maxDev)
asset(iptr) = x(1)
Next iptr
For i = 2 To iNumRows: assetReturn(i) = Log(asset(i) / asset(i - 1)): Next i
sigmaAsset = WorksheetFunction.StDev(assetReturn) * Sqr(260)
meanAsset = WorksheetFunction.Average(assetReturn) * 260
If (Abs(sigmaAssetLast - sigmaAsset) > prec) Then GoTo NextItr
Dim disToDef As Double: disToDef = (Log(asset(iNumRows) / debt(iNumRows)) + (meanAsset - sigmaAsset ^ 2 / 2) * maturity) / (sigmaAsset * Sqr(maturity))
Dim defProb As Double: defProb = WorksheetFunction.NormSDist(-disToDef)
VarunModel = defProb
End Function
Thanks.
Try the below code
Dim SelectedRange As Range
Set SelectedRange = Selection
x = SelectedRange.Cells(1).Value
y = SelectedRange.Cells(2).Value
z = SelectedRange.Cells(3).Value
try this:
Dim Row as integer
Dim Col as Integer
Row = 2
Col = 4 'column "D"
x = Worksheets("Data").cells(row, col).Offset(i - 1, 0)
col = col + 1
y = Worksheets("Data").cells(row, col).Offset(i - 1, 0)
col = col + 1
z = Worksheets("Data").cells(row, col).Offset(i - 1, 0)
See the example below for using the selection on the excel, you can control the column you want by changing the column index. If you select only 1 cell, it will also work:
Sub Solution()
x = Selection.Cells(1, 0) 'By using the zero index on the column, it will get the left cell from the selected one.
y = Selection.Cells(2, 0)
Z = Selection.Cells(3, 0)
End Sub