I need macro excel code which will check if my string is in the correct format - vba

Here is my entire code and I will explain it and what I want to add.
The first function is calling two other functions.
The second function is used to calculate JMBG, which is unique number of citizen in my country. The third one is calculating PIB, which is registered number for companies.
Those two functions are OK and they don't need to be moved or anything like that.
We need to change this first function. As you can see, in the first function I am checking whether the length of the input string is OK. If the length is 13 numbers I call JMBG and if it is 8 I call PIB function. That is OK.
But I must check other types of validation in this first function. As I said, my Excel cell contains 13 numbers or 8 numbers. I want to make some rules in this first function that will tell me if my cell is filled with anything else except those 8 numbers or 13, then send me msg telling me that there is error in the cell and those 2 other functions then won't be called. As you can see, I need validation.
Example: Cell A1: 1234567891234...there is 13 numbers and JMBG will be called
08058808...there is 8 numbers and PIB will be called
1234567890123aSdf~...error because small and big letters and other characters are in the field.
As sum of all this, I need for 8 numbers to call PIB, for 13 numbers to call JMBG and for anything else except that to send me error.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Function ProvjeraID(ID As String) As String
If Len(ID) = 13 Then
ProvjeraID = Provjeri_JMBG(ID)
'Exit Function
ElseIf Len(ID) = 8 Then
ProvjeraID = ProvjeriPIB(ID)
'Exit Function
Else
ProvjeraID = "Duzina je razlicita od 8 i od 13"
'Exit Function
End If
End Function
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Function Provjeri_JMBG(JMBG As String) As String
' Funkcija vraca tekst sa opisom ispravnosti JMBG
' Primijeniti na radnom listu uz pomoc komande: =Proveri_JMBG(adresa)
' Inicijalizacija promenljivih koje se koriste prilikom izrade koda
Dim duzina As Integer, zbir As Integer
Dim cifra(1 To 13) As Integer
Dim dan As Integer, mesec As Integer, godina As String
' Inicijalizacija konstanti
Const ERR_dan = "GREŠKA: podatak o datumu neispravan!"
Const ERR_mesec = "GREŠKA: podatak o mesecu neispravan!"
Const ERR_godina = "GREŠKA: podatak o godini neispravan!"
Const ERR_duzina = "GREŠKA: dužina razlicita od 13!"
Const ERR_kont = "GREŠKA: neispravan kontrolni broj!"
Const OK_JMBG = "JMBG je ispravan"
' Preuzimanje ulaznih vrednosti sa kojima ce se vrsiti operacije
duzina = Len(JMBG)
dan = Int(Left(JMBG, 2))
mesec = Int(Mid$(JMBG, 3, 2))
godina = Mid$(JMBG, 5, 3)
' Provjera dužine JMBG
If (duzina <> 13) Then
Provjeri_JMBG = "GREŠKA: dužina razlicita od 13!"
Exit Function
End If
' Provjera datuma
If dan < 1 Then
Provjeri_JMBG = "GREŠKA: podatak o datumu neispravan!"
Exit Function
End If
' Provjera mjeseca i dana u mjesecu
Select Case mesec
Case 1, 3, 5, 7, 8, 10, 12
If dan > 31 Then
Provjeri_JMBG = "GREŠKA: podatak o datumu neispravan!"
Exit Function
End If
Case 4, 6, 9, 11
If dan > 30 Then
Provjeri_JMBG = "GREŠKA: podatak o datumu neispravan!"
Exit Function
End If
Case 2
If ((godina Mod 4 = 0) And dan > 29) Or _
((godina Mod 4 <> 0) And dan > 28) Then
Provjeri_JMBG = "GREŠKA: podatak o datumu neispravan!"
Exit Function
End If
Case Else
Provjeri_JMBG = "GREŠKA: podatak o mesecu neispravan!"
Exit Function
End Select
' Provjera godine: ispravne su od 1899 do tekuce godine
If (godina > Right(Str(Year(Now)), 3)) And (godina < "899") Then
Provjeri_JMBG = "GREŠKA: podatak o godini neispravan!"
Exit Function
End If
' Provjera kontrolnog broja
For i = 1 To 13
cifra(i) = Int(Mid$(JMBG, i, 1))
Next i
zbir = cifra(13) + cifra(1) * 7 + cifra(2) * 6
zbir = zbir + cifra(3) * 5 + cifra(4) * 4
zbir = zbir + cifra(5) * 3 + cifra(6) * 2
zbir = zbir + cifra(7) * 7 + cifra(8) * 6
zbir = zbir + cifra(9) * 5 + cifra(10) * 4
zbir = zbir + cifra(11) * 3 + cifra(12) * 2
If (zbir Mod 11) <> 0 Then
Provjeri_JMBG = "GREŠKA: neispravan kontrolni broj!"
Else
Provjeri_JMBG = "JMBG je ispravan"
End If
End Function
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Public Function ProvjeriPIB(PIB As String)
Dim c0 As Integer
Dim c1 As Integer
Dim c2 As Integer
Dim c3 As Integer
Dim c4 As Integer
Dim c5 As Integer
Dim c6 As Integer
Dim c7 As Integer
Dim c8 As Integer
Dim zadnji As String
zadnji = Right(PIB, 1)
PIB = Left(PIB, 8)
If Len(PIB) <> 8 Then
ProvjeriPIB = "PIB je OK"
Else
c8 = (CInt(Mid(PIB, 1, 1)) + 10) Mod 10
If c8 = 0 Then
c8 = 10
End If
c8 = (c8 * 2) Mod 11
c7 = (CInt(Mid(PIB, 2, 1)) + c8) Mod 10
If c7 = 0 Then
c7 = 10
End If
c7 = (c7 * 2) Mod 11
c6 = (CInt(Mid(PIB, 3, 1)) + c7) Mod 10
If c6 = 0 Then
c6 = 10
End If
c6 = (c6 * 2) Mod 11
c5 = (CInt(Mid(PIB, 4, 1)) + c6) Mod 10
If c5 = 0 Then
c5 = 10
End If
c5 = (c5 * 2) Mod 11
c4 = (CInt(Mid(PIB, 5, 1)) + c5) Mod 10
If c4 = 0 Then
c4 = 10
End If
c4 = (c4 * 2) Mod 11
c3 = (CInt(Mid(PIB, 6, 1)) + c4) Mod 10
If c3 = 0 Then
c3 = 10
End If
c3 = (c3 * 2) Mod 11
c2 = (CInt(Mid(PIB, 7, 1)) + c3) Mod 10
If c2 = 0 Then
c2 = 10
End If
c2 = (c2 * 2) Mod 11
c1 = (CInt(Mid(PIB, 8, 1)) + c2) Mod 10
If c1 = 0 Then
c1 = 10
End If
c1 = (c1 * 2) Mod 11
c0 = (11 - c1) Mod 10
If c0 <> zadnji Then
ProvjeriPIB = "PIB je OK"
Else
ProvjeriPIB = "PIB nije OK"
End If
'return(pib || to_char(c0));
End If
End Function

