example for print barcode cl-s621 Citizen - printing

I have a citizen cl-s621 printer, where can i find example for programming code39 or ean code barcode label.
I've worked with zebra y sato printer, and never with citizen.

According to specification, CL-S621 can emulate Zebra ZPL-II language.
https://www.citizen-systems.com/us/products/printer/label/cl-s621/
This is an example of barcode 39 printing to Zebra printer. Refactoring required.
' module code
Public Type DOCINFO
pDocName As String
pOutputFile As String
pDatatype As String
End Type
Public Declare Function ClosePrinter Lib "winspool.drv" (ByVal hPrinter As Long) As Long
Public Declare Function EndDocPrinter Lib "winspool.drv" (ByVal hPrinter As Long) As Long
Public Declare Function EndPagePrinter Lib "winspool.drv" (ByVal hPrinter As Long) As Long
Public Declare Function OpenPrinter Lib "winspool.drv" Alias "OpenPrinterA" (ByVal pPrinterName As String, phPrinter As Long, ByVal pDefault As Long) As Long
Public Declare Function StartDocPrinter Lib "winspool.drv" Alias "StartDocPrinterA" (ByVal hPrinter As Long, ByVal Level As Long, pDocInfo As DOCINFO) As Long
Public Declare Function StartPagePrinter Lib "winspool.drv" (ByVal hPrinter As Long) As Long
Public Declare Function WritePrinter Lib "winspool.drv" (ByVal hPrinter As Long, pBuf As Any, ByVal cdBuf As Long, pcWritten As Long) As Long
Public Const BARCODE_PLACEHOLDER = "#####"
' label script created using ZebraDesigner
Public Const LABEL_TEMPLATE_39 = "^XA~TA000~JSN^LT0^MNW^MTD^PON^PMN^LH0,0^JMA^PR6,6~SD15^JUS^LRN^CI0^XZ" _
& "^XA" _
& "^MMT" _
& "^PW609" _
& "^LL0406" _
& "^LS0" _
& "^BY4,3,160^FT586,219^B3I,N,,Y,N" _
& "^FD#####^FS" _
& "^PQ1,0,1,Y^XZ"
Public Function AddMOD43CheckChar(Text As String) As String
Const charSet As String = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%"
Dim I As Long
Dim T As Long
For I = 1 To Len(Trim$(UCase(Text)))
T = InStr(charSet, Mid$(Text, I, 1)) - 1 + T
Next I
AddMOD43CheckChar = Text & Mid$(charSet, (T Mod 43 + 1), 1)
End Function
Public Function ClearCommandChars(Text As String) As String
Dim sTmp As String
sTmp = Replace(Text, "^", vbNullString, Compare:=vbBinaryCompare)
sTmp = Replace(sTmp, "~", vbNullString, Compare:=vbBinaryCompare)
ClearCommandChars = Replace(sTmp, "_", vbNullString, Compare:=vbBinaryCompare)
End Function
Public Function PrintCode39toZebra(PrinterName As String, BarCodeText As String, Optional AddCheckChar As Boolean) As Boolean
Dim sBCtext As String
Dim lPrinterHandle As Long, lRetVal As Long, lWritten As Long
Dim tDocInfo As DOCINFO
' clear barcode text and add check character
sBCtext = ClearCommandChars(BarCodeText)
If AddCheckChar Then sBCtext = AddMOD43CheckChar(sBCtext)
' insert barcode into label template
sBCtext = Replace(LABEL_TEMPLATE_39, BARCODE_PLACEHOLDER, sBCtext, Compare:=vbTextCompare)
' send label script to printer
tDocInfo.pDocName = "LoremIpsum"
tDocInfo.pOutputFile = vbNullString
tDocInfo.pDatatype = vbNullString
lRetVal = OpenPrinter(PrinterName, lPrinterHandle, 0)
If lRetVal <> 0 Then
lRetVal = StartDocPrinter(lPrinterHandle, 1, tDocInfo)
If lRetVal <> 0 Then
lRetVal = StartPagePrinter(lPrinterHandle)
If lRetVal <> 0 Then
lRetVal = WritePrinter(lPrinterHandle, ByVal sBCtext, Len(sBCtext), lWritten)
If lRetVal <> 0 Then
lRetVal = EndPagePrinter(lPrinterHandle)
If lRetVal <> 0 Then
lRetVal = EndDocPrinter(lPrinterHandle)
If lRetVal <> 0 Then
ClosePrinter lPrinterHandle
PrintCode39toZebra = True
End If
End If
End If
End If
End If
End If
End Function
' form code
Private Sub Command1_Click()
' "ZDesigner GX420d" - printer name from Devices and Printers
' "01234" - test barcode text
PrintCode39toZebra "ZDesigner GX420d", "01234", True
End Sub

Related

Split Wav File in VB6

