PDA

View Full Version : Putting a mid function into a loop



Pakally
05-26-2012, 02:05 AM
Hello there!

I have recently started learning VBA in IT classes and I have an assignment to create a function that converts a 64-digit binary number into a hexadecimal number.

This was my idea:
-Create a sting that is defined by an input box
-Check the length of the string and create an error report if it has less than 64 digits
(And now comes the part that I'm having trouble with)
-Use the mid function to split the binary number into 16 parts each containing four digits
-Define a hexadecimal digit for each possible combination of the four digits
The thing I'm having trouble with is putting it in a loop.
The VBA editor tells me that the types are not compatible and selects the "For StrPart = Mid (BinZahl, 4, 4) To..."

Here is my attempt.
It would be great if some one could tell me what I am doing wrong and/or give me a hint on how to get it to work without having to type out each part of the binary individually.
PS the German in the code is because I am living in Germany, but I don't think it should be too confusing :)

Thanks in advance

Public Sub BinHexCalc()
Dim BinZahl As String
BinZahl = InputBox("Bitte geben Sie eine 64-stellige Binärzahl ein.")
Dim HexZahl As String
Dim iLen As Integer
Dim strPart As String
iLen = Len(BinZahl)
If iLen < 64 Then
MsgBox ("Ihre Zahl hat weniger, als 64 Stellen")
End If

For strPart = Mid(BinZahl, 4, 4) To Mid(BinZahl, 64, 4) Step -4

If strPart = "0000" Then
HexZahl = "0" + HexZahl
End If

If strPart = "0001" Then
HexZahl = "1" + HexZahl
End If

If strPart = "0010" Then
HexZahl = "2" + HexZahl
End If

If strPart = "0011" Then
HexZahl = "3" + HexZahl
End If

If strPart = "0100" Then
HexZahl = "4" + HexZahl
End If

If strPart = "0101" Then
HexZahl = "5" + HexZahl
End If

If strPart = "0110" Then
HexZahl = "6" + HexZahl
End If

If strPart = "0111" Then
HexZahl = "7" + HexZahl
End If

If strPart = "1000" Then
HexZahl = "8" + HexZahl
End If

If strPart = "1001" Then
HexZahl = "9" + HexZahl
End If

If strPart = "1010" Then
HexZahl = "A" + HexZahl
End If

If strPart = "1011" Then
HexZahl = "B" + HexZahl
End If

If strPart = "1100" Then
HexZahl = "C" + HexZahl
End If

If strPart = "1101" Then
HexZahl = "D" + HexZahl
End If

If strPart = "1110" Then
HexZahl = "E" + HexZahl
End If

If strPart = "1111" Then
HexZahl = "F" + HexZahl
End If

Next strPart

MsgBox HexZahl

End Sub

gmaxey
05-26-2012, 05:33 AM
What if someone passed string with values other that 0 or 1? Try this:

Option Explicit
Sub Demo()
Dim strIn As String
strIn = "1111000010100101"
MsgBox ConvertBinaryToHex(strIn)
End Sub
Function ConvertBinaryToHex(strPassed As String) As String
Dim lngLen As Long, i As Long
Dim vHex As Variant
lngLen = Len(strPassed)
If lngLen < 64 Then
ConvertyBinaryToHex = "Ihre Zahl hat weniger, als 64 Stellen"
Exit Function
End If
For i = lngLen To 1 Step -1
'Check the string for invalid characters
Select Case Asc(Mid(strPassed, i, 1))
Case 48, 49
'Process valid input.
If Mid(strPassed, i, 1) And 1 Then
vHex = vHex + 2 ^ Abs(i - lngLen)
End If
Case Else
vHex = ""
ConvertBinaryToHex = "Invalid Input"
Exit Function
End Select
Next i
'Return vHex as String
ConvertBinaryToHex = Hex(vHex)
End Function

Pakally
05-26-2012, 06:32 AM
Hi Greg.

Thanks for your quick reply.

Looks like it would solve the problem, but I'm not allowed to copy entire codes off the internet or from other people.

But I managed to find another solution (even if my code is a little longer than yours :doh: ).

Thanks for the hint about the possibility of someone adding a digit other than 1 or 0

Is there a way to tell the program to return to the original input box rather than ending it if that happens?

Paul_Hossler
05-26-2012, 08:37 AM
1. strPart is dimmed as a string, but you're trying to use it as loop index

For strPart = Mid(BinZahl, 4, 4) To Mid(BinZahl, 64, 4) Step -4

2. You could use If ... ElseIf .... ElseIF ..... Endif instead of all the If/Then/Endif. After all, once you have a successful match, you don't need to check anymore. Look in Help for Select Case

3. Always a good idea to use Option Explicit in your modules (see Help)

4. I usually use a Do / Loop Until construct to handle re-getting bad input corrected.

5. Examples of concepts for your own code


Option Explicit
Public Sub BinHexCalc()
Dim BinZahl As String
Dim HexZahl As String
Dim iLen As Long, iPart As Long
Dim bGoodInput As Boolean

bGoodInput = True

Do
BinZahl = InputBox("Bitte geben Sie eine 64-stellige Binärzahl ein.")

iLen = Len(BinZahl)

If iLen < 64 Then
bGoodInput = False
MsgBox ("Ihre Zahl hat weniger, als 64 Stellen")

Else
For iPart = 61 To 1 Step -4

Select Case Mid(BinZahl, iPart, 4)
Case "0000": HexZahl = "0" + HexZahl
Case "0001": HexZahl = "1" + HexZahl
Case "0010": HexZahl = "2" + HexZahl
Case "0011": HexZahl = "3" + HexZahl
Case "0100": HexZahl = "4" + HexZahl
Case "0101": HexZahl = "5" + HexZahl
Case "0110": HexZahl = "6" + HexZahl
Case "0111": HexZahl = "7" + HexZahl

Case "1000": HexZahl = "8" + HexZahl
Case "1001": HexZahl = "9" + HexZahl
Case "1010": HexZahl = "A" + HexZahl
Case "1011": HexZahl = "B" + HexZahl
Case "1100": HexZahl = "C" + HexZahl
Case "1101": HexZahl = "D" + HexZahl
Case "1110": HexZahl = "E" + HexZahl
Case "1111": HexZahl = "F" + HexZahl
Case Else
bGoodInput = False
End Select

Next iPart

If Not bGoodInput Then
MsgBox "Bad input"
Else
MsgBox HexZahl
End If

End If

Loop Until bGoodInput

End Sub



Paul

Pakally
05-26-2012, 09:42 AM
Wow, this forum definitely seems better than the German Office forum.
Thanks for the replies.

gmaxey
05-26-2012, 10:44 AM
If you can get two or more values from a function if you create a user defined type. Here you want to know a) Was the value passed valid and b)what is the string value of the converted input passed.