This solution is based on regex from Scripting library. I have used 3 objects, but code definitely be trimmed to use just one object to check for all three conditions that you required. Since you wanted information about the text that you are inserting I have merely used 3 different regex rules.
Option Explicit
Sub TextNature()
Dim str As String
Dim strMsg As String
Dim objRegEx1 As Object, objRegEx2 As Object
Dim objRegEx3 As Object
str = Sheets(1).Range("A2").Value
'--check length
If Len(str) <> 13 Then
Exit Sub
strMsg = "Too lengthy...limit should be 13"
End If
Set objRegEx1 = CreateObject("VBScript.RegExp")
Set objRegEx2 = CreateObject("VBScript.RegExp")
Set objRegEx3 = CreateObject("VBScript.RegExp")
objRegEx1.IgnoreCase = False
objRegEx1.Global = True
objRegEx2.IgnoreCase = False
objRegEx2.Global = True
objRegEx3.IgnoreCase = False
objRegEx3.Global = True
objRegEx1.Pattern = "^\d+$" '-- only numbers
objRegEx2.Pattern = "^[a-zA-Z]+$" '-- only lower upper letters
objRegEx3.Pattern = "^[a-zA-Z\d]+$" '-- numbers and lower upper letters
If objRegEx1.Test(str) Then
strMsg = "Contain only numbers"
ElseIf objRegEx2.Test(str) Then
strMsg = "Contain only lower upper letters"
ElseIf objRegEx3.Test(str) Then
strMsg = "Contain numbers and lower upper letters"
Else
strMsg = "not satisfying"
End If
End Sub
Results : used the sub as a function:
OP requests for a function, and length limit to be 8:
Option Explicit
Function TextNature(ByRef rng As Range) As String
Dim str As String, strMsg As String
Dim objRegEx1 As Object, objRegEx2 As Object, objRegEx3 As Object
str = rng.Value
If Len(str) <> 8 Then
TextNature = "Limit is not correct. It should be 8."
Exit Function
End If
Set objRegEx1 = CreateObject("VBScript.RegExp")
Set objRegEx2 = CreateObject("VBScript.RegExp")
Set objRegEx3 = CreateObject("VBScript.RegExp")
objRegEx1.IgnoreCase = False
objRegEx1.Global = True
objRegEx2.IgnoreCase = False
objRegEx2.Global = True
objRegEx3.IgnoreCase = False
objRegEx3.Global = True
objRegEx1.Pattern = "^\d+$" '-- only numbers
objRegEx2.Pattern = "^[a-zA-Z]+$" '-- only lower/upper letters
objRegEx3.Pattern = "^[a-zA-Z\d]+$" '-- numbers and lower/upper letters
If objRegEx1.Test(str) Then
strMsg = "Contain only numbers"
ElseIf objRegEx2.Test(str) Then
strMsg = "Contain only lower upper letters"
ElseIf objRegEx3.Test(str) Then
strMsg = "Contain numbers and lower upper letters"
Else
strMsg = "Not Satisfying"
End If
TextNature = strMsg
End Function