I need help to fix the attached VB6 code which is supposed to take an audio file and split it into 5 equal parts.
This is the way this code should work:
The first part starts from the beginning of Track.wav file.
The second part starts from where the first split part ended.
The third part starts from where the second split part ended.
The fourth part starts from where the third split part ended.
The fifth part starts from where the fourth split part ended.
Essentially each of the file parts is a continuation of the previous part of file split. After the split I have 1.wav, 2.wav, 3.wav. 4.wav and 5.wav all derived from a Track.wav file. The code attached already splits the file into five equal parts but the problem is that all the audio parts are the same as the first part instead of a continuation.
I need help to get this fixed to work as it should in VB6 (not .NET). I'd be grateful for your assistance with this.
Dim Wavlength As Integer
Private Sub Command1_Click()
On Error Resume Next
DoFirstWav
Me.SetFocus
End Sub
Private Sub DoFirstWav()
On Error Resume Next
Dim ByteData() As Byte
Dim FirstWav As Integer
FirstWav = Wavlength / 5
ByteData = ReadFile(App.Path & "\Track.wav", 1, FirstWav & "0000")
Call WriteFile(App.Path & "\Segments\1.wav", ByteData)
DoSecondWav
End Sub
Private Sub DoSecondWav()
On Error Resume Next
Dim ByteData() As Byte
Dim SecondWav As Integer
SecondWav = Wavlength / 5
ByteData = ReadFile(App.Path & "\Track.wav", 1, SecondWav & "0000")
Call WriteFile(App.Path & "\Segments\2.wav", ByteData)
DoThirdWav
End Sub
Private Sub DoThirdWav()
On Error Resume Next
Dim ByteData() As Byte
Dim ThirdWav As Integer
ThirdWav = Wavlength / 5
ByteData = ReadFile(App.Path & "\Track.wav", 1, ThirdWav & "0000")
Call WriteFile(App.Path & "\Segments\3.wav", ByteData)
DoFourthWav
End Sub
Private Sub DoFourthWav()
On Error Resume Next
Dim ByteData() As Byte
Dim FourthWav As Integer
FourthWav = Wavlength / 5
ByteData = ReadFile(App.Path & "\Track.wav", 1, FourthWav & "0000")
Call WriteFile(App.Path & "\Segments\4.wav", ByteData)
DoFifthWav
End Sub
Private Sub DoFifthWav()
On Error Resume Next
Dim ByteData() As Byte
Dim FifthWav As Integer
FifthWav = Wavlength / 5
ByteData = ReadFile(App.Path & "\Track.wav", 1, FifthWav & "0000")
Call WriteFile(App.Path & "\Segments\5.wav", ByteData)
MsgBox "Wav Split Successfully", vbInformation
End
End Sub
Private Function ReadFile(ByVal strFileName As String, Optional ByVal lngStartPos As Long = 1, Optional ByVal lngFileSize As Long = -1) As Byte()
On Error Resume Next
Dim FilNum As Integer
FilNum = FreeFile
Open strFileName For Binary As #FilNum
If lngFileSize = -1 Then
ReDim ReadFile(LOF(FilNum) - lngStartPos)
Else
ReDim ReadFile(lngFileSize - 1)
End If
Get #FilNum, lngStartPos, ReadFile
Close #FilNum
End Function
Private Function WriteFile(ByVal strFileName As String, ByteData() As Byte, Optional ByVal lngStartPos As Long = -1, Optional ByVal OverWrite As Boolean = True)
On Error Resume Next
Dim FilNum As Integer
FilNum = FreeFile
If OverWrite = True And Dir(strFileName) <> "" Then
Kill strFileName
End If
Open strFileName For Binary As #FilNum
If lngStartPos = -1 Then
Put #FilNum, LOF(FilNum) + 1, ByteData
Else
Put #FilNum, l, ByteData
End If
Close #FilNum
End Function
Private Sub Form_Load()
On Error Resume Next
Dim MyInt As Integer
Dim MyByte As Byte
Dim MyStr As String * 4
Dim MyLong As Long
Dim SampleRate, BytesPerSample, FileSize As Long
Open App.Path & "\Track.wav" For Binary Access Read Lock Read As #1
Get #1, , MyStr: Debug.Print "Riff = "; MyStr
Get #1, , MyLong: Debug.Print "File size = "; MyLong
FileSize = MyLong
Get #1, , MyStr: Debug.Print "Wave = "; MyStr
Get #1, , MyStr: Debug.Print "Format = "; MyStr
Get #1, , MyLong: Debug.Print "Any = "; MyLong
Get #1, , MyInt: Debug.Print "formatTag = "; MyInt
Get #1, , MyInt: Debug.Print "Channels = "; MyInt
Get #1, , MyLong: Debug.Print "Samples per Sec = "; MyLong
SampleRate = MyLong
Get #1, , MyInt: Debug.Print "Bytes per Sec = "; MyInt
Get #1, , MyInt: Debug.Print "BlockAlign = "; MyInt
Get #1, , MyInt: Debug.Print "Bytes per Sample = "; MyInt
BytesPerSample = MyInt
Close #1
Wavlength = FileSize / (SampleRate * BytesPerSample)
End Sub
This question is quite involved, particularly if each part needs to be playable. The reason is that each file you create needs to have a valid header record. To complicate it further, it appears a header record may be 44 bytes, 46 bytes, or even other sizes.
I worked out some basic code based on your post that appears to work for the wav file I tested:
Option Explicit
Private Const HEADER_SIZE As Long = 46
Private Const CHUNK_COUNT As Long = 5
Private HeaderData(HEADER_SIZE) As Byte
Private ChunkSize As Long
Private Sub Form_Load()
Dim MyInt As Integer
Dim MyByte As Byte
Dim MyStr As String * 4
Dim MyLong As Long
Dim FileSize As Long
Open App.Path & "\Track.wav" For Binary Access Read Lock Read As #1
Get #1, , MyStr: Debug.Print "Riff = "; MyStr
Get #1, , MyLong: Debug.Print "File size = "; MyLong
Get #1, , MyStr: Debug.Print "Wave = "; MyStr
Get #1, , MyStr: Debug.Print "Format = "; MyStr
Get #1, , MyLong: Debug.Print "Any = "; MyLong
Get #1, , MyInt: Debug.Print "formatTag = "; MyInt
Get #1, , MyInt: Debug.Print "Channels = "; MyInt
Get #1, , MyLong: Debug.Print "Samples per Sec = "; MyLong
Get #1, , MyInt: Debug.Print "Bytes per Sec = "; MyInt
Get #1, , MyInt: Debug.Print "BlockAlign = "; MyInt
Get #1, , MyInt: Debug.Print "Bytes per Sample = "; MyInt
Get #1, , MyInt: Debug.Print "Something = "; MyInt 'for my wave file, I needed 2 extra bytes
Get #1, , MyStr: Debug.Print "SubchunkID = "; MyStr
Get #1, , FileSize: Debug.Print "SubchunkSize = "; FileSize
Get #1, 1, HeaderData 'the size changes depending upon the file
Close #1
ChunkSize = CLng(FileSize / CHUNK_COUNT) 'you might loose some data here
End Sub
Private Sub Command1_Click()
Dim i As Integer
Dim ByteData() As Byte
Dim StartPos As Long
For i = 1 To CHUNK_COUNT
StartPos = HEADER_SIZE + ((i - 1) * ChunkSize)
ByteData = ReadFile(App.Path & "\Track.wav", StartPos, ChunkSize)
Call WriteFile(App.Path & "\Segments\" & i & ".wav", HeaderData, ByteData)
Next
MsgBox "Wav Split Successfully", vbInformation
End
End Sub
Private Function ReadFile(ByVal strFileName As String, ByVal lngStartPos As Long, ByVal lngFileSize As Long) As Byte()
On Error Resume Next
Dim FilNum As Integer
FilNum = FreeFile
ReDim ReadFile(lngFileSize - 1)
Open strFileName For Binary As #FilNum
Get #FilNum, lngStartPos, ReadFile
Close #FilNum
End Function
Private Function WriteFile(ByVal strFileName As String, HeaderData() As Byte, ByteData() As Byte, Optional ByVal OverWrite As Boolean = True)
On Error Resume Next
Dim FilNum As Integer
FilNum = FreeFile
If OverWrite = True And Dir(strFileName) <> "" Then
Kill strFileName
End If
Open strFileName For Binary As #FilNum
Put #FilNum, LOF(FilNum) + 1, HeaderData
Put #FilNum, HEADER_SIZE, ByteData
Close #FilNum
End Function
I eliminated a lot of duplicate code by implementing a For loop. In that loop, I calculate the Start position for the Read, and also pass the header record for the Write.
Again, I stress that this is very basic and will not work for all wav files. You can manually adjust the HEADER_SIZE if it does not work for your file.
Likely the header record needs to be modified to reflect the correct size of the new file, instead of using the header from the original file.
This should get you started.
This is the working code. I'm sure someone may need something like this in future, si thought I'd post it here.
Dim Wavlength As Long
Dim PartLength As Integer
Dim WavHeader() As Byte
Private Sub Command1_Click()
On Error Resume Next
WavHeader = ReadFile(App.Path & "\Track.wav", 1, 320)
PartLength = Wavlength / 6 - 2
DoFirstWav
End Sub
Private Sub DoFirstWav()
On Error Resume Next
Dim ByteData() As Byte
Dim FirstWav As Integer
ByteData = ReadFile(App.Path & "\Track.wav", 1, PartLength & "0000")
Call WriteFile(App.Path & "\Segments\1.wav", ByteData)
DoSecondWav
End Sub
Private Sub DoSecondWav()
On Error Resume Next
Dim ByteData() As Byte
Dim ByteRead() As Byte
Dim SecondWav As Integer
SecondWav = PartLength
ByteRead = ReadFile(App.Path & "\Track.wav", SecondWav & "0000", PartLength & "0000")
ReDim ByteData(UBound(WavHeader) + UBound(ByteRead)) As Byte
For i = 0 To UBound(WavHeader)
ByteData(i) = WavHeader(i)
Next i
For i = 0 To UBound(ByteRead)
ByteData(UBound(WavHeader) + i) = ByteRead(i)
Next i
Call WriteFile(App.Path & "\Segments\2.wav", ByteData)
DoThirdWav
End Sub
Private Sub DoThirdWav()
On Error Resume Next
Dim ByteData() As Byte
Dim ByteRead() As Byte
Dim ThirdWav As Integer
ThirdWav = PartLength * 2 + 1
ByteRead = ReadFile(App.Path & "\Track.wav", ThirdWav & "0000", PartLength & "0000")
ReDim ByteData(UBound(WavHeader) + UBound(ByteRead)) As Byte
For i = 0 To UBound(WavHeader)
ByteData(i) = WavHeader(i)
Next i
For i = 0 To UBound(ByteRead)
ByteData(UBound(WavHeader) + i) = ByteRead(i)
Next i
Call WriteFile(App.Path & "\Segments\3.wav", ByteData)
DoFourthWav
End Sub
Private Sub DoFourthWav()
On Error Resume Next
Dim ByteData() As Byte
Dim ByteRead() As Byte
Dim FourthWav As Integer
FourthWav = PartLength * 3 + 1
ByteRead = ReadFile(App.Path & "\Track.wav", FourthWav & "0000", PartLength & "0000")
ReDim ByteData(UBound(WavHeader) + UBound(ByteRead)) As Byte
For i = 0 To UBound(WavHeader)
ByteData(i) = WavHeader(i)
Next i
For i = 0 To UBound(ByteRead)
ByteData(UBound(WavHeader) + i) = ByteRead(i)
Next i
Call WriteFile(App.Path & "\Segments\4.wav", ByteData)
DoFifthWav
End Sub
Private Sub DoFifthWav()
On Error Resume Next
Dim ByteData() As Byte
Dim ByteRead() As Byte
Dim FifthWav As Integer
FifthWav = PartLength * 4 + 1
ByteRead = ReadFile(App.Path & "\Track.wav", FifthWav & "0000", PartLength & "0000")
ReDim ByteData(UBound(WavHeader) + UBound(ByteRead)) As Byte
For i = 0 To UBound(WavHeader)
ByteData(i) = WavHeader(i)
Next i
For i = 0 To UBound(ByteRead)
ByteData(UBound(WavHeader) + i) = ByteRead(i)
Next i
Call WriteFile(App.Path & "\Segments\5.wav", ByteData)
End Sub
Private Function ReadFile(ByVal strFileName As String, Optional ByVal lngStartPos As Long = 1, Optional ByVal lngFileSize As Long = -1) As Byte()
On Error Resume Next
Dim FilNum As Integer
FilNum = FreeFile
Open strFileName For Binary As #FilNum
If lngFileSize = -1 Then
ReDim ReadFile(LOF(FilNum) - lngStartPos)
Else
ReDim ReadFile(lngFileSize - 1)
End If
Get #FilNum, lngStartPos, ReadFile
Close #FilNum
End Function
Private Function WriteFile(ByVal strFileName As String, ByteData() As Byte, Optional ByVal lngStartPos As Long = -1, Optional ByVal OverWrite As Boolean = True)
On Error Resume Next
Dim FilNum As Integer
FilNum = FreeFile
If OverWrite = True And Dir(strFileName) <> "" Then
Kill strFileName
End If
Open strFileName For Binary As #FilNum
If lngStartPos = -1 Then
Put #FilNum, LOF(FilNum) + 1, ByteData
Else
Put #FilNum, l, ByteData
End If
Close #FilNum
End Function
Private Sub Form_Load()
On Error Resume Next
Dim MyInt As Integer
Dim MyByte As Byte
Dim MyStr As String * 4
Dim MyLong As Long
Dim SampleRate, BytesPerSample, FileSize As Long
Open App.Path & "\Track.wav" For Binary Access Read Lock Read As #1
Get #1, , MyStr: Debug.Print "Riff = "; MyStr
Get #1, , MyLong: Debug.Print "File size = "; MyLong
FileSize = MyLong
Get #1, , MyStr: Debug.Print "Wave = "; MyStr
Get #1, , MyStr: Debug.Print "Format = "; MyStr
Get #1, , MyLong: Debug.Print "Any = "; MyLong
Get #1, , MyInt: Debug.Print "formatTag = "; MyInt
Get #1, , MyInt: Debug.Print "Channels = "; MyInt
Get #1, , MyLong: Debug.Print "Samples per Sec = "; MyLong
SampleRate = MyLong
Get #1, , MyInt: Debug.Print "Bytes per Sec = "; MyInt
Get #1, , MyInt: Debug.Print "BlockAlign = "; MyInt
Get #1, , MyInt: Debug.Print "Bytes per Sample = "; MyInt
BytesPerSample = MyInt
Close #1
Wavlength = FileSize \ (SampleRate * BytesPerSample)
Debug.Print "Wavlength"; Wavlength
End Sub

Break up 32-bit hex value into 4 bytes [QB64]

I would want to ask, how do you break up a 32-bit hex (for example: CEED6644) into 4 bytes (var1 = CE, var2 = ED, var3 = 66, var4 = 44). In QB64 or QBasic. I would use this to store several data bytes into one array address.
Something like this:
DIM Array(&HFFFF&) AS _UNSIGNED LONG
Array(&HAA00&) = &HCEED6644&
addr = &HAA00&
SUB PrintChar
SHARED addr
IF var1 = &HAA& THEN PRINT "A"
IF var1 = &HBB& THEN PRINT "B"
IF var1 = &HCC& THEN PRINT "C"
IF var1 = &HDD& THEN PRINT "D"
IF var1 = &HEE& THEN PRINT "E"
IF var1 = &HFF& THEN PRINT "F"
IF var1 = &H00& THEN PRINT "G"
IF var1 = &H11& THEN PRINT "H"
And so on...
You could use integer division (\) and bitwise AND (AND) to accomplish this.
DIM x(0 TO 3) AS _UNSIGNED _BYTE
a& = &HCEED6644&
x(0) = (a& AND &HFF000000&) \ 2^24
x(1) = (a& AND &H00FF0000&) \ 2^16
x(2) = (a& AND &H0000FF00&) \ 2^8
x(3) = a& AND &HFF&
PRINT HEX$(x(0)); HEX$(x(1)); HEX$(x(2)); HEX$(x(3))
Note that you could alternatively use a generic RShift~& function instead of raw integer division since what you're really doing is shifting bits:
x(0) = RShift~&(a& AND &HFF000000&, 18)
...
FUNCTION RShift~& (value AS _UNSIGNED LONG, shiftCount AS _UNSIGNED BYTE)
' Raise illegal function call if the shift count is greater than the width of the type.
' If shiftCount is not _UNSIGNED, then you must also check that it isn't less than 0.
IF shiftCount > 32 THEN ERROR 5
RShift~& = value / 2^shiftCount
END FUNCTION
Building upon that, you might create another function:
FUNCTION ByteAt~%% (value AS _UNSIGNED LONG, position AS _UNSIGNED BYTE)
'position must be in the range [0, 3].
IF (position AND 3) <> position THEN ERROR 5
ByteAt~%% = RShift~&(value AND LShift~&(&HFF&, 8*position), 8*position)
END FUNCTION
Note that an LShift~& function was used that shifts bits to the left (multiplication by a power of 2). A potentially better alternative would be to perform the right-shift first and just mask the lower 8 bits, eliminating the need for LShift~&:
FUNCTION ByteAt~%% (value AS _UNSIGNED LONG, position AS _UNSIGNED BYTE)
'position must be in the range [0, 3].
IF (position AND 3) <> position THEN ERROR 5
ByteAt~%% = RShift~&(value, 8*position) AND 255
END FUNCTION
Incidentally, another QB-like implementation known as FreeBASIC has an actual SHR operator, used like MOD or AND, to perform a shift operation directly instead of using division, which is potentially faster.
You could also use QB64's DECLARE LIBRARY facility to create functions in C++ that will perform the shift operations:
/*
* Place in a separate "shift.h" file or something.
*/
unsigned int LShift (unsigned int n, unsigned char count)
{
return n << count;
}
unsigned int RShift (unsigned int n, unsigned char count)
{
return n >> count;
}
Here's the full corresponding QB64 code:
DECLARE LIBRARY "shift"
FUNCTION LShift~& (value AS _UNSIGNED LONG, shiftCount AS _UNSIGNED _BYTE)
FUNCTION RShift~& (value AS _UNSIGNED LONG, shiftCount AS _UNSIGNED _BYTE)
END DECLARE
x(0) = ByteAt~%%(a&, 0)
x(1) = ByteAt~%%(a&, 1)
x(2) = ByteAt~%%(a&, 2)
x(3) = ByteAt~%%(a&, 3)
END
FUNCTION ByteAt~%% (value AS _UNSIGNED LONG, position AS _UNSIGNED BYTE)
'position must be in the range [0, 3].
IF (position AND 3) <> position THEN ERROR 5
ByteAt~%% = RShift~&(value, 8*position) AND 255
END FUNCTION
If QB64 had a documented API, it might be possible to raise a QB64 error from the C++ code when the shift count is too high, rather than relying on the behavior of C++ to essentially ignore shift counts that are too high. Unfortunately, this isn't the case, and it might actually cause more problems than it's worth.
This snip gets the byte pairs of a hexidecimal value:
DIM Value AS _UNSIGNED LONG
Value = &HCEED6644&
S$ = RIGHT$("00000000" + HEX$(Value), 8)
PRINT "Byte#1: "; MID$(S$, 1, 2)
PRINT "Byte#2: "; MID$(S$, 3, 2)
PRINT "Byte#3: "; MID$(S$, 5, 2)
PRINT "Byte#4: "; MID$(S$, 7, 2)

How do I find what a TextBox's contents will be after pressing Ctrl + Z, before it occurs?

I am writing a small function that will calculate the contents of a TextBox after the KeyPress event, but during the KeyPress event. I know, it sounds strange. :)
The reason for this is because I have been given a project at work, where I am to fix any errors in a current program.
There is currently a TextBox, which triggers a search on a SQL Server, in the KeyPress event.
This searches for the current contents of the TextBox concatenated with Chr(KeyAscii)
This means that if your TextBox contains Hello and your cursor is at the end of the word it will work correctly, but if you have the o selected and press a it will search for Helloa instead of Hella.
So to correct, this I have come up with the following function
Private Function TextAfterKeyPress(Ctrl As Control, KeyAscii As Integer) As String
Dim strUnSelLeft As String
Dim strUnSelRight As String
Dim strSel As String
Dim strMid As String
With Ctrl
strUnSelLeft = ""
strUnSelRight = ""
strMid = .Text
Select Case KeyAscii
Case 1 ' Ctrl + A
' No change to text
Case 3 ' Ctrl + C
' No change to text
Case 8 ' BackSpace
If .SelStart = 0 Then
' No change to text
Else
If .SelLength = 0 Then
strUnSelLeft = Left(.Text, .SelStart - 1)
strUnSelRight = Right(.Text, Len(.Text) - (.SelStart + .SelLength))
strMid = ""
Else
strUnSelLeft = Left(.Text, .SelStart)
strUnSelRight = Right(.Text, Len(.Text) - (.SelStart + .SelLength))
strMid = ""
End If
End If
Case 9 ' Tab
' No change to text
Case 13 ' Return
' No change to text
Case 22 ' Ctrl + V
strUnSelLeft = Left(.Text, .SelStart)
strUnSelRight = Right(.Text, Len(.Text) - (.SelStart + .SelLength))
strMid = Clipboard.GetText
Case 24 ' Ctrl + X
If .SelLength = 0 Then
' No change to text
Else
strUnSelLeft = Left(.Text, .SelStart)
strUnSelRight = Right(.Text, Len(.Text) - (.SelStart + .SelLength))
strMid = ""
End If
Case 26 ' Ctrl + Z
Case 27 ' Esc
' No Change to text
Case 137, 153, 160, 169, 188, 189, 190, 215, 247 ' Disallowed Chars
' No Change to text
Case 128 To 255 ' Allowed non standard Chars
strUnSelLeft = Left(.Text, .SelStart)
strUnSelRight = Right(.Text, Len(.Text) - (.SelStart + .SelLength))
strMid = Chr(KeyAscii)
Case 32 To 127 ' Standard Printable Chars
strUnSelLeft = Left(.Text, .SelStart)
strUnSelRight = Right(.Text, Len(.Text) - (.SelStart + .SelLength))
strMid = Chr(KeyAscii)
Case Else
End Select
TextAfterKeyPress = strUnSelLeft & strMid & strUnSelRight
End With
End Function
Now for the section where it says "Case 26", it will perform an undo action, and then the search won't work correctly again.
Is there any way to find out what the contents of the TextBox will be when you press Ctrl + Z, but during the KeyPress in which it happens? The KeyPress event fires before the content of the TextBox changes so I would need to find out what is in the Undo buffer so that I can run a correct search.
Can anyone point me in the right direction?
I have worked with textbox APIs a bit ..And i don't think you can deal with its UNDO buffer due to its limitation.. but something you can do is to manually send an UNDO then read the textbox content.
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Private Const EM_UNDO = &HC7
,
Case 26
KeyAscii = 0
SendMessage .hwnd, EM_UNDO, ByVal 0, ByVal 0
strMid = .Text
If you only need to read the text and not to change it you can send an another UNDO msg to get the text to its previous content.

