I know there is already existing topic with the same name Convert a hex string to base64 in an excel function However I am not receiving the same result as I am expecting by VBA provided in the thread. I am using this website and it provides the correct answer https://cryptii.com/pipes/base64-to-hex
It looks like there are 12 unnecessary characters in result provided by Hex2Base64. How to make it work like a website?
I know there is simple solution to input to another cell something like: =LEFT(cell;20) but how it is possible to make with current VBA?
So I have:
HEX: 01 00 00 00 05 00 00 00 00 E3 07 04 00 0F 00
On the website I receive BASE64: AQAAAAUAAAAA4wcEAA8A
By solution provided, in already existing thread, I receive BASE64: AQAAAAUAAAAA4wcEAA8AAAAAAAAAAA==
Function Hex2Base64(byVal strHex)
Dim arrBytes
If Len(strHex) Mod 2 <> 0 Then
strHex = Left(strHex, Len(strHex) - 1) & "0" & Right(strHex, 1)
End If
With CreateObject("Microsoft.XMLDOM").createElement("objNode")
.DataType = "bin.hex"
.Text = strHex
arrBytes = .nodeTypedValue
End With
With CreateObject("Microsoft.XMLDOM").createElement("objNode")
.DataType = "bin.base64"
.nodeTypedValue = arrBytes
Hex2Base64 = .Text
End With
End Function
The problem is with input parameter - hex string with spaces. Removing spaces gives expected results:
Debug.Print Hex2Base64(Replace("01 00 00 00 05 00 00 00 00 E3 07 04 00 0F 00", " ",""))
Related
I got 8 bytes Hex values in a cell as below which is in little endian format
00 00 08 04 22 00 40 00
With text split I could get individual hex values in an array.
= TEXTSPLIT(A1, , " ")
00
00
08
04
22
00
40
00
Is there an excel formula that I can use to grab the values in reverse order from an array to do below?
00
40
00
22
04
08
00
00
I don't want to use LEFT or MID or RIGHT extractors as I want to create generic formula that works on all data types.
For this very specific case you could use =TRIM(CONCAT(MID(" "&A1,SEQUENCE(8,,22,-3),3))) but to be more generic, try:
Formula in A2:
=TEXTJOIN(" ",,SORTBY(TEXTSPLIT(A1,," "),ROW(1:8),-1))
I suppose you can make this even more generic for any string you split on space:
=LET(r,TEXTSPLIT(A1,," "),TEXTJOIN(" ",,SORTBY(r,SEQUENCE(ROWS(r)),-1)))
Note this is almost an exact copy of this question where you could also use the technique shown by #ScottCraner using INDEX().
=MID(SUBSTITUTE(A1, " ", ""), SEQUENCE(1, LEN(SUBSTITUTE(A1, " ", ""))/2, LEN(SUBSTITUTE(A1, " ", ""))-1, -2), 2)
I want to write the hexadecimal values to a binary file in order they look the same when I open in hex editor.
My current code is this:
Sub Write2Binary()
Dim i As Integer
Dim nFileNum As Integer
Dim sFilename As String
sFilename = "D:\OutputPath\Test.bin"
strBytes = "F3 A1 02 00 04 00 8D 24 44 C3 8C 03 83 49 26 92 B5"
arrBytes = Split(strBytes)
nFileNum = FreeFile
Open sFilename For Binary Lock Read Write As #nFileNum
For i = LBound(arrBytes) To UBound(arrBytes)
Put #nFileNum, , arrBytes(i)
Next i
Close #nFileNum
End Sub
This code produces the following binary file that when I open it in a Hex editor looks like this:
08 00 02 00 46 33 08 00 02 00 41 31 08 00 02 00
30 32 08 00 02 00 30 30 08 00 02 00 30 34 08 00
02 00 30 30 08 00 02 00 38 44 08 00 02 00 32 34
08 00 02 00 34 34 08 00 02 00 43 33 08 00 02 00
38 43 08 00 02 00 30 33 08 00 02 00 38 33 08 00
02 00 34 39 08 00 02 00 32 36 08 00 02 00 39 32
08 00 02 00 42 35
That is different to the content I want to have in binary file. When I open the file in Hex editor I like to see the following content:
F3 A1 02 00 04 00 8D 24 44 C3 8C 03 83 49 26 92 B5
How can I do this?
Your data represents Hex values of bytes to be wriiten to a binary file. Split produces an array of strings, each element being a string represention of a hex value. As Comintern told you, you need to convert them to numbers.
Put uses the type of the Varname parameter to determine the length (number of bytes) to write, so in this case you need to convert to Byte, so use CByte to convert. CByte also needs to know the values are Hex, so prepend with &H
All up, your code becomes
Sub Write2Binary()
Dim i As Long
Dim nFileNum As Integer
Dim sFilename As String
Dim strBytes As String
Dim arrBytes As Variant
sFilename = "D:\OutputPath\Test.bin"
strBytes = "F3 A1 02 00 04 00 8D 24 44 C3 8C 03 83 49 26 92 B5"
arrBytes = Split(strBytes)
nFileNum = FreeFile
Open sFilename For Binary Lock Read Write As #nFileNum
For i = LBound(arrBytes) To UBound(arrBytes)
Put #nFileNum, , CByte("&H" & arrBytes(i))
Next i
Close #nFileNum
End Sub
So I've got really big .bin files with bytes written in them. They have 96-bit numbers written in them as two's complement numbers (still no ASCII, only bytes). Now I have to write an assembly program to sort the numbers in this files and save it to another file (don't ask why, assembly class). I've done it for a file with 32k numbers, like this:
./main < inSort32Kx96b.bin > XD.bin
diff outSort32Kx96b.bin XD.bin
The file outSort32Kx96b.bin is given to me by my teacher. So now diff doesn't output anything, they are identical (I can check that with hexdump or mcview). But I got another file inSort1Kx96b.bin. And I also sort it. But then diff says:
Binary files outSort1Kx96b.bin and XD.bin differ
#Edit:
cmp gave the number of byte where those 2 files differ. Now I can see the difference:
So the difference appears from 0x000017C0. Then I don't know now. If they are written as two's complement numbers in little endian order, then which one is bigger, f.e
00 00 00 00 00 00 00 81 00 00 00 00
or
00 00 00 00 00 00 00 7F 00 00 00 00
?
A hexdump shows you the single bytes in big endian order. If a bunch of bytes have to be interpreted as a number, only the byte order is reversed.
little endian big endian (C notation)
AB CD EF = 0xEFCDAB
01 02 03 04 05 06 07 08 09 10 11 12 = 0x121110090807060504030201
Let's translate your examples to big endian order:
0x000000008100000000000000
0x000000007F00000000000000
You can see that the first number is bigger.
"Two's complement number" is not a very clear expression. Better is "signed integer". The sign which shows whether the number is positive or negativ, is the very first bit of the number. This bit can be found at the begginning of a big endian number and the end of a little endian number.
Positive:
00 00 00 00 00 00 00 81 00 00 00 00 = 0x000000008100000000000000
00 00 00 00 00 00 00 81 00 00 00 10 = 0x100000008100000000000000
00 00 00 00 00 00 00 81 00 00 00 7F = 0x7F0000008100000000000000
Negativ:
00 00 00 00 00 00 00 81 00 00 00 80 = 0x800000008100000000000000
00 00 00 00 00 00 00 81 00 00 00 CD = 0xCD0000008100000000000000
00 00 00 00 00 00 00 81 00 00 00 F0 = 0xF00000008100000000000000
I am trying to debug an issue where my data is stored in Azure Table Store as a byte[]. I am using the Cerebrata Azure Management Studio and it shows the byte[] column as:
16000000010000000E00000001010400000031343230
Does anyone know what format this is stored in? How can I convert this into a byte array? It does not look like a base 64 or UTF encoded string.
Haha... the data is literally stored as bytes, just in hex form.
i.e. 16000000010000000E00000001010400000031343230 is really:
16 00 00 00 01 00 00 00 0E 00 00 00 01 01 04 00 00 00 31 34 32 30
:-)
So the rest is trivial... I used a quick function like this:
var hex = "16000000010000000E00000001010400000031343230";
byte[] bytes = new byte[hex.Length/2];
for(int i=0; i<hex.Length;i+=2)
{
bytes[i/2] = byte.Parse(
hex.Substring(i, 2),
System.Globalization.NumberStyles.HexNumber);
}
I made TDataset descendant asynchronous, instead of sleep or ProcessMessages in main thread it works by events from network thread. So when Recordset is ready it calls
procedure TMySqlQuery.OrdinalOnDataReady(Sender: TObject);
begin
AddToLog('OrdinalOnDataReady');
FDataAvailable := true; // used in IsCursorOpen
inherited Open;
if Assigned(FParentOnDataReady) then
FParentOnDataReady(self);
end;
It works, but sometime I have issues with GetRecord by Open called from this thread and DBGrid's GetFieldData called from main thread by DBGrid's DrawCells from Form's ProcessMessages. By logging both functions I see
[17:10:39] RecordToBuffer row 0
[17:10:39] len = 17 buf :
00 E0 10 C3 00 0A 00 00 00 F0 10 C3 00 0B 00 00 | .ïœ.ï“.....ÿ€.ï“....
00 | .
[17:10:40] RecordToBuffer row 1
[17:10:40] len = 17 buf :
00 00 FF C3 00 25 00 00 00 10 11 C3 00 0B 00 00 | ..ÿï“.%.....ï“....
00 | .
[17:10:40] ActiveBuffer
[17:10:40] len = 17 buf :
00 E0 10 C3 00 0A 00 00 00 F0 10 C3 00 0B 00 00 | .ïœ.ï“.....ÿ€.ï“....
00 | .
...
more ActiveBuffer
...
[17:10:40] ActiveBuffer
[17:10:40] len = 17 buf :
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ................
00 | .
[17:10:40] len = 8 buf :
00 00 00 00 00 00 00 00 | ........
and on break by assert when ActiveBuffer column data is nil I can see that DBGrid attempts to read row higher than GetRecord readed into own internal FBuffers. For example if assertion fired at GetFieldData row 3 - FBuffers filled up to row 2 from total 36 rows available in Recordset. When I debugging step by step GetRecord with F8 there is no errors utnil I press F9 and get assertion at another record.
I'm not quite understand how exactly DBGrid works with TDataset (even stack trace is huge), but can this thread races be solved?
Solution was quite simple: since data in TDataset's FBuffers (from Data.DB) filled with 0 if not initialized it is possible to find filled ActiveBuffer by GetRecord or not by adding yet another marker byte into record and assigning not 0 in GetRecord.
So if DBGrid attempts to read uninitialized data I checking marker in GetFieldData, if 0 result false and exit. Since DBGrid extracting data to same cells more than once I still have it filled with proper data.
It is workaround but it works.