Something like this should help - you can define the criteria in the select statement. It's a UDF so put the code into a module and enter =checkcell(A1) into a cell.
Public Function CheckCell(ByVal CheckRange As Range) As String
Dim strChr As String, rngCheck As Range
Dim i As Integer, NPC As Integer, UC As Integer, LC As Integer, OT As Integer
Set rngCheck = Range("A1")
For i = 1 To rngCheck.Characters.Count
strChr = rngCheck.Characters(i, 1).Text
Select Case Asc(strChr)
Case 0 To 31
NPC = NPC + 1
Case 96 To 122
LC = LC + 1
Case 65 To 90
UC = UC + 1
Case Else
OT = OT + 1
End Select
Next
CheckCell = "NPC: " & NPC & " UC: " & UC & " LC: " & LC & " Others: " & OT
End Function

In case formula-based solution is OK - use this ARRAY formula (assuming string for checking is in A1):
=IF(OR(NOT(ISERROR(SEARCH(ROW($1:$10)-1,A1)))),"Has digits","No digits")
and press CTRL+SHIFT+ENTER instead of usual ENTER - this will define an ARRAY formula and will result in {} brackets around it (but do NOT type them manually!).
String length and any other chars do not matter. Hope that was helpful)

Replace your first function with something like the following, and call it in a cell using =ProvjeraID2(A1) to evaluate the contents of cell A1:
Function ProvjeraID2(oRng As Range) As String
Dim sRet As String
If Not oRng Is Nothing Then
If IsNumeric(oRng.Value) Then
If Len(oRng.Value) = 13 Then
sRet = Provjeri_JMBG(CStr(oRng.Value))
ElseIf Len(oRng.Value) = 8 Then
sRet = ProvjeriPIB(CStr(oRng.Value))
Else
sRet = "Numeric but wrong length (" & Len(oRng.Value) & ")"
End If
Else
sRet = "Not a number"
End If
End If
ProvjeraID2 = sRet
End Function

Related

VB.Net Drawing Binary Trees