How to use a loop through multiple similar textboxes?

So I know this is pretty sloppy, but I have a lot going on for a simple triangulation program (2d) and I'm very new.
The user inputs value in textboxes- "aft1.text,ain1.text,aft2.text,ain2.text,bft1.text,bin1.text,bft2.text,bin1.text." This goes on for as many points that need triangulated. I want to be able to run a loop through these similar textboxes, and run a function on them.
So for each textbox that starts with abft + i and ain + i run the inches function to create a1.
Do the same to create b1.
Then another loop to plot a + i and b + i on the chart per the xcoord/ycoord functions created.
Dim a1 As Double = inches(aft1.Text, ain1.Text)
Dim b1 As Double = inches(bft1.Text, bin1.Text)
If a1 <> 0 And b1 <> 0 Then
Dim targetpoint As Int32
targetpoint = Chart1.Series("Drawing").Points.AddXY((xcoord(a1, b1)), ((ycoord(a1, b1))))
Chart1.Series("Drawing").Points.Item(targetpoint).Label = "1"
End If
Dim a2 As Double = inches(aft2.Text, ain2.Text)
Dim b2 As Double = inches(bft2.Text, bin2.Text)
If a2 <> 0 And b2 <> 0 Then
Dim targetpoint As Int32
targetpoint = Chart1.Series("Drawing").Points.AddXY((xcoord(a2, b2)), ((ycoord(a2, b2))))
Chart1.Series("Drawing").Points.Item(targetpoint).Label = "2"
End If
Dim a3 As Double = inches(aft3.Text, ain3.Text)
Dim b3 As Double = inches(bft3.Text, bin3.Text)
If a3 <> 0 And b3 <> 0 Then
Dim targetpoint As Int32
targetpoint = Chart1.Series("Drawing").Points.AddXY((xcoord(a3, b3)), ((ycoord(a3, b3))))
Chart1.Series("Drawing").Points.Item(targetpoint).Label = "3"
End If
If I understand you correctly, this code can be easily generalized by creating a Sub and calling it with your inches calculation and Label text,:oord are reachable (in scope) Functions:
Triangulate(inches(aft1.Text, ain1.Text), inches(bft1.Text, bin1.Text), 1)
Triangulate(inches(aft2.Text, ain2.Text), inches(bft2.Text, bin2.Text), 2)
Triangulate(inches(aft3.Text, ain3.Text), inches(bft3.Text, bin3.Text), 3)
EDIT-2
Although I have tested the following up to a point, since I do not have your chart properties nor the inches, xcoord and ycoord functions I could not test it completely, so try it out and let me know how it goes.
Sub TriangulateAll()
Try
Dim aft As New SortedList(Of String, TextBox)
Dim ain As New SortedList(Of String, TextBox)
Dim bft As New SortedList(Of String, TextBox)
Dim bin As New SortedList(Of String, TextBox)
For Each ctl As Control In Controls
If TypeOf (ctl) Is TextBox Then
Select Case ctl.Name.Substring(0, 3)
Case "aft"
aft.Add(ctl.Name, ctl)
Case "ain"
ain.Add(ctl.Name, ctl)
Case "bft"
bft.Add(ctl.Name, ctl)
Case "bin"
bin.Add(ctl.Name, ctl)
End Select
End If
Next
Dim a As New List(Of Double)
Dim b As New List(Of Double)
For Each kvp_aft As KeyValuePair(Of String, TextBox) In aft
For Each kvp_ain As KeyValuePair(Of String, TextBox) In ain
a.Add(inches(kvp_aft.Value.Text, kvp_ain.Value.Text))
Next
Next
For Each kvp_bft As KeyValuePair(Of String, TextBox) In bft
For Each kvp_bin As KeyValuePair(Of String, TextBox) In bin
b.Add(inches(kvp_bft.Value.Text, kvp_bin.Value.Text))
Next
Next
For i As Int16 = 0 To aft.Count - 1
Triangulate(a(i), b(i), i.ToString())
Next
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
EDIT
Replace the 3 calls to Triangulate with the following code to completely generalize the Triangulation routine. Note that this routine expects there to be an equal number of each of the TextBox controls: aft, ain, bft, bin. I haven't tested this but it should work.
Dim aft As List(Of TextBox) = Nothing
Dim ain As List(Of TextBox) = Nothing
Dim bft As List(Of TextBox) = Nothing
Dim bin As List(Of TextBox) = Nothing
For Each ctl As Control In Controls
If TypeOf (ctl) Is TextBox Then
Select Case ctl.Name.Substring(0, 2)
Case "aft"
aft.Add(ctl)
Case "ain"
ain.Add(ctl)
Case "bft"
bft.Add(ctl)
Case "bin"
bin.Add(ctl)
End Select
End If
Next
aft.Sort()
ain.Sort()
bft.Sort()
bin.Sort()
For i As Int16 = 0 To aft.Count - 1
Dim a As Double = inches(aft.Item(i).Text, ain.Item(i).Text)
Dim b As Double = inches(bft.Item(i).Text, bin.Item(i).Text)
Triangulate(a, b, i.ToString())
Next
Sub Triangulate(a As Double, b As Double, LabelValue As String)
If a <> 0 And b <> 0 Then
Dim targetpoint As Int32
targetpoint = Chart1.Series("Drawing").Points.AddXY((xcoord(a, b)), ((ycoord(a, b))))
Chart1.Series("Drawing").Points.Item(targetpoint).Label = LabelValue
End If
End Sub

