My aims is to do the following
Convert UNIX Time (i.e. 1582818012) to HEX String (i.e. 5E57E2DC) - Solved
Convert HEX String to Byte Array (i.e. 5E57E2DC) to (i.e. &H5E, &H57, &HE2, &HDC) - Pending
How can I do the conversion?
So I this case the result will be something like below:
Dim oneByte() As Byte = {&H5E, &H57, &HE2, &HDC}
oneByte(0)= 5E
oneByte(1)= 57
etc...
Using a couple of standard methods
Dim ut As Integer = 1582818012
Dim uts As String = Convert.ToString(ut, 16)
'look at oneByte in hex
Dim oneByte() As Byte = BitConverter.GetBytes(ut).Reverse.ToArray
' (0) &H5E Byte
' (1) &H57 Byte
' (2) &HE2 Byte
' (3) &HDC Byte
Related
I need to take a string and assign each character to a new string variable for a Text To Speech engine to read out each character separately, mainly to control the speed at which it's read out by adding pauses in between each character.
The string contains a number which can vary in length from 6 digits to 16 digits, and I've put the below code together for 6 digits but would like something neater to handle any different character count.
I've done a fair bit of research but can't seem to find a solution, plus I'm new to Groovy / programming.
OrigNum= "12 34 56"
Num = OrigNum.replace(' ','')
sNum = Num.split("(?!^)")
sDigit1 = sNum[0]
sDigit2 = sNum[1]
sDigit3 = sNum[2]
sDigit4 = sNum[3]
sDigit5 = sNum[4]
sDigit6 = sNum[5]
Edit: The reason for needing a new variable for each character is the app that I'm using doesn't let the TTS engine run any code. I have to specifically declare a variable beforehand for it to be read out
Sample TTS input: "The number is [var:sDigit1] [pause] [var:sDigit2] [pause]..."
I've tried using [var:sNum[0]] [var:sNum[1]] to read from the map instead but it is not recognised.
Read this about dynamically creating variable names.
You could use a map in your stuation, which is cleaner and more groovy:
Map digits = [:]
OrigNum.replaceAll("\\s","").eachWithIndex { digit, index ->
digits[index] = digit
}
println digits[0] //first element == 1
println digits[-1] //last element == 6
println digits.size() // 6
Not 100% sure what you need, but to convert your input String to output you could use:
String origNum = "12 34 56"
String out = 'The number is ' + origNum.replaceAll( /\s/, '' ).collect{ "[var:$it]" }.join( ' [pause] ' )
gives:
The number is [var:1] [pause] [var:2] [pause] [var:3] [pause] [var:4] [pause] [var:5] [pause] [var:6]
I am trying to implement a calculator using VBA. I am facing trouble with calculating the result using recursion.
I've tried implementing the function. I always end up getting the result to be zero.
Idea:
For example, 2+3+4+5 is to be calculated
The function will recursively read and combine two elements with every step. For instance, at step 2, from the first position, the first two slots of the array give you "2" and "+" so you know that you need to add 2 to the rest of the array starting from position 3. Finally, the result of the array would be 5 (from step 5) + 4 (from step 4) + 3 (from step 3) + 2 (from step 2) = 14.
Please find the code below. I have tried implementing it but I am getting type mismatch error. "Display" is a string to remember the current display of the calculator.
Dim Memory(1 To 100) As String
' The current position used by the calculator inside the memory array
Dim CurrentPos As Integer
' This function is a recursive function for calculating the result of the expression
' stored in the Memory array, starting at the position Pos.
'
' Note that the return value is a Long number. When you calculate the result you need
' to convert the numbers (as text) in the memory to long numbers using CLng().
Function CalcTotal(ByVal Pos As Integer) As Long
'
' Task 4: Calculating the Result Using Recursion
'
' Case 1: if Pos is bigger than what you have in the Memory array
' Nothing is available
' Case 2: if Pos is exactly at the end of the Memory array
' Return the number in the position
' Case 3: Memory(Pos) is a number and Memory(Pos + 1) is an operator
' Return the number in the current position together with the rest of the Memory array
If Pos > CurrentPos Then ' Case 1: Nothing left to read
Display = "0"
'return 0 as the result because there is nothing to do...
ElseIf Pos = CurrentPos Then ' Case 2: There is only a number left
Display = CLng(Memory(Pos))
'return the number in the current position...
Else ' Case 3: Read the next two slots of the array and combine with the rest of the array
Display = CLng(Memory(Pos)) + CLng(Memory(Pos + 1))
CalcTotal (Pos + 2)
End If
End Function
This might help you get started:
Public MyInputs As Variant
Sub Test()
MyInputs = Array("2", "+", "3", "+", "4", "+", "5")
Debug.Print Application.Evaluate(CalcTotal(UBound(MyInputs))) '~~> prints 14
End Sub
Function CalcTotal(n As Integer) As String
If n = 0 Then
CalcTotal = MyInputs(n)
Else
CalcTotal = MyInputs(n) & (CalcTotal(n - 1))
End If
End Function
Notes:
CalcTotal will return a string e.g. 5+4+3+2
Application.Evaluate parses that string as a computation and prints 14
The problem in the code is , You are returning a String "0" , for a function who returns LONG , the correction is replace the "0" (string) to a 0 (long).
' This function is a recursive function for calculating the result of the expression
' stored in the Memory array, starting at the position Pos.
'
' Note that the return value is a Long number. When you calculate the result you need
' to convert the numbers (as text) in the memory to long numbers using CLng().
Function CalcTotal(ByVal Pos As Integer) As Long
'
' Task 4: Calculating the Result Using Recursion
'
' Case 1: if Pos is bigger than what you have in the Memory array
' Nothing is available
' Case 2: if Pos is exactly at the end of the Memory array
' Return the number in the position
' Case 3: Memory(Pos) is a number and Memory(Pos + 1) is an operator
' Return the number in the current position together with the rest of the Memory array
If Pos > CurrentPos Then ' Case 1: Nothing left to read
' Display = "0" WRONG THATS A STRING
Display = 0
'return 0 as the result because there is nothing to do...
ElseIf Pos = CurrentPos Then ' Case 2: There is only a number left
Display = CLng(Memory(Pos))
'return the number in the current position...
Else ' Case 3: Read the next two slots of the array and combine with the rest of the array
Display = CLng(Memory(Pos)) + CLng(Memory(Pos + 1))
CalcTotal (Pos + 2)
End If
End Function
I have the following tabular data:
Raw data:
Description
String A Q1FY18
String B Q1FY18, String B Q2FY18
String C Q4FY17, String C Q1FY18, String D Q2FY18
String E Q2FY18
I would like to split this column into multiple columns. The target data frame would look like this:
Desired output:
Description Period
String A Q1FY18
String B Q1FY18
String B Q2FY18
String C Q4FY17
String C Q1FY18
String D Q2FY18
String E Q2FY18
What comes to mind is that the original column is comma delimited, so there must be a way to create new columns by splitting the strings using the comma as the delimiter. This step would look something like this:
First step
Description Period1 Period2
String A Q1FY18
String B Q1FY18 Q2FY18
String C Q4FY17 Q1FY18
String E Q1FY18 Q2FY18
The next step would be to collapse the table to get the desired output. It would be easier if I could use other tools for data manipulation such as R or Python, but those are not an option in this case due to end-user limitations. How would you go about transforming the raw data to get to the desired output? Is there some way to split the raw data using the comma as the delimiter and having access automatically determine the number of new columns it should create? I would appreciate your help!
You could try something like this:
Dim strArray() As String
strTest = "String B Q1FY18, String B Q2FY18"
strArray = Split(strTest, ",")
For intCount = LBound(strArray) To UBound(strArray)
Debug.Print Trim(strArray(intCount))
Next
UPDATED - I added 2 screen shots with 0.00 in the data and one with 1234.56 in the data
I am using an old VB6 set of code as 95% works to read a text file that gets converted and stored in MS SQL. The strings are all good however there are numbers mixed into the text binary file that I haven't figured out how to read. The original application the numbers are all currency however the hex dump of the numbers looks to be 4 byte numbers.
Either way I am not sure how to read the numbers into a local variable. Maybe I am not starting at the correct place in the data. In the example below I am starting at the <160>.
Here is a dump of the part of the binary file with 0.00 in the data:
Here is a dump of the part of the binary file with 1234.56 in the data:
Note the arrow point to where the data changed.
This is my last try but that doesnt work either.
Function ReadFloat(f As Integer, Optional ShowDB As Boolean = False) As String
On Error GoTo 0
Dim c As Single
Dim S(4) As Byte
Dim x As Integer
Dim flt As Single
Get f, , S
For x = 1 To 4
Debug.Print x & " " & S(x) & " " & Hex(S(x)); "='" & Chr(S(x)) & "'"
Next x
CopyMemory flt, S, 4
My initial inspection suggests that the bytes starting:
40 E2 01
are what you're looking for. These are stored little endian, so 01E240 is hex for 123456 in decimal. So my guess would be 32 bit integers (4 byte long type). You can test this by using -0.01 as a value, this should give:
... FF FF FF FF ...
in the file.
If you're only interested in reading just these values then you can read and discard the first x values. Something like:
Dim yDiscard(123) As Byte
...
Get #1, ,yDiscard
Or alternatively, just seek to the position first before reading:
Seek #1, 123
To work out what byte values to expect in general, I found the following to be useful. Just run the code in a module:
Sub main()
Dim lValue As Long
Dim cValue As Currency
Dim nValue As Single
Dim dValue As Double
Dim sValue As String
Dim vValue As Variant
lValue = 123456
cValue = 1234.56
nValue = 1234.56
dValue = 1234.56
sValue = "1234.56"
vValue = CDec(1234.56)
Open "c:\test1.bin" For Binary As 1
Open "c:\test2.bin" For Binary As 2
Open "c:\test3.bin" For Binary As 3
Open "c:\test4.bin" For Binary As 4
Open "c:\test5.bin" For Binary As 5
Open "c:\test6.bin" For Binary As 6
Put #1, , lValue
Put #2, , cValue
Put #3, , nValue
Put #4, , dValue
Put #5, , sValue
Put #6, , vValue
Close #1
Close #2
Close #3
Close #4
Close #5
Close #6
End Sub
You can then inspect each file in a hex editor (I use MadEdit but anything will do).
It's probably useful to also try simple values like 1.00, 2.00, 10.00, -1.00 and see how the bytes differ each time.
This may also be informative (fairly in depth):
http://www.codeguru.com/vb/gen/vb_misc/algorithms/article.php/c7495/How-Visual-Basic-6-Stores-Data.htm
And to actually answer the question, something like the following will read a 32 bit integer and convert to currency:
Function ReadAmount(iFileHandle As Integer, lFileBytePosition As Long) As Currency
Dim lValue As Long
Seek #iFileHandle, lFileBytePosition
Get #iFileHandle, , lValue
ReadAmount = CCur(lValue) / 100
End Function
There's no need for an intermediate byte array.
True floating point are bad when using currency, so actually your number is an integer with fixed point.
First : put them in an integer variable (type Long)
Second : divide by 100 to get back the decimal !
Straightforward method to convert it to single:
Dim S(4) As Byte 'your 4 bytes, like (1)=&H40, (2)=&HE2 (3)=&H01, (4)=&H00
Dim Buffer As Long
Buffer = S(4) * 16777116 Or S(3) * 65536 Or S(2) * 256 Or S(1)
Dim flt As Single
flt = Buffer / 100
Ok... I guess my brain has finally gone on vacation without me today. I have extracted 2 fields from a website and I get this string
vData = "Amount Owed [EXTRACT]$125.00[EXTRACT]
vData was declared as an array (string).
I split vData on [EXTRACT] and I end up with 2 string variables like this:
varA = "Amount Owed"
varB = "$125.00"
To parse varB, I use
Dim varC as Currency
varC = val(varB)
I want to use varC in an If statement:
If Val(VarC) <> 0 Then
I was expecting varC to be 125 but when I look at varC is 0. I can't figure out why varC = 0 and not 125.
Use CCur(varB) instead of Val(varB). CCur converts to a Currency type, so knows about $ and other things.
Explanation from the MS docs:
... when you use CCur, different decimal separators, different thousand separators, and various currency options are properly recognized depending on the locale setting of your computer.
Val is only looking for straight numbers:
The Val function stops reading the string at the first character it can't recognize as part of a number. Symbols and characters that are often considered parts of numeric values, such as dollar signs and commas, are not recognized.