Essentially, the purpose of this program is for revision. The program will generate a random mathematical expression, convert this into a visual representation of a binary tree and the user will have to traverse the binary tree. However, when I run this code, the initial node is far off centre. How would I go about re-positioning the binary tree to be in the middle of the PictureBox? Here is my code:
Public Class BTT
'VARAIBLES DECLARED CANNOT BE A FAULT
Dim nodes(7) As Object
'maybe try to alter the form so that the user can only get two incorrect answers'
Dim operators(6) As String
Dim actualAnswer As String = ""
Dim ogEquation(11) As String
Dim newLabel As String = "" 'used to store the equation to be stored in the label'
Dim userAnswer As String
Dim myTime As Double
Dim traversal(3) As String
Dim selectedTraversal As String
Dim treeCounter As Integer = 0
Dim draw As Boolean = False
Structure tree
Dim name As String
Dim left As Integer
Dim right As Integer
End Structure
Dim TreeNode(7) As tree
Dim scoreValue As Integer = 0 'stores the user's score for the game just completed'
Dim updating As Boolean = False 'if there are already 10 scores, the first one will need to be removed, so updating = true'
Class node
Public lineColour As Color
Public lineWidth As Integer
Public posX As Integer
Public posY As Integer
Public radius As Integer
Public Sub draw(e As PaintEventArgs)
Dim myPen As New Pen(Me.lineColour, Me.lineWidth)
e.Graphics.DrawEllipse(myPen, Me.posX, Me.posY, Me.radius, Me.radius)
End Sub
End Class
Sub DrawTree()
'these are the coordinates of the top left of the PictureBox
Dim leftX As Integer = 171
Dim rightX As Integer = 171 + PictureBox1.Width 'will be set to the edge of the picturebox
Dim topY As Integer = 138
Dim bottomY As Integer = 138 + PictureBox1.Height 'will be that number of pixels down, WILL NEVER CHANGE
Dim currentNode As Integer = 1 'will initially be the root node
For i = 1 To treeCounter 'loops based on the number of nodes in the array'
'assigns the basic information common to all of the nodes
nodes(i) = New node
nodes(i).radius = 70
nodes(i).lineWidth = 2
nodes(i).lineColour = Color.Black
Next
'need to go through the binary tree and determine x & y positions, with labels inside the ellipses
ConstructTree(currentNode, leftX, rightX, topY, bottomY)
draw = True
PictureBox1.Refresh()
End Sub
Sub ConstructTree(ByRef currentNode As Integer, ByRef leftX As Integer, ByRef rightX As Integer, ByRef topY As Integer, ByRef bottomY As Integer)
'ASK ISABEL ABOUT DYNAMICALLY GENERATING A LABEL'
'e.g. Dim test As New Label
nodes(currentNode).posX = (leftX + rightX) / 2 'gets average of x coordinates'
nodes(currentNode).posY = topY + ((bottomY - topY) * (1 / 3)) 'gets number of pixels down between bottom of form & last node, goes a third of the way down
If TreeNode(currentNode).left <> 0 Then 'if there is a node to the left
ConstructTree(TreeNode(currentNode).left, leftX, (leftX + rightX) / 2, nodes(currentNode).posY, bottomY)
End If
If TreeNode(currentNode).right <> 0 Then 'if there is a node to the right
ConstructTree(TreeNode(currentNode).right, (leftX + rightX) / 2, rightX, nodes(currentNode).posY, bottomY) 'swaps the left and right x-coords which have been changed
End If
End Sub
Private Sub PictureBox1_Paint(sender As Object, e As PaintEventArgs) Handles PictureBox1.Paint
If draw = True Then
For i = 1 To treeCounter
nodes(i).draw(e)
Next
'ALSO need to draw lines between the nodes, but IGNORE FOR NOW
End If
End Sub
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
TextBox1.Text = myTime - (0.1)
myTime = TextBox1.Text
If myTime = 0 Then
Timer1.Enabled = False
MsgBox("Time is up!")
checkupdate()
resetForm()
End If
'add another if statement checking for two wrong answers, will stop the timer and tell the user that they have got too man questions wrong'
End Sub
Sub resetForm()
Score.Text = "Score:"
Label1.Text = ""
scoreValue = 0
End Sub
Sub writefile()
FileOpen(1, "BTTscores.txt", OpenMode.Output)
Select Case updating
Case True
For i = 2 To 11
WriteLine(1, scores(i))
Next
Case False
For i = 1 To numberOfScores + 1
WriteLine(1, scores(i))
Next
End Select
FileClose()
End Sub
Sub checkupdate()
'need to check whether there are already ten elements in the array. If so, then delete the first score, move all the indices of the other scores 1 to the left and add the new scores on the end'
numberOfScores = 0 'will need to be reset if the user carries on using the program'
FileOpen(1, "BTTscores.txt", OpenMode.Input) 'need to bubble sort values'
Dim line As String
Do Until EOF(1)
line = LineInput(1)
If line <> "" Then
numberOfScores = numberOfScores + 1
scores(numberOfScores) = line 'copies the line to the array'
End If
Loop
If numberOfScores = 10 Then 'if one needs to be updated, need to read all but the first line into the array'
updating = True
scores(11) = scoreValue
Else 'if there are less than 10 scores, the user's current score just needs to be added on the end'
updating = False
scores(numberOfScores + 1) = scoreValue
End If
FileClose(1)
writefile()
End Sub
Private Sub EnterButton_Click(sender As Object, e As EventArgs) Handles EnterButton.Click
userAnswer = Answer.Text
If actualAnswer.Replace(" ", "") = userAnswer.Replace(" ", "") Then
UpdateScore()
End If
Score.Text = ("Score: " & scoreValue)
Answer.Text = ""
InitialSetup()
End Sub
Sub UpdateScore()
Select Case difficulty
Case "Easy"
scoreValue = scoreValue + 10
Case "Medium"
scoreValue = scoreValue + 15
Case "Hard"
scoreValue = scoreValue + 20
End Select
End Sub
Private Sub StartButton_Click(sender As Object, e As EventArgs) Handles StartButton.Click
scoreValue = 0
Initialisation()
InitialSetup()
myTime = 60
Timer1.Enabled = True
End Sub
Sub InitialSetup()
Dim currentNode As Integer = 1 'will be root node'
actualAnswer = ""
GetEquation()
newLabel = ""
selectedTraversal = traversal(CInt(Math.Floor((3 - 1 + 1) * Rnd())) + 1) 'will choose a random traversal'
newLabel = "Traversal: " + selectedTraversal
Label1.Text = newLabel
If selectedTraversal = "Prefix" Then
PrefixConversion(currentNode)
ElseIf selectedTraversal = "Infix" Then
InfixConversion()
Else
RPConversion()
End If
DrawTree()
End Sub
Sub Initialisation()
operators(1) = "("
operators(2) = "-"
operators(3) = "+"
operators(4) = "*"
operators(5) = "/"
operators(6) = ")"
traversal(1) = "Prefix"
traversal(2) = "Infix"
traversal(3) = "Postfix"
End Sub
Sub GetEquation()
Select Case difficulty
'RANDOM NUMBER FORMAT: CInt(Math.Floor((upperbound - lowerbound + 1) * Rnd())) + lowerbound'
Case "Easy"
'FORMAT: 17 * 4'
treeCounter = 3
ogEquation(1) = CInt(Math.Floor((20 - 1 + 1) * Rnd())) + 1
ogEquation(2) = operators(CInt(Math.Floor((5 - 2 + 1) * Rnd())) + 2)
ogEquation(3) = CInt(Math.Floor((20 - 1 + 1) * Rnd())) + 1
'initialising the binary tree iteration'
TreeNode(1).name = ogEquation(2) 'operator is the root'
TreeNode(1).left = 2
TreeNode(1).right = 3
TreeNode(2).name = ogEquation(1)
TreeNode(3).name = ogEquation(3)
'EG: * 17 4
Case "Medium"
treeCounter = 5
'FORMAT: 15 * (17 + 4)'
ogEquation(1) = CInt(Math.Floor((50 - 1 + 1) * Rnd())) + 1
ogEquation(2) = operators(CInt(Math.Floor((5 - 2 + 1) * Rnd())) + 2)
ogEquation(3) = operators(1)
ogEquation(4) = CInt(Math.Floor((50 - 1 + 1) * Rnd())) + 1
ogEquation(5) = operators(CInt(Math.Floor((5 - 2 + 1) * Rnd())) + 2)
ogEquation(6) = CInt(Math.Floor((50 - 1 + 1) * Rnd())) + 1
ogEquation(7) = operators(6)
'initialising the binary tree iteration'
TreeNode(1).name = ogEquation(2) 'root node'
TreeNode(1).left = 2
TreeNode(1).right = 3
TreeNode(2).name = ogEquation(1)
TreeNode(3).name = ogEquation(5)
TreeNode(3).left = 4
TreeNode(3).right = 5
TreeNode(4).name = ogEquation(4)
TreeNode(5).name = ogEquation(6)
'EG: * 15 + 17 4
Case "Hard"
'FORMAT: (17 + 4) * (20 / 10), random numbers are 1-150'
treeCounter = 7
ogEquation(1) = operators(1)
ogEquation(2) = CInt(Math.Floor((150 - 1 + 1) * Rnd())) + 1
ogEquation(3) = operators(CInt(Math.Floor((5 - 2 + 1) * Rnd())) + 2)
ogEquation(4) = CInt(Math.Floor((150 - 1 + 1) * Rnd())) + 1
ogEquation(5) = operators(6)
ogEquation(6) = operators(CInt(Math.Floor((5 - 2 + 1) * Rnd())) + 2)
ogEquation(7) = operators(1)
ogEquation(8) = CInt(Math.Floor((150 - 1 + 1) * Rnd())) + 1
ogEquation(9) = operators(CInt(Math.Floor((5 - 2 + 1) * Rnd())) + 2)
ogEquation(10) = CInt(Math.Floor((150 - 1 + 1) * Rnd())) + 1
ogEquation(11) = operators(6)
'initialising the binary tree iteration'
TreeNode(1).name = ogEquation(6) 'root node'
TreeNode(1).left = 2
TreeNode(1).right = 5
TreeNode(2).name = ogEquation(3)
TreeNode(2).left = 3
TreeNode(2).right = 4
TreeNode(3).name = ogEquation(2)
TreeNode(4).name = ogEquation(4)
TreeNode(5).name = ogEquation(9)
TreeNode(5).left = 6
TreeNode(5).right = 7
TreeNode(6).name = ogEquation(8)
TreeNode(7).name = ogEquation(10)
'EG: * + 17 4 / 20 10
End Select
End Sub
'Traversal Solutions'
'Postfix Conversion'
Sub RPConversion()
Dim myStack As New Stack(15)
Dim empty As Boolean = True
Dim temp As String 'used to store the current part of the original equation'
Dim operatorNum As Integer
Dim peekNum As Integer
Dim stoploop As Boolean = True
For i = 1 To ogEquation.Count - 1 'will iterate through the total number of elements in the array ogEquation'
If myStack.Count = 0 Then empty = True
temp = ogEquation(i)
MatchTempOperation(myStack, temp, operatorNum)
If operatorNum > 1 And operatorNum < 6 Then 'if the value is an operator'
If myStack.Count <> 0 Then 'if the stack contains a value'
CheckPeek(myStack, peekNum)
If operatorNum > peekNum Then
myStack.Push(temp)
ElseIf operatorNum = peekNum Then
actualAnswer = actualAnswer + myStack.Pop()
myStack.Push(temp)
Else 'operatorNum < peekNum'
actualAnswer = actualAnswer + myStack.Pop()
Do
stoploop = True
CheckPeek(myStack, peekNum)
If operatorNum > peekNum Then
myStack.Push(temp)
ElseIf operatorNum = peekNum Then
actualAnswer = actualAnswer + myStack.Pop()
myStack.Push(temp)
Else
actualAnswer = actualAnswer + myStack.Pop()
stoploop = False
End If
Loop Until stoploop Or myStack.Count = 0
End If
Else
myStack.Push(temp)
End If
ElseIf temp = "(" Then
myStack.Push(temp)
ElseIf temp = ")" Then
Do
actualAnswer = actualAnswer + myStack.Pop()
Loop Until myStack.Peek() = "("
myStack.Pop()
Else
actualAnswer = actualAnswer + temp
End If
operatorNum = 0
Next
If myStack.Count > 0 Then
For i = 1 To myStack.Count
actualAnswer = actualAnswer + myStack.Pop()
Next
End If
End Sub
Sub CheckPeek(ByVal myStack As Stack, ByRef peekNum As Integer) 'does the same as MatchTempOperation but for the top of the stack'
For i = 2 To 5 'skip one and six because we know it isn't a left or right bracket'
If myStack.Peek() = operators(i) Then
peekNum = i
End If
Next
End Sub
Sub MatchTempOperation(ByVal myStack As Stack, ByVal temp As String, ByRef operatorNum As Integer) 'wants to look at the stack but not be able to change it'
For i = 1 To 6
If temp = operators(i) Then
operatorNum = i
End If
Next
End Sub
'Infix'
Sub InfixConversion()
For i = 1 To 11
'check each element for empty spaces / brackets'
If ogEquation(i) <> "" And ogEquation(i) <> "(" And ogEquation(i) <> ")" Then
actualAnswer = actualAnswer + ogEquation(i)
End If
Next
End Sub
'Prefix'
Sub PrefixConversion(ByRef currentNode As Integer)
actualAnswer = actualAnswer + TreeNode(currentNode).name
If TreeNode(currentNode).left <> 0 Then
PrefixConversion(TreeNode(currentNode).left)
End If
If TreeNode(currentNode).right <> 0 Then
PrefixConversion(TreeNode(currentNode).right)
End If
End Sub
Private Sub ExitButton_Click(sender As Object, e As EventArgs) Handles ExitButton.Click
Me.Hide()
End Sub
End Class
Apologies for it's inefficiency, please also note that the "difficulty" variable is Public and stored outside of this form. Thanks :)
OUTPUT:
enter image description here
As you can see, the root node is far off centre in the bottom left.

