Bitwise And with Large Numbers in VBA - vba

I keep getting an Overflow on the bitwise and in this first function. I fixed the other overflows by converting from Long to Currency (still seems weird), but I can't get this And to work.
Any ideas? I'm just trying to convert some IP addresses to CIDRs and calculate some host numbers.
Option Explicit
Public Function ConvertMaskToCIDR(someIP As String, someMask As String)
Dim ipL As Variant
ipL = iPToNum(someIP)
Dim maskL As Variant
maskL = iPToNum(someMask)
maskL = CDec(maskL)
'Convert Mask to CIDR(1-30)
Dim oneBit As Variant
oneBit = 2147483648#
oneBit = CDec(oneBit)
Dim CIDR As Integer
CIDR = 0
Dim x As Integer
For x = 31 To 0 Step -1
If (maskL And oneBit) = oneBit Then
CIDR = CIDR + 1
Else
Exit For
End If
oneBit = oneBit / 2# 'Shift one bit to the right (>> 1)
Next
Dim answer As String
answer = numToIp(ipL And maskL) & " /" & CStr(CIDR)
End Function
Public Function NumHostsInCidr(CIDR As Integer) As Currency
Dim mask As Currency
mask = maskFromCidr(CIDR)
NumHostsInCidr = iPnumOfHosts(mask)
End Function
Private Function maskFromCidr(ByVal CIDR As Integer) As Currency
'x = 32 - CIDR
'z = (2^x)-1
'return z xor 255.255.255.255
maskFromCidr = CLng(2 ^ ((32 - CIDR)) - 1) Xor 4294967295# '255.255.255.255
End Function
Private Function iPnumOfHosts(ByVal IPmsk As Currency) As Currency 'a mask for the host portion
'255.255.255.0 XOR 255.255.255.255 = 255 so 0 to 255 is 256 hosts
iPnumOfHosts = IPmsk Xor 4294967295# '255.255.255.255 , calculate the number of hosts
End Function
Private Function numToIp(ByVal theIP As Currency) As String 'convert number back to IP
Dim IPb(3) As Byte '4 octets
Dim theBit As Integer
theBit = 31 'work MSb to LSb
Dim addr As String 'accumulator for address
Dim x As Integer
For x = 0 To 3 'four octets
Dim y As Integer
For y = 7 To 0 Step -1 '8 bits
If (theIP And CLng(2 ^ theBit)) = CLng(2 ^ theBit) Then 'if the bit is on
IPb(x) = IPb(x) + CByte(2 ^ y) 'accumulate
End If
theBit = theBit - 1
Next
addr = addr & CStr(IPb(x)) & "." 'add current octet to string
Next
numToIp = trimLast(addr, ".")
End Function
Private Function iPToNum(ByVal ip As String) As Currency
Dim IPpart As Variant
Dim IPbyte(3) As Byte
IPpart = Split(ip, ".")
Dim x As Integer
For x = 0 To 3
IPbyte(x) = CByte(IPpart(x))
Next x
iPToNum = (IPbyte(0) * (256 ^ 3)) + (IPbyte(1) * (256 ^ 2)) + (IPbyte(2) * 256#) + IPbyte(3)
End Function
Private Function trimLast(str As String, chr As String)
'****
'* Remove "chr" (if it exists) from end of "str".
'****
trimLast = str
If Right(str, 1) = chr Then trimLast = Left(str, Len(str) - 1)
End Function

Whoah,
it is definitelly interesting functionality. But I would do this in very different way. I would treat IP adress and Mask as array of four bytes. Moreover as far as I remeber (well it was some time ago) CIDR and mask can be converted to each other in very simply way (did you looked at the table?). Why don't you apply bitwise operations to each byte separatelly?
BR.
edit: ok I looked closer at the code. The reason why it is overflowing is that you can't use currency and and. I think and is internally defined as Long and can't return any bigger values. It is very common in other languages too. I remember that once I had this problem in other language (Pascal?). You can try to replace and by division. It will be slow but it can't be matter here I suppose. Other solution is, like I wrote, to treat those valueas all the time as byte arrays and perform bitwise operations on each byte.

This is an entirely mathematical approach to working with IPv4 addresses in VBA (Excel specifically).
The first three functions are serving a strictly supporting role.
Support #1:
Public Function RoundDouble(ByVal Number As Double, ByVal Places As Long) As Double
On Error GoTo Err_RoundDouble
Dim i As Long
Dim j As Long
i = 0
j = 0
While Number < -(2 ^ 14)
Number = Number + (2 ^ 14)
i = i - 1
Wend
While Number > (2 ^ 14)
Number = Number - (2 ^ 14)
i = i + 1
Wend
While Number < -(2 ^ 5)
Number = Number + (2 ^ 5)
j = j - 1
Wend
While Number > (2 ^ 5)
Number = Number - (2 ^ 5)
j = j + 1
Wend
RoundDouble = Round(Number, Places) + (i * (2 ^ 14)) + (j * (2 ^ 5))
Exit_RoundDouble:
Exit Function
Err_RoundDouble:
MsgBox Err.Description
Resume Exit_RoundDouble
End Function
Support #2:
Public Function RoundDownDouble(ByVal Number As Double, ByVal Places As Long) As Double
On Error GoTo Err_RoundDownDouble
Dim i As Double
i = RoundDouble(Number, Places)
If Number < 0 Then
If i < Number Then
RoundDownDouble = i + (10 ^ -Places)
Else
RoundDownDouble = i
End If
Else
If i > Number Then
RoundDownDouble = i - (10 ^ -Places)
Else
RoundDownDouble = i
End If
End If
Exit_RoundDownDouble:
Exit Function
Err_RoundDownDouble:
MsgBox Err.Description
Resume Exit_RoundDownDouble
End Function
Support #3
Public Function ModDouble(ByVal Number As Double, ByVal Divisor As Double) As Double
On Error GoTo Err_ModDouble
Dim rndNumber As Double
Dim rndDivisor As Double
Dim intermediate As Double
rndNumber = RoundDownDouble(Number, 0)
rndDivisor = RoundDownDouble(Divisor, 0)
intermediate = rndNumber / rndDivisor
ModDouble = (intermediate - RoundDownDouble(intermediate, 0)) * rndDivisor
Exit_ModDouble:
Exit Function
Err_ModDouble:
MsgBox Err.Description
Resume Exit_ModDouble
End Function
This first function will convert a Double back into an IP address.
Public Function NUMtoIP(ByVal Number As Double) As String
On Error GoTo Err_NUMtoIP
Dim intIPa As Double
Dim intIPb As Double
Dim intIPc As Double
Dim intIPd As Double
If Number < 0 Then Number = Number * -1
intIPa = RoundDownDouble(ModDouble(Number, (2 ^ 32)) / (2 ^ 24), 0)
intIPb = RoundDownDouble(ModDouble(Number, (2 ^ 24)) / (2 ^ 16), 0)
intIPc = RoundDownDouble(ModDouble(Number, (2 ^ 16)) / (2 ^ 8), 0)
intIPd = ModDouble(Number, (2 ^ 8))
NUMtoIP = intIPa & "." & intIPb & "." & intIPc & "." & intIPd
Exit_NUMtoIP:
Exit Function
Err_NUMtoIP:
MsgBox Err.Description
Resume Exit_NUMtoIP
End Function
This second function is strictly to convert from IPv4 dotted octet format to a Double.
Public Function IPtoNUM(ByVal IP_String As String) As Double
On Error GoTo Err_IPtoNUM
Dim intIPa As Integer
Dim intIPb As Integer
Dim intIPc As Integer
Dim intIPd As Integer
Dim DotLoc1 As Integer
Dim DotLoc2 As Integer
Dim DotLoc3 As Integer
Dim DotLoc4 As Integer
DotLoc1 = InStr(1, IP_String, ".", vbTextCompare)
DotLoc2 = InStr(DotLoc1 + 1, IP_String, ".", vbTextCompare)
DotLoc3 = InStr(DotLoc2 + 1, IP_String, ".", vbTextCompare)
DotLoc4 = InStr(DotLoc3 + 1, IP_String, ".", vbTextCompare)
If DotLoc1 > 1 And DotLoc2 > DotLoc1 + 1 And _
DotLoc3 > DotLoc2 + 1 And DotLoc4 = 0 Then
intIPa = CInt(Mid(IP_String, 1, DotLoc1))
intIPb = CInt(Mid(IP_String, DotLoc1 + 1, DotLoc2 - DotLoc1))
intIPc = CInt(Mid(IP_String, DotLoc2 + 1, DotLoc3 - DotLoc2))
intIPd = CInt(Mid(IP_String, DotLoc3 + 1, 3))
If intIPa <= 255 And intIPa >= 0 And intIPb <= 255 And intIPb >= 0 And _
intIPc <= 255 And intIPc >= 0 And intIPd <= 255 And intIPd >= 0 Then
IPtoNUM = (intIPa * (2 ^ 24)) + (intIPb * (2 ^ 16)) + _
(intIPc * (2 ^ 8)) + intIPd
Else
IPtoNUM = 0
End If
Else
IPtoNUM = 0
End If
Exit_IPtoNUM:
Exit Function
Err_IPtoNUM:
MsgBox Err.Description
Resume Exit_IPtoNUM
End Function
Next we have the conversion from an IPv4 address to it's bitmask representation (assuming that the source entry is a string containing only the dotted octet format of the subnet mask).
Public Function IPtoBitMask(ByVal strIP_Address As String) As Integer
On Error GoTo Err_IPtoBitMask
IPtoBitMask = (32 - Application.WorksheetFunction.Log((2 ^ 32 - IPtoNUM(strIP_Address)), 2))
Exit_IPtoBitMask:
Exit Function
Err_IPtoBitMask:
MsgBox Err.Description
Resume Exit_IPtoBitMask
End Function
This last one is to convert a bitmask back into dotted octet format.
Public Function BitMasktoIP(ByVal intBit_Mask As Integer) As String
On Error GoTo Err_BitMasktoIP
BitMasktoIP = NUMtoIP((2 ^ 32) - (2 ^ (32 - intBit_Mask)))
Exit_BitMasktoIP:
Exit Function
Err_BitMasktoIP:
MsgBox Err.Description
Resume Exit_BitMasktoIP
End Function
Edited to remove leftover debugging code (it's been working for me so long, that I had entirely forgotten about it).
As an aside, it is faster to perform mathematical operations on a computer than it is to work with a string.

This was my "cheating" way:
Option Explicit
Public Function ConvertMaskToCIDR(varMask As Variant) As String
Dim strCIDR As String
Dim mask As String
mask = CStr(varMask)
Select Case mask
Case "255.255.255.255":
strCIDR = "/32"
Case "255.255.255.254":
strCIDR = "/31"
Case "255.255.255.252":
strCIDR = "/30"
Case "255.255.255.248":
strCIDR = "/29"
Case "255.255.255.240":
strCIDR = "/28"
Case "255.255.255.224":
strCIDR = "/27"
Case "255.255.255.192":
strCIDR = "/26"
Case "255.255.255.128":
strCIDR = "/25"
Case "255.255.255.0":
strCIDR = "/24"
Case "255.255.254.0":
strCIDR = "/23"
Case "255.255.252.0":
strCIDR = "/22"
Case "255.255.248.0":
strCIDR = "/21"
Case "255.255.240.0":
strCIDR = "/20"
Case "255.255.224.0":
strCIDR = "/19"
Case "255.255.192.0":
strCIDR = "/18"
Case "255.255.128.0":
strCIDR = "/17"
Case "255.255.0.0":
strCIDR = "/16"
Case "255.254.0.0":
strCIDR = "/15"
Case "255.252.0.0":
strCIDR = "/14"
Case "255.248.0.0":
strCIDR = "/13"
Case "255.240.0.0":
strCIDR = "/12"
Case "255.224.0.0":
strCIDR = "/11"
Case "255.192.0.0":
strCIDR = "/10"
Case "255.128.0.0":
strCIDR = "/9"
Case "255.0.0.0":
strCIDR = "/8"
Case "254.0.0.0":
strCIDR = "/7"
Case "252.0.0.0":
strCIDR = "/6"
Case "248.0.0.0":
strCIDR = "/5"
Case "240.0.0.0":
strCIDR = "/4"
Case "224.0.0.0":
strCIDR = "/3"
Case "192.0.0.0":
strCIDR = "/2"
Case "128.0.0.0":
strCIDR = "/1"
Case "0.0.0.0":
strCIDR = "/0"
End Select
ConvertMaskToCIDR = strCIDR
End Function
Public Function NumUsableIPs(cidr As String) As Long
Dim strHosts As String
If Len(cidr) > 3 Then
'They probably passed a whole address.
Dim slashIndex As String
slashIndex = InStr(cidr, "/")
If slashIndex = 0 Then
NumUsableIPs = 1
Exit Function
End If
cidr = Right(cidr, Len(cidr) - slashIndex + 1)
End If
Select Case cidr
Case "/32":
strHosts = 1
Case "/31":
strHosts = 0
Case "/30":
strHosts = 2
Case "/29":
strHosts = 6
Case "/28":
strHosts = 14
Case "/27":
strHosts = 30
Case "/26":
strHosts = 62
Case "/25":
strHosts = 126
Case "/24":
strHosts = 254
Case "/23":
strHosts = 508
Case "/22":
strHosts = 1016
Case "/21":
strHosts = 2032
Case "/20":
strHosts = 4064
Case "/19":
strHosts = 8128
Case "/18":
strHosts = 16256
Case "/17":
strHosts = 32512
Case "/16":
strHosts = 65024
Case "/15":
strHosts = 130048
Case "/14":
strHosts = 195072
Case "/13":
strHosts = 260096
Case "/12":
strHosts = 325120
Case "/11":
strHosts = 390144
Case "/10":
strHosts = 455168
Case "/9":
strHosts = 520192
Case "/8":
strHosts = 585216
Case "/7":
strHosts = 650240
Case "/6":
strHosts = 715264
Case "/5":
strHosts = 780288
Case "/4":
strHosts = 845312
Case "/3":
strHosts = 910336
Case "/2":
strHosts = 975360
Case "/1":
strHosts = 1040384
End Select
NumUsableIPs = strHosts
End Function

Related

VBA Split array

I have the following code:
Sub UpdateBlock()
'Define empty variables for each attribute
Dim ent As AcadEntity
Dim oBkRef As AcadBlockReference
Dim Insertpoints As Variant
Dim A As Double
Dim tag As String
Dim material As String
Dim actualLength As String
Dim cutOff As Double
Dim cutLengths As Double
Dim totalLengths As Double
Dim weight As Double
Dim purchaseLength As Double
Dim decimalLength As Double
Dim lengthWeight As Double
Dim totalLengthWeight As Double
Dim cutLengthWeight As Double
Dim cutWeight As Double
Dim order As Double
Dim feet As Double
Dim inches As Double
Dim fraction As Double
Dim fracVal As Variant
'First we go over every object in the modelspace
For Each ent In ThisDrawing.ModelSpace
'Check if the object is a block
If ent.ObjectName = "AcDbBlockReference" Then
Set oBkRef = ent
'If the object is a block then check if its the block we are looking for
If oBkRef.EffectiveName = "AUTOTAG-MATERIAL" Then
A = A + 1
'Get Current Attributes
attlist = oBkRef.GetAttributes
For i = LBound(attlist) To UBound(attlist)
Select Case attlist(i).TagString
Case "ACTUAL-LENGTH"
actualLength = attlist(i).TextString
Case "PURCHASE-LENGTH"
purchaseLength = attlist(i).TextString
Case "CUT-OFF"
cutOff = Frac2Num(attlist(i).TextString)
Case "DECIMAL-LENGTH"
feet = Split(actualLength)(0)
inches = Split(actualLength)(1)
fracVal = Split(actualLength)(2)
If Not IsNull(Split(actualLength)(2)) Then
fraction = Frac2Num(fracVal)
Else
fraction = 0
End If
decimalLength = Round((((feet * 12) + (inches + fraction)) / 12) - cutOff, 2)
attlist(i).TextString = decimalLength
Case "WEIGHT"
weight = attlist(i).TextString
Case "CUT-WEIGHT"
cutWeight = weight * decimalLength
attlist(i).TextString = cutWeight
Case "LENGTH-WEIGHT"
lengthWeight = weight * purchaseLength
attlist(i).TextString = lengthWeight
Case "TOTAL-LENGTHS"
totalLengths = attlist(i).TextString
Case "CUT-LENGTHS"
cutLength = attlist(i).TextString
Case "TOTAL-LENGTH-WEIGHT"
totalLengthWeight = lengthWeight * totalLengths
attlist(i).TextString = totalLengthWeight
Case "CUT-LENGTH-WEIGHT"
totalCutWeight = lengthWeight * cutLength
attlist(i).TextString = totalCutWeight
End Select
Next
End If
End If
Next ent
End Sub
Function Frac2Num(ByVal X As String) As Double
Dim P As Integer, N As Double, Num As Double, Den As Double
X = Trim$(X)
P = InStr(X, "/")
If P = 0 Then
N = Val(X)
Else
Den = Val(Mid$(X, P + 1))
If Den = 0 Then Error 11 ' Divide by zero
X = Trim$(Left$(X, P - 1))
P = InStr(X, " ")
If P = 0 Then
Num = Val(X)
Else
Num = Val(Mid$(X, P + 1))
N = Val(Left$(X, P - 1))
End If
End If
If Den <> 0 Then
N = N + Num / Den
End If
Frac2Num = N
End Function
The variable fraction / fracVal comes from a tag in AutoCAD that is a length, that will always be at least "0 0", but may be "0 0 0" it is a length in feet, inches, and fractional inches. So some possible values could be "8 5", "16 11 11/16", "0 5 3/8" etc.
What I need is a check for when the fraction is not there.
Any suggestions?
I would split the string on the space and see if the ubound of the resulting array is 2. So something like this
If Ubound(Split(thisString, " ")) = 2 then
'fractional part is present
End If
Another option is the Like Operator:
If thisString Like "#* #* #*/#*" Then
# matches any single digit (0–9) and * matches zero or more characters.
but since you split the string anyway, I would store the result of the split in a variable and check the number of items in it with UBound as shown in the other answer.

Longest common substring large strings?

I need some help with this function. I am trying to find the longest common string between 2 strings. Here is the function that I am currently using:
Public Shared Function LCS(str1 As Char(), str2 As Char())
Dim l As Integer(,) = New Integer(str1.Length - 1, str2.Length - 1) {}
Dim lcs__1 As Integer = -1
Dim substr As String = String.Empty
Dim [end] As Integer = -1
For i As Integer = 0 To str1.Length - 1
For j As Integer = 0 To str2.Length - 1
If str1(i) = str2(j) Then
If i = 0 OrElse j = 0 Then
l(i, j) = 1
Else
l(i, j) = l(i - 1, j - 1) + 1
End If
If l(i, j) > lcs__1 Then
lcs__1 = l(i, j)
[end] = i
End If
Else
l(i, j) = 0
End If
Next
Next
For i As Integer = [end] - lcs__1 + 1 To [end]
substr += str1(i)
Next
Return substr
End Function
This works great on strings of up to around 600 words or so. If I try to compare strings with a larger word count than that it starts to throw system.outofmemoryexception. Obviously, this is hitting the memory pretty hard. Is there any way to fine tune this function or is there possibly another way of doing this that is more streamlined?

Performance loss in VB.net equivalent of light weight conversion from hex to byte

I have read through the answers here https://stackoverflow.com/a/14332574/44080
I've also tried to produce equivalent VB.net code:
Option Strict ON
Public Function ParseHex(hexString As String) As Byte()
If (hexString.Length And 1) <> 0 Then
Throw New ArgumentException("Input must have even number of characters")
End If
Dim length As Integer = hexString.Length \ 2
Dim ret(length - 1) As Byte
Dim i As Integer = 0
Dim j As Integer = 0
Do While i < length
Dim high As Integer = ParseNybble(hexString.Chars(j))
j += 1
Dim low As Integer = ParseNybble(hexString.Chars(j))
j += 1
ret(i) = CByte((high << 4) Or low)
i += 1
Loop
Return ret
End Function
Private Function ParseNybble(c As Char) As Integer
If c >= "0"C AndAlso c <= "9"C Then
Return c - "0"C
End If
c = ChrW(c And Not &H20)
If c >= "A"C AndAlso c <= "F"C Then
Return c - ("A"C - 10)
End If
Throw New ArgumentException("Invalid nybble: " & c)
End Function
Can we remove the compile errors in ParseNybble without introducing data conversions?
Return c - "0"c Operator '-' is not defined for types 'Char' and 'Char'
c = ChrW(c And Not &H20) Operator 'And' is not defined for types 'Char' and 'Integer'
As it stands, no.
However, you could change ParseNybble to take an integer and pass AscW(hexString.Chars(j)) to it, so that the data conversion takes place outside of ParseNybble.
This solution is much much faster than all the alternative i have tried. And it avoids any ParseNybble lookup.
Function hex2byte(s As String) As Byte()
Dim l = s.Length \ 2
Dim hi, lo As Integer
Dim b(l - 1) As Byte
For i = 0 To l - 1
hi = AscW(s(i + i))
lo = AscW(s(i + i + 1))
hi = (hi And 15) + ((hi And 64) >> 6) * 9
lo = (lo And 15) + ((lo And 64) >> 6) * 9
b(i) = CByte((hi << 4) Or lo)
Next
Return b
End Function

Converting Numbers to Excel Letter Column vb.net

I am trying to write data to excel files using vb.net. So I my function which converts number column into excel letter columns.
Public Function ConvertToLetter(ByRef iCol As Integer) As String
Dim Reminder_Part As Integer = iCol Mod 26
Dim Integer_Part As Integer = Int(iCol / 26)
If Integer_Part = 0 Then
ConvertToLetter = Chr(Reminder_Part + 64)
ElseIf Integer_Part > 0 And Reminder_Part <> 0 Then
ConvertToLetter = Chr(Integer_Part + 64) + Chr(Reminder_Part + 64)
ElseIf Integer_Part > 0 And Reminder_Part = 0 Then
ConvertToLetter = Chr(Integer_Part * 26 + 64)
End If
End Function
The Function works ok with any other numbers.
For example,
1 => A
2 => B
...
26 => Z
27 => AA
...
51 => AY
52 => t (And here is when it start to went wrong) It is suppose to return AZ, but it returned t.
I couldn't figure out what part I made a mistake. Can someone help me or show me how to code a proper function of converting numbers to excel letter columns using vb.net.
This should do what you want.
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
This will work up to 52.
Public Function ConvertToLetterA(ByRef iCol As Integer) As String
Select Case iCol
Case 1 To 26
Return Chr(iCol + 64)
Case 27 To 52
Return "A" & Chr(iCol - 26 + 64)
End Select
End Function
On a side note, you can write XLSX files directly with EPPlus via .Net. You can use letter notation for columns if you wish, or you can use numbers.
There are a couple flaws in the logic, the second else clause is not required and the operations should be zero based.
Public Function ConvertToLetter(ByRef iCol As Integer) As String
Dim col As Integer = iCol - 1
Dim Reminder_Part As Integer = col Mod 26
Dim Integer_Part As Integer = Int(col / 26)
If Integer_Part = 0 Then
ConvertToLetter = Chr(Reminder_Part + 65)
Else
ConvertToLetter = Chr(Integer_Part + 64) + Chr(Reminder_Part + 65)
End If
End Function

Barcode is hidden in reporting services

I have a report which carries a barcode , at the time of the Visual Studio preview it looks perfectly but when published to the server reporting services ( WEB ) does not show me the barcode as if hidden
This is the code I use within the report :
Public Shared Function Code39(ByVal stringText As String) As Byte()
Dim result As Byte() = Nothing
Try
result = GenerateImage("Code 3 de 9", StringToBarcode39String(stringText))
Catch ex As Exception
End Try
Return result
End Function
Public Shared Function Code128(ByVal stringText As String) As Byte()
Dim result As Byte() = Nothing
Try
result = GenerateImage("Code 128", StringToBarcode128String(stringText))
Catch ex As Exception
End Try
Return result
End Function
Public Shared Function GenerateImage(ByVal fontName As String, ByVal stringText As String) As Byte()
Dim oGraphics As System.Drawing.Graphics
Dim barcodeSize As System.Drawing.SizeF
Dim ms As System.IO.MemoryStream
Using font As New System.Drawing.Font(New System.Drawing.FontFamily(fontName), 36)
Using tmpBitmap As New System.Drawing.Bitmap(1, 1, System.Drawing.Imaging.PixelFormat.Format32bppArgb)
oGraphics = System.Drawing.Graphics.FromImage(tmpBitmap)
oGraphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SingleBitPerPixel
barcodeSize = oGraphics.MeasureString(stringText, font)
oGraphics.Dispose()
End Using
Using newBitmap As New System.Drawing.Bitmap(barcodeSize.Width, barcodeSize.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb)
oGraphics = System.Drawing.Graphics.FromImage(newBitmap)
oGraphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SingleBitPerPixel
Using oSolidBrushWhite As New System.Drawing.SolidBrush(System.Drawing.Color.White)
Using oSolidBrushBlack As New System.Drawing.SolidBrush(System.Drawing.Color.Black)
oGraphics.FillRectangle(oSolidBrushWhite, New System.Drawing.Rectangle(0, 0, barcodeSize.Width, barcodeSize.Height))
oGraphics.DrawString(stringText, font, oSolidBrushBlack, 0, 0)
End Using
End Using
ms = New System.IO.MemoryStream()
newBitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Png)
End Using
End Using
Return ms.ToArray()
End Function
Public Shared Function StringToBarcode128String(ByVal value As String) As String
' Parameters : a string
' Return : a string which give the bar code when it is dispayed with CODE128.TTF font
' : an empty string if the supplied parameter is no good
Dim charPos As Integer, minCharPos As Integer
Dim currentChar As Integer, checksum As Integer
Dim isTableB As Boolean = True, isValid As Boolean = True
Dim returnValue As String = String.Empty
If value.Length > 0 Then
' Check for valid characters
For charCount As Integer = 0 To value.Length - 1
'currentChar = char.GetNumericValue(value, charPos);
currentChar = AscW(Char.Parse(value.Substring(charCount, 1)))
If Not (currentChar >= 32 AndAlso currentChar <= 126) Then
isValid = False
Exit For
End If
Next
' Barcode is full of ascii characters, we can now process it
If isValid Then
charPos = 0
While charPos < value.Length
If isTableB Then
' See if interesting to switch to table C
' yes for 4 digits at start or end, else if 6 digits
If charPos = 0 OrElse charPos + 4 = value.Length Then
minCharPos = 4
Else
minCharPos = 6
End If
minCharPos = IsNumber(value, charPos, minCharPos)
If minCharPos < 0 Then
' Choice table C
If charPos = 0 Then
' Starting with table C
' char.ConvertFromUtf32(210);
returnValue = (ChrW(210)).ToString()
Else
' Switch to table C
returnValue = returnValue & (ChrW(204)).ToString()
End If
isTableB = False
Else
If charPos = 0 Then
' Starting with table B
' char.ConvertFromUtf32(209);
returnValue = (ChrW(209)).ToString()
End If
End If
End If
If Not isTableB Then
' We are on table C, try to process 2 digits
minCharPos = 2
minCharPos = IsNumber(value, charPos, minCharPos)
If minCharPos < 0 Then
' OK for 2 digits, process it
currentChar = Integer.Parse(value.Substring(charPos, 2))
currentChar = IIf(currentChar < 95, currentChar + 32, currentChar + 105) ''
returnValue = returnValue & (ChrW(currentChar)).ToString()
charPos += 2
Else
' We haven't 2 digits, switch to table B
returnValue = returnValue & (ChrW(205)).ToString()
isTableB = True
End If
End If
If isTableB Then
' Process 1 digit with table B
returnValue = returnValue & value.Substring(charPos, 1)
charPos += 1
End If
End While
' Calculation of the checksum
checksum = 0
For [loop] As Integer = 0 To returnValue.Length - 1
currentChar = AscW(Char.Parse(returnValue.Substring([loop], 1)))
currentChar = IIf(currentChar < 127, currentChar - 32, currentChar - 105)
If [loop] = 0 Then
checksum = currentChar
Else
checksum = (checksum + ([loop] * currentChar)) Mod 103
End If
Next
' Calculation of the checksum ASCII code
checksum = IIf(checksum < 95, checksum + 32, checksum + 105)
' Add the checksum and the STOP
returnValue = returnValue & (ChrW(checksum)).ToString() & (ChrW(211)).ToString()
End If
End If
Return returnValue
End Function
Private Shared Function IsNumber(ByVal InputValue As String, ByVal CharPos As Integer, ByVal MinCharPos As Integer) As Integer
' if the MinCharPos characters from CharPos are numeric, then MinCharPos = -1
MinCharPos -= 1
If CharPos + MinCharPos < InputValue.Length Then
While MinCharPos >= 0
If AscW(Char.Parse(InputValue.Substring(CharPos + MinCharPos, 1))) < 48 OrElse AscW(Char.Parse(InputValue.Substring(CharPos + MinCharPos, 1))) > 57 Then
Exit While
End If
MinCharPos -= 1
End While
End If
Return MinCharPos
End Function
Public Shared Function StringToBarcode39String(ByVal value As String, Optional ByVal addChecksum As Boolean = False) As String
' Parameters : a string
' Return : a string which give the bar code when it is dispayed with CODE128.TTF font
' : an empty string if the supplied parameter is no good
Dim isValid As Boolean = True
Dim currentChar As Char
Dim returnValue As String = String.Empty
Dim checksum As Integer = 0
If value.Length > 0 Then
'Check for valid characters
For CharPos As Integer = 0 To value.Length - 1
currentChar = Char.Parse(value.Substring(CharPos, 1))
If Not ((currentChar >= "0"c AndAlso currentChar <= "9"c) OrElse (currentChar >= "A"c AndAlso currentChar <= "Z"c) OrElse currentChar = " "c OrElse currentChar = "-"c OrElse currentChar = "."c OrElse currentChar = "$"c OrElse currentChar = "/"c OrElse currentChar = "+"c OrElse currentChar = "%"c) Then
isValid = False
Exit For
End If
Next
If isValid Then
' Add start char
returnValue = "*"
' Add other chars, and calc checksum
For CharPos As Integer = 0 To value.Length - 1
currentChar = Char.Parse(value.Substring(CharPos, 1))
returnValue += currentChar.ToString()
If currentChar >= "0"c AndAlso currentChar <= "9"c Then
checksum = checksum + AscW(currentChar) - 48
ElseIf currentChar >= "A"c AndAlso currentChar <= "Z"c Then
checksum = checksum + AscW(currentChar) - 55
Else
Select Case currentChar
Case "-"c
checksum = checksum + AscW(currentChar) - 9
Exit Select
Case "."c
checksum = checksum + AscW(currentChar) - 9
Exit Select
Case "$"c
checksum = checksum + AscW(currentChar) + 3
Exit Select
Case "/"c
checksum = checksum + AscW(currentChar) - 7
Exit Select
Case "+"c
checksum = checksum + AscW(currentChar) - 2
Exit Select
Case "%"c
checksum = checksum + AscW(currentChar) + 5
Exit Select
Case " "c
checksum = checksum + AscW(currentChar) + 6
Exit Select
End Select
End If
Next
' Calculation of the checksum ASCII code
If addChecksum Then
checksum = checksum Mod 43
If checksum >= 0 AndAlso checksum <= 9 Then
returnValue += (ChrW(checksum + 48)).ToString()
ElseIf checksum >= 10 AndAlso checksum <= 35 Then
returnValue += (ChrW(checksum + 55)).ToString()
Else
Select Case checksum
Case 36
returnValue += "-"
Exit Select
Case 37
returnValue += "."
Exit Select
Case 38
returnValue += " "
Exit Select
Case 39
returnValue += "$"
Exit Select
Case 40
returnValue += "/"
Exit Select
Case 41
returnValue += "+"
Exit Select
Case 42
returnValue += "%"
Exit Select
End Select
End If
End If
' Add stop char
returnValue += "*"
End If
End If
Return returnValue
End Function
Do I use assemblies , And the barcode image is kind
Could it be that on the server the barcode font is missing?