Option Explicit
Type typConverter
strOut As String
bValid As Boolean
End Type
Sub Demo()
Dim result As typConverter
Dim strIn As String
Do
strIn = InputBox("Enter a binary string", "Input")
result = ConvertBinaryToHex(strIn)
MsgBox result.strOut
Loop Until result.bValid = True
End Sub
Function ConvertBinaryToHex(strPassed As String) As typConverter
Dim lngLen As Long, i As Long
Dim vHex As Variant
ConvertBinaryToHex.bValid = False
lngLen = Len(strPassed)
If lngLen < 64 Then
ConvertBinaryToHex.strOut = "Ihre Zahl hat weniger, als 64 Stellen"
Exit Function
End If
For i = lngLen To 1 Step -1
'Check the string for invalid characters
Select Case Asc(Mid(strPassed, i, 1))
Case 48, 49
'Process valid input.
If Mid(strPassed, i, 1) And 1 Then
vHex = vHex + 2 ^ Abs(i - lngLen)
End If
Case Else
vHex = ""
ConvertBinaryToHex.strOut = "Invalid Input"
Exit Function
End Select
Next i
'Return vHex as String
ConvertBinaryToHex.strOut = Hex(vHex)
ConvertBinaryToHex.bValid = True
End Function

Frosty
05-29-2012, 11:25 AM
Another concept is the difference between ByVal and ByRef in VBA. Most parameters are passed ByRef, as a default. What does this mean?

It means that, as an alternative to using a custom Type as a function return when needing multiple return values, you can also simply populate parameters within a function and reference them outside of a function. Although I like Greg's approach, there are times when it may not be the best approach. As an alternative, here is a demo of another way of using a function where you need multiple returns:

Sub Demo
Dim sParam1 As String
Dim sParam2 As String
Dim bReturn As Boolean

sParam1 = "Before"
sParam2 = "I change"
'the variables as they first exist
MsgBox sParam1 & " " & sParam2