Algorithmn: Cut Company name into 3 Strings, did I miss a case?

Hello I wrote an algorithmn which should cut a companies name into 3 strings.
Input 1 String
Output 3 String.
Conditions:
String 1 2 and 3 shall not be longer then 35 signs.
If the Input string is longer then 105 it only shall be cut.
If you have fun and be interested in algorithmns it would be nice if you take a look at it.
I´m happy for every input
Cheers B101
Public Sub CompanyCut()
//3 output Strings
Dim var1 As String = ""
Dim var2 As String = ""
Dim var3 As String = ""
If Module1.insertdict("company").Length > 35 Then
Dim s1 As String = Module1.insertdict("company").ToString
If s1.Length > 105 Then
s1 = Microsoft.VisualBasic.Left(s1, 105)
End If
//Split String into array at every Whitespace
Dim pattern As String = "\s"
Dim sa() As String = Regex.Split(s1, pattern)
//Variables for loop
Dim i As Integer = 0
Dim varyn As Boolean = True
Dim varyn1 As Boolean = False
Dim varyn2 As Boolean = False
//loop which fills var1 var2 and var3 with arrayfields untill size 35
would be reached
For i = 0 To sa.Length - 1
If var1.Length < 35 AndAlso varyn = True Then
If var1.Length + 1 + sa(i).Length < 35 Then
var1 = var1 + " " + sa(i).ToString
Else
varyn = False
varyn1 = True
varyn2 = False
End If
End If
If var2.Length < 35 AndAlso varyn1 = True Then
If var2.Length + 1 + sa(i).Length < 35 Then
var2 = var2 + " " + sa(i).ToString
Else
varyn1 = False
varyn = False
varyn2 = True
End If
End If
If var3.Length < 35 AndAlso varyn2 = True Then
If var3.Length + 1 + sa(i).Length < 35 Then
var3 = var3 + " " + sa(i).ToString
Else
varyn2 = False
End If
End If
Next
//my idea was that if it has the same or bigger length all fields must
be in + the whitespaces
If var1.Length + var2.Length + var3.Length >= s1.Length Then
Module1.insertdict("Firma") = var1
Module1.insertdict("Name2") = var2
Module1.insertdict("Name3") = var3
Else
//this occurs when the string is smaller as 105 signs but not all
fields of the array could be placed in the variables.
Module1.insertdict("Failure") = "Company name need to split by user"
End If
Else
Module1.insertdict("Name2") = ""
Module1.insertdict("Name3") = ""
End If
End Sub