Does VBA have any built in URL decoding?

I just need to decode a URL, for example, replace %2E with .
I can hack out a method if one isn't build in, but my assumption is that there must be a URL decoding tool already existing.
Here's a snippet I wrote years ago
-markus
Public Function URLDecode(sEncodedURL As String) As String
On Error GoTo Catch
Dim iLoop As Integer
Dim sRtn As String
Dim sTmp As String
If Len(sEncodedURL) > 0 Then
' Loop through each char
For iLoop = 1 To Len(sEncodedURL)
sTmp = Mid(sEncodedURL, iLoop, 1)
sTmp = Replace(sTmp, "+", " ")
' If char is % then get next two chars
' and convert from HEX to decimal
If sTmp = "%" and LEN(sEncodedURL) + 1 > iLoop + 2 Then
sTmp = Mid(sEncodedURL, iLoop + 1, 2)
sTmp = Chr(CDec("&H" & sTmp))
' Increment loop by 2
iLoop = iLoop + 2
End If
sRtn = sRtn & sTmp
Next
URLDecode = sRtn
End If
Finally:
Exit Function
Catch:
URLDecode = ""
Resume Finally
End Function
No.
But here's one: URL Encoder and Decoder for VB
Or something along the lines of (possibly not complete):
Public Function URLDecode(ByVal strEncodedURL As String) As String
Dim str As String
str = strEncodedURL
If Len(str) > 0 Then
str = Replace(str, "&amp", " & ")
str = Replace(str, "&#03", Chr(39))
str = Replace(str, "&quo", Chr(34))
str = Replace(str, "+", " ")
str = Replace(str, "%2A", "*")
str = Replace(str, "%40", "#")
str = Replace(str, "%2D", "-")
str = Replace(str, "%5F", "_")
str = Replace(str, "%2B", "+")
str = Replace(str, "%2E", ".")
str = Replace(str, "%2F", "/")
URLDecode = str
End If
End Function
Also, take a look at How can I URL encode a string in Excel VBA?
EncodeURL and DecodeURL function using htmlfile object(Late binding)
I got this source from this site: http://cocosoft.kr/442
Function ENCODEURL(varText As Variant, Optional blnEncode = True)
Static objHtmlfile As Object
If objHtmlfile Is Nothing Then
Set objHtmlfile = CreateObject("htmlfile")
With objHtmlfile.parentWindow
.execScript "function encode(s) {return encodeURIComponent(s)}", "jscript"
End With
End If
If blnEncode Then
ENCODEURL = objHtmlfile.parentWindow.encode(varText)
End If
End Function
Function DECODEURL(varText As Variant, Optional blnEncode = True)
Static objHtmlfile As Object
If objHtmlfile Is Nothing Then
Set objHtmlfile = CreateObject("htmlfile")
With objHtmlfile.parentWindow
.execScript "function decode(s) {return decodeURIComponent(s)}", "jscript"
End With
End If
If blnEncode Then
DECODEURL = objHtmlfile.parentWindow.decode(varText)
End If
End Function
For example,
str = ENCODEURL("/?&=") 'returns "%2F%3F%26%3D"
str = DECODEURL("%2F%3F%26%3D") 'returns "/?&="
Here is the code from the URL posted in another answer in case it goes down as it works great.
http://www.freevbcode.com/ShowCode.asp?ID=1512
Public Function URLEncode(StringToEncode As String, Optional _
UsePlusRatherThanHexForSpace As Boolean = False) As String
Dim TempAns As String
Dim CurChr As Integer
CurChr = 1
Do Until CurChr - 1 = Len(StringToEncode)
Select Case Asc(Mid(StringToEncode, CurChr, 1))
Case 48 To 57, 65 To 90, 97 To 122
TempAns = TempAns & Mid(StringToEncode, CurChr, 1)
Case 32
If UsePlusRatherThanHexForSpace = True Then
TempAns = TempAns & "+"
Else
TempAns = TempAns & "%" & Hex(32)
End If
Case Else
TempAns = TempAns & "%" & _
Format(Hex(Asc(Mid(StringToEncode, _
CurChr, 1))), "00")
End Select
CurChr = CurChr + 1
Loop
URLEncode = TempAns
End Function
Public Function URLDecode(StringToDecode As String) As String
Dim TempAns As String
Dim CurChr As Integer
CurChr = 1
Do Until CurChr - 1 = Len(StringToDecode)
Select Case Mid(StringToDecode, CurChr, 1)
Case "+"
TempAns = TempAns & " "
Case "%"
TempAns = TempAns & Chr(Val("&h" & _
Mid(StringToDecode, CurChr + 1, 2)))
CurChr = CurChr + 2
Case Else
TempAns = TempAns & Mid(StringToDecode, CurChr, 1)
End Select
CurChr = CurChr + 1
Loop
URLDecode = TempAns
End Function
' URLDecode function in Perl for reference
' both VB and Perl versions must return same
'
' sub urldecode{
' local($val)=#_;
' $val=~s/\+/ /g;
' $val=~s/%([0-9A-H]{2})/pack('C',hex($1))/ge;
' return $val;
' }

Resources