'but if we pass them ByRef to our function, and our function returns true...
If fDemo(sParam1, sParam2) Then
'then see how the messagebox is different... because the variables were returned "changed"
MsgBox sParam1 & " " & sParam2
End If
End Sub
'See the difference in the above subroutine if you insert "ByVal" before each of these parameter names
'Function fDemo (ByVal sOneThing As String, ByVal sAnotherThing As String) As Boolean
Function fDemo (sOneThing As String, sAnotherThing As String) As Boolean
sOneThing = "Hello"
sAnotherThing = "World"
fDemo = True
End Function

Paul_Hossler
05-29-2012, 01:35 PM
Greg / Frosty -- UDT's and ByRef/ByVal

You're pushing the OP into the advanced course :clap:

Paul

Frosty
05-29-2012, 02:08 PM
It's true. But I'm sure the course will cover it at some point, and then the OP will learn that UDTs mean "User Defined Types" and there will be more stuff to read up on in the help file.

I appreciate that the OP requested hints rather than answers... so I was trying to cover the conceptual hints ;)

You put in the harder stuff... Do ... Loops with steps and Mid ;)

Personally, I would separate out the data validation from the data analysis. But there are so many ways to structure items, I make this comment not as a "this is better" but just as a different approach.

As a bit of a brain teaser, I think I'd probably use the following function to determine whether to do any processing at all...
I don't know if this kind of "Is" function exists elsewhere in the system, but it doesn't seem to exist in VBA in Word 2010.

'pass in a value ByVal since we'll manipulate in the routine to determine whether it is a valid binary number
'can pass in "0000 1110 11110110" or "01011101101"
Public Function IsBinary(ByVal sExpression As String) As Boolean
Dim bRet As Boolean
Dim sChar As String
Dim i As Integer

'any errors, and we assume the passed string is not something which is binary
On Error GoTo l_err

'allow the passing in of blank spaces
sExpression = Replace(sExpression, " ", "")
'if not empty, and is numeric-- it might be binary
If Len(sExpression) > 0 And IsNumeric(sExpression) Then
'make sure the only characters in this string are 0s and 1s
For i = 1 To Len(sExpression)
sChar = Mid(sExpression, i, 1)
Select Case sChar
Case "0", "1"
bRet = True
Case Else
bRet = False
Exit For
End Select
Next
End If

l_exit:
IsBinary = bRet
Exit Function
l_err:
bRet = False
Resume l_exit
End Function
A couple concerns I would have with the input box method:
1) empty spaces at the beginning or end
2) typing 64 characters absolutely correctly

So I would test for more than just 64 characters (you could easily have 63 chars and a space... and go through a whole bunch of processing before you find out you've got a bad input). The processing isn't a big deal time-wise, but it's a bit of a pain when stepping through code to analyze, so I would want to break apart whether I wanted to attempt to convert it to hexadecimal first).

Frosty
05-29-2012, 02:13 PM
Two concepts in the above code which may be helpful...
1) using the string manipulation function "Replace" to get rid of any spaces in the potential string. Similar to a Trim/LTrim/RTrim, this has the advantage of getting rid of any spaces which would cause a problem.
2) Breaking apart multiple pieces of functionality, so that you can test those components without testing the whole system (i.e., this process requires 3 separate pieces: a) should you try to convert? (determine bad input) b) is it a valid length (determine valid good input) and c) the actual hexidecimal result.

If you break these different pieces apart, you can give your end-user a better hint on why the function broke. i.e.,
"Unable to process-- does not appear to be a binary string."
"Unable to process-- must be 64 digits long."
"Unable to process-- unanticipated error"

Etc etc... the more you break a function apart, the easier it is to not just troubleshoot your own code, but to give valid error messages to the end-user.

Frosty
05-29-2012, 02:29 PM
This is a good assignment, because (to me) the hardest part about it is actually the easiest part -- conversion to hex. That's the part that VBA will do for you, with the "Hex" function. So the best "hint" would be to not spend so much of your coding time on that part (that is your extended Select Case or If...Else If...End if structure will you convert valid strings to a hex value by hand (i.e., "0000" becomes "0", etc))... but rather thinking about the various ways your InputBox methodology can be stymied by an end-user not putting in the right stuff, and how you can help your end user put in the right stuff.

I don't want to say too much more, without giving it away...

The rest of it is

Frosty
05-30-2012, 11:09 AM
Haha, I clearly posted an incomplete sentence... but it ends up looking like I'm teasing the OP.

What I meant to say was...

The rest of it is all logic, structure and data validation. The actual conversion of binary to hex is incidental to the real lesson. I like.

fumei
05-30-2012, 10:35 PM
"logic, structure and data validation"

ah yes, all part of that OVERT ruse...