vbscript, using counting variable to identify other variables

I have variables el1, el2,....el16 and c1, c2,....c16 and Counter
Would like to use in a counting loop
For Counter = 1 to 16
If el1 = "x" Then
el1 = 0
c1 = 0
Else
c1 = 1
End If
Next
The If statement works fine with defined variables. How can I combine the "Counter" variable with the "el" and "c" in the loop to recognize as el1, c1, el2, c2,...el16, c16
Here is the final version of the script. It worked fine in Windows 7 version of ArcPad, but the If statement blew up on the mobile device using mobile vbscript runtime libraries. The variable array method might work better, but I wasn't quite sure how to patch it in. Any help would be appreciated.
Sub findelement
Dim el1, el2, el3, el4, el5, el6, el7, el8, el9, el10, el11, el12, el13, el14, el15, el16, scoreA, scoreB, calc
el1 = EDITFORM.Pages.Item("page4").Controls.Item("element1")
el2 = EDITFORM.Pages.Item("page4").Controls.Item("element2")
el3 = EDITFORM.Pages.Item("page4").Controls.Item("element3")
el4 = EDITFORM.Pages.Item("page4").Controls.Item("element4")
el5 = EDITFORM.Pages.Item("page4").Controls.Item("element5")
el6 = EDITFORM.Pages.Item("page4").Controls.Item("element6")
el7 = EDITFORM.Pages.Item("page4").Controls.Item("element7")
el8 = EDITFORM.Pages.Item("page4").Controls.Item("element8")
el9 = EDITFORM.Pages.Item("page5").Controls.Item("element9")
el10 = EDITFORM.Pages.Item("page5").Controls.Item("element10")
el11 = EDITFORM.Pages.Item("page5").Controls.Item("element11")
el12 = EDITFORM.Pages.Item("page5").Controls.Item("element12")
el13 = EDITFORM.Pages.Item("page5").Controls.Item("element13")
el14 = EDITFORM.Pages.Item("page5").Controls.Item("element14")
el15 = EDITFORM.Pages.Item("page5").Controls.Item("element15")
el16 = EDITFORM.Pages.Item("page5").Controls.Item("element16")
Dim c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, Counter
For Counter = 1 to 16
If "x" = eval ("el" & Counter) Then
execute "el" & Counter & " = 0"
execute "c" & Counter & " = 0"
Else
execute "c" & Counter & " = 1"
End If
Next
'do math
scoreA = CInt(el1) + CInt(el2) + CInt(el3) + CInt(el4) + CInt(el5) + CInt(el6) + CInt(el7) + CInt(el8) + CInt(e9) + CInt(el10) + CInt(el11) + CInt(el12) + CInt(el13) + CInt(el14) + CInt(el15) + CInt(el16)
scoreB = CInt(c1) + CInt(c2) + CInt(c3) + CInt(c4) + CInt(c5) + CInt(c6) + CInt(c7) + CInt(c8) + CInt(c9) + CInt(c10) + CInt(c11) + CInt(c12) + CInt(c13) + CInt(c14) + CInt(c15) + CInt(c16)
calc = CDbl(scoreA) / CDbl(scoreB)
'vbscript assumes these are strings and appends them, to get the sum like you want cast them to a double (CDbl) or integer (CInt)
'MsgBox (scoreA)
'MsgBox (scoreB)
'MsgBox (calc)
'Return calculated data to form.....
EDITFORM.Pages("Results").Controls("sumEl").Value = (scoreA)
EDITFORM.Pages("Results").Controls("scoreB").Value = (scoreB)
EDITFORM.Pages("Results").Controls("calc").Value = (calc)
End Sub
You can use Execute, ExecuteGlobal and Eval to dynamically form variable names for expressions to execute:
Execute "el" & Counter & " = 42"
In general, Eval/Execute/ExecuteGlobal are dangerous, inefficient, and
unnecessary. There are exception (e.g. library/module import, (quick and dirty)
calculations based on user input), but I doubt that your (real) problem can't be
solved without such Voodoo.
Compare:
Dim el1, el2, el3
el1 = "a"
el2 = "x"
el3 = "b"
WScript.Echo "el:", el1, el2, el3
Dim c1, c2, c3
Dim i
For i = 1 to 3
If "x" = Eval("el" & i) Then
Execute "el" & i & " = 0"
Execute "c" & i & " = 0"
Else
Execute "c" & i & " = 1"
End If
Next
WScript.Echo "el:", el1, el2, el3
WScript.Echo " c:", c1, c2, c3
output:
el: a x b
el: a 0 b
c: 1 0 1
(idea stolen from Helen)
With:
Dim sEL : sEL = "a x b"
Dim oWAN : Set oWAN = WScript.Arguments.Named
If oWAN.Exists("el") Then sEL = oWAN("el")
Dim aEL : aEL = Split(sEL)
WScript.Echo "aEL:", Join(aEL)
ReDim aC(UBound(aEL))
Dim i
For i = 0 to UBound(aEL)
If "x" = aEL(i) Then
aEL(i) = 0
aC(i) = 0
Else
aC(i) = 1
End If
Next
WScript.Echo "aEL:", Join(aEL)
WScript.Echo " aC:", Join(aC)
output (no arg):
aEL: a x b
aEL: a 0 b
aC: 1 0 1
output (arg: /el:"a a a x b x x c x"):
aEL: a a a x b x x c x
aEL: a a a 0 b 0 0 c 0
aC: 1 1 1 0 1 0 0 1 0
I think, you'll agree that using a collection/array gives you as much flexibility
as the eval/execute approach.

problem with programming playfair cipher

I have problem with my code
Public Class Form1
Dim lm(4, 4) As Char
Dim pt As String = ""
Dim ct As String = ""
Dim key As String = ""
Dim n1, n2, n3, n4, m1, m2, m3, m4 As Integer
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
key = k.Text
key.Replace(" ", "")
pt = plaintext.Text
If pt.Length Mod 2 <> 0 Then
pt = pt & "e"
End If
pt = UCase(pt)
pt.Replace("J", "I")
Dim Value As String
Dim NewValue As String
key.Replace("J", "I")
Value = key & "ABCDEFGHIKLMNOPQRSTUVWXYZ"
NewValue = ""
Value = UCase(Value)
NewValue = Value(0)
For i As Integer = 1 To Value.Length - 1
If Not (InStr(1, NewValue, Value(i)) > 0) Then
NewValue = NewValue & Value(i)
End If
Next
Dim p As Integer = 0
For n As Integer = 0 To 4
For m As Integer = 0 To 4
lm(n, m) = NewValue(p)
p = p + 1
Next
Next
Dim leave As Boolean = False
For q As Integer = 0 To pt.Length - 1 Step 2
For n1 = 0 To 4
For m1 = 0 To 4
If lm(n1, m1).Equals(pt(q)) Then
leave = True
Exit For
End If
Next
If leave Then
Exit For
End If
Next
leave = False
For n2 = 0 To 4
For m2 = 0 To 4
If lm(n2, m2).Equals(pt(q + 1)) Then
leave = True
Exit For
End If
Next
If leave Then
Exit For
End If
Next
If n1 = n2 Then
If m1 >= 4 Then
m3 = 0
Else
m3 = m1 + 1
End If
If m2 >= 4 Then
m4 = 0
Else
m4 = m2 + 1
End If
ElseIf m1 = m2 Then
If n1 >= 4 Then
n3 = 0
Else
n3 = n1 + 1
End If
If n2 >= 4 Then
n4 = 0
Else
n4 = n2 + 1
End If
Else
n3 = n1
m3 = m2
n4 = n2
m4 = m1
End If
ct = ct & lm(n3, m3) & lm(n4, m4)
Next
ciphertext.Text = ct
ct = ""
End Sub
End Class
it gives error in this line ct = ct & lm(n3, m3) & lm(n4, m4)array out of range
I cuoldn't find why can someone help me ?
Ah, spotted : )
Dim leave As Boolean = False
For q As Integer = 0 To pt.Length - 1 Step 2
For n1 = 0 To 4
You set it to false before the first iteration and inside the loop just before the (q+1)
leave = False
For n2 = 0 To 4
You need to reset leave = False every time you loop:
Dim leave As Boolean
For q As Integer = 0 To pt.Length - 1 Step 2
leave = False ' This was missing
For n1 = 0 To 4
For a shorter code, try:
(a,b,f,g,c)="".join(input("CODE: ").split()),input("Polybius S: "),"","",1
for(i)in(a):
if(c%2)==0:
g+=i
else:
f+=i
c+=1
for(j)in(range(0,len(f))):
if(b.find(f[j])%5)!=(b.find(g[j])%5)and(int(((b.find(f[j]))-(b.find(f[j])%5))/5))!=(int(((b.find(g[j]))-(b.find(g[j])%5))/5)):
print(b[((int(((b.find(f[j]))-(b.find(f[j])%5))/5))*5)+(b.find(g[j])%5)],end="")
print(b[((int(((b.find(g[j]))-(b.find(g[j])%5))/5))*5)+(b.find(f[j])%5)],end="")
elif(b.find(f[j])%5)==(b.find(g[j])%5)and(int(((b.find(f[j]))-(b.find(f[j])%5))/5))!=(int(((b.find(g[j]))-(b.find(g[j])%5))/5)):
print(b[((((int(((b.find(f[j]))-(b.find(f[j])%5))/5))-1)%5)*5)+b.find(f[j])%5],end="")
print(b[((((int(((b.find(g[j]))-(b.find(g[j])%5))/5))-1)%5)*5)+b.find(g[j])%5],end="")
elif(b.find(f[j])%5)!=(b.find(g[j])%5)and(int(((b.find(f[j]))-(b.find(f[j])%5))/5))==(int(((b.find(g[j]))-(b.find(g[j])%5))/5)):
print(b[((int(((b.find(f[j]))-(b.find(f[j])%5))/5))*5)+((b.find(f[j])%5)-1)%5],end="")
print(b[((int(((b.find(g[j]))-(b.find(g[j])%5))/5))*5)+((b.find(g[j])%5)-1)%5],end="")
OK maybe not that short. Or simple

What could be slowing down my Excel VBA Macro?

This function goes through all integers and picks out binary values with only five ones and writes them to the spreadsheet.
To run this For x = 1 To 134217728 would take 2.5 days!!!! Help!
How could I speed this up?
Function D2B(ByVal n As Long) As String
n = Abs(n)
D2B = ""
Do While n > 0
If n = (n \ 2) * 2 Then
D2B = "0" & D2B
Else
D2B = "1" & D2B
n = n - 1
End If
n = n / 2
Loop
End Function
Sub mixtures()
Dim x As Long
Dim y As Integer
Dim fill As String
Dim mask As String
Dim RowOffset As Integer
Dim t As Date
t = Now
fill = ""
For x = 1 To 134217728
mask = Right(fill & CStr(D2B(x)), Len(fill & CStr(D2B(x))))
Debug.Print mask
If x > 100000 Then Exit For
If Len(mask) - Len(WorksheetFunction.Substitute(mask, "1", "")) = 5 Then _
RowOffset = RowOffset + 1
For y = 1 To Len(mask)
If Len(mask) - Len(WorksheetFunction.Substitute(mask, "1", "")) = 5 Then _
Range("mix").Offset(RowOffset).Cells(y) = Mid(mask, y, 1)
Next
Next
Debug.Print DateDiff("s", Now, t)
End Sub
By first sight guess, I think the problem lies in the fact that you do that cell by cell, which causes many read and write accesses.
You should do it range by range, like
vArr = Range("A1:C1000").Value
' it is array now, do something here effeciently
Range("A1:C1000").Value = vArr
You want find all 28bit numbers with 5 1s
There are 28*27*26*25*24/5/4/3/2=98280 such numbers
The following code took ~10 seconds on my PC:
lineno = 1
For b1 = 0 To 27
For b2 = b1 + 1 To 27
For b3 = b2 + 1 To 27
For b4 = b3 + 1 To 27
For b5 = b4 + 1 To 27
Cells(lineno, 1) = 2 ^ b1 + 2 ^ b2 + 2 ^ b3 + 2 ^ b4 + 2 ^ b5
lineno = lineno + 1
Next
Next
Next
Next
Next
mask = Right(fill & CStr(D2B(x)), Len(fill & CStr(D2B(x))))
The above line of code does the same thing (CStr(D2B(x))) twice.
Store the result of CStr(D2B(x)) in a variable & use that variable in the above line of code.
I've got 2 suggestions:
Get rid of the substitution command by counting the ones/zeroes in D2B and return an empty string if the count does not equal 5
Write these pre-filtered bitstrings to an array first and copy the array directly to the cells when finished.
Something like
ws.Range(ws.cells(1, 1), ws.cells(UBound(dstArr, 1) + 1, UBound(dstArr, 2) + 1)) = dstArr
The array-copy-trick greatly improves performance!