Save local file from MS SQL varbinary - vb.net

I'm trying to save a local document stored in SQL db using UiPath.
From the execute query activity it returns a DataTable value with one column(“Data”).
If I'm not wrong somehow I need to transform the DataTable.rows(0)(“Data”) (studio is interpreting it as object) to an array of bytes.
I used invoke code but the file is broken:
Dim _MemoryStream As New System.IO.MemoryStream()
Dim _BinaryFormatter As New System.Runtime.Serialization.Formatters.Binary.BinaryFormatter()
_BinaryFormatter.Serialize(_MemoryStream, inputObj)
_MemoryStream.ToArray()
File.WriteAllBytes(“C:\Users\Desktop\test.tiff”, _MemoryStream.ToArray())

Unless you serialised an object when saving, which I doubt, there's no reason to try to deserialise an object when retrieving. Every field from a DataRow is returned as an Object reference, because it must support any type of object, but that object still has its own type. If you saved binary data then that type will be Byte(), i.e. a Byte array. Kinda looks like File.WriteAllBytes takes a Byte array:
File.WriteAllBytes(“C:\Users\Desktop\test.tiff”, DirectCast(inputObj, Byte()))
That is what I would expect that you need to do. It does depend on how you saved the data in the first place but if you used File.ReadAllBytes or Image.Save then this should do the job. If not, show us how you sabed the data in the first place.

Related

Using UTF-8 in VB .net for ä,ö,ü etc

For my current project in need a way to use ä,ö etc. in a datatable that is written to a .csv
It is the same project as in: VB Reading data from SQL Server to Array, writing into .CSV
I know that I need UTF-8 but how do I use it ?
Unlike VB6/VBScript/VBA, VB.Net strings already use full Unicode internally. You can already put accented characters in your string variables (and string members for other objects), and you don't need to do anything special.
There are three things you do need to watch for, though.
First, you must be sure to use NVARCHAR rather than VARCHAR for your Sql Server columns, as well as your ADO.Net parameters. You may also need to be careful about what collation you have (but the default is almost certainly fine here).
Second, when you open your StreamWriter, you need to use unicode-capable correct Encoding. System.Text.UTF8Encoding is one option. You could also do System.Text.UnicodeEncoding (which is UTF16) or System.Text.UTF32Encoding and get accurate output.
Finally, just because you successfully create a unicode CSV file, this does not mean your downstream consumers will handle the file correctly. A lot of text editors and other tools like to assume csv data is ASCII. But that's really outside of your scope. All you can is give them valid data. If they don't process it, that's on them :)
So assuming the database is correct, and based on the other question, you have this code:
Sub WriteCsvFiles(destPath As String, headings As String(), dt As DataTable)
Dim separator As Char = ";"c
Dim header = String.Join(separator, headings)
For Each r As DataRow In dt.Rows
Dim destFile = Path.Combine(destPath, r(0).ToString().Trim() & ".csv")
Using sw As New StreamWriter(destFile)
sw.WriteLine(header)
sw.WriteLine(CsvLine(r.ItemArray, separator))
End Using
Next
End Sub
This is close. However, take a look at the remarks in the documentation for the StreamWriter constructor:
This constructor creates a StreamWriter with UTF-8 encoding without a Byte-Order Mark (BOM), so its GetPreamble method returns an empty byte array. The default UTF-8 encoding for this constructor throws an exception on invalid bytes. This behavior is different from the behavior provided by the encoding object in the Encoding.UTF8 property.
So we kind of already have UTF-8 data, but to really have a correct UTF-8 file, including correct byte-order handling for certain wide characters, we need to change things just a little bit. Where you have this right now:
Using sw As New StreamWriter(destFile)
should become:
Using sw As New StreamWriter(destFile, False, Encoding.UTF8)
It also seems very odd to create a separate file for every row that will all have the same structure. I know it's in your original question, but I'd really push back on that, or find out why, and the maybe re-write the method as so:
Sub WriteCsvFile(destFile As String, headings As IEnumerable(Of String), dt As DataTable)
Dim separator As Char = ";"c
Dim header As String = String.Join(separator, headings)
Using sw As New StreamWriter(destFile, False, Encoding.UTF8)
sw.WriteLine(header)
For Each r As DataRow In dt.Rows
sw.WriteLine(CsvLine(r.ItemArray, separator))
Next
End Using
End Sub

Save a custom Class to a Access Table with VBA

I have a really weird one that I'm not quite clear if it's possible. I have an Access database that I've built that stores documents basically. And in it, you are able to produce these documents in Excel. As it stands today, I have it storing values I want to put into a cell as a table value, such as a string. But I'd like to possibly store an attributed string so that I can also store formatting.
I have an idea of how I would make a custom class that would basically be an attributed string, but then I still have the problem that it would need to be an object that could be stored in an Access table.
I was thinking to make an OLEObject field in the table, and save it there, but it gives me an error when I try saving my custom class in that field.
Run-time error '438':
Object doesn't support this property or method
I tried making an object variable and then setting my custom class to that, but still same error.
Dim attStr As New AttributedStringClass
attStr.Value = "Test Test"
Dim oleObj As Object
Set oleObj = attStr
Dim rst As Recordset: Set rst = CurrentDb.OpenRecordset("tblTest")
rst.AddNew
rst("attributeString") = oleObj
rst.Update
AttributedStringClass
Option Compare Database
Option Explicit
Dim zValue As String
Property Get Value() As String
Value = zValue
End Property
Property Let Value(dValue As String)
zValue = dValue
End Property
I kept it really simple to test if I could store the custom class, just in case it wasn't possible.
Is what I'm trying to do even possible? Or am I barking up the wrong tree?
Thanks in advance!
Unfortunately, what you looking for is object serialization. .net supports serialization, and thus you can convert a object into XML, or these days the much tighter and shorter format used is JSON.
You could however, make your own serializer. So, you would have to take the custom class you make, and call a routine (passing the class object) to spit out all the values as text. Perhaps the format could be comma delimited, or I suppose even JSON format (but we don't have a good JSON serlizer/de-serlizer like we do in .net).
You then save the text in a standard memo column. You could then read/pull that data, and call a routine to de-serialize the text back into the object.
But, since you do know the class, you can expose each property, and use a for/each loop. this trick is outline here:
https://www.mrexcel.com/forum/excel-questions/466141-use-custom-class-each-loop.html
However, what I would simply do is make your class, add all the "members", and then simply add a routine called serialize, and de serializer.
So:
dim clsMyClass as new clsTour
clsMyClass.HotelName = "Greenwood Inn"
.etc. etc. etc.
' now get all of the values as a string
dim strCsv as string
strCsv = clsMyClass.Serlize
' now, the comma delimited strCsv as all the values of the class as a string
rstData!Cdata = strCsv
rstData.update
Now, at this point,the memo field is saved (as noted, xml, json, or csv format is fine).
To pull + load (de-serialize) the class, we now go:
dim rstData as DAO.Recordset
' code to load up reocord set
set rstData = currentdb.OpenRecordSet("Select * from tblTours where id =2")
strCsv = rstData!CData
dim clsMyClass as new clsTour
clsMyclass.Serialize = strCsv
' at this point, your class is now loaded with all the correct values.
eg:
msgbox "Hotel name = " & clsMyClass.HotelName
So, in the .net world, the idea of serializing a class ito a string, passing to a web service, and then on that end, they de-serialize the object back into a class/object.
In .net, this generating is built into the frame work. So, when you call a SOAP or these days more common a REST service, then the data is sent to you as xml (or json). On your end, you now call the de-serialize method, and you have the object now ready for use in your code. So, this idea of converting a class into some kind of "string" or something that can be saved as text, or pass (or pulled) from a web site is rather common these days.
So, your idea and question is rather normal, especially if you coming from any of the modern systems and frameworks that support serialization.
As noted, if your class only has say 5-10 values to save, then a simple method to serialize and de-serialize all values to/from a string from the values the class holds is not hard at all. But for complex objects, then of course one would want a development platform that supports this automatic. In .net, you can pass any object to a serializer, and it will spit back the xml (or json) string. Now that string can be saved, sent to a web site, or some program. And to get the object, you de-serialize that string back to the object for use in your code.
Do keep in mind that this whole concept only works well for a well defined class, and if the class is not dynamic, then the concept works well.

Buffer cannot be null

I try to download files from gridview .. I save files in database and then I display in grid-view I try this
I save files in database table not in folder so I try to download files
when i do this document is download but there is problem when i debug the code and check then in this line
Dim row = db_stu.dResult.Tables(0).Rows(i)
dResult shows
docid document docname docextension
1014 System.Byte[] Book2.xlsx .xlsx
and then when i further proceed docname shows "1912218726836.xlsx" this and also file download as a corrupt
These two lines together are wrong:
Dim binary() As Byte = TryCast(structDb.dstResult.Tables(0).Rows(i).Item("document"), Byte())
Dim ms As MemoryStream = New MemoryStream(binary)
The reason to use TryCast is that the object that you're trying to cast may not be the type you're trying to cast it as. In that case, TryCast will return Nothing. Use of TryCast should ALWAYS be followed by a test for Nothing, which you haven't done. You're using the result as though you're sure that there will be an object of that type. If you know that then you should be using DirectCast rather than TryCast.
Even if you do know that the reference will not be to an object of a different type and you use DirectCast though, if you cast a null reference, i.e. Nothing, then you're still going to get Nothing back. So, you first need to determine whether structDb.dstResult.Tables(0).Rows(i).Item("document") can refer to an object of a type other than Byte(). If it can't then use DirectCast rather than TryCast. Either way, it appears that that expression can produce Nothing so you need to check for Nothing either way, e.g.
Dim binary() As Byte = TryCast(structDb.dstResult.Tables(0).Rows(i).Item("document"), Byte())
If binary IsNot Nothing Then
Dim ms As MemoryStream = New MemoryStream(binary)
'...
End If
EDIT: If the column is nullable then you need to first test whether the row contains null and then only use the data if there is some:
Dim row = structDb.dstResult.Tables(0).Rows(i)
If Not row.IsNull("document") Then
'There is data so go ahead and use it.
Dim binary = DirectCast(row("document"), Byte())
'...

Read data from JSON file, add new data following data structure VB.NET

Okay, So I have been trying to wrap my small head around this topic for some time now. All I want to do is:
1) Read all data from a .json file
2) Add data to the json file, while still following structure (Adding objects withing java somehow maybe?)
3) Save file back
I have figured out how to download json.net and add it to my project. I just have no clue how to use it.
I am a big noob at java and vb, so please don't reply with a bunch of unnecessary stuff that won't help. (Really irritated by this already :|)
I am writing this with a GUI, so no console stuff, as I seen from most of the sources on the interweb.
Things I have tried: Reading all lines and storing into var, array and or string.
Dim str() As String = IO.File.ReadAllLines("C:\MCHCI_Profile.txt")
I got this from somewhere but threw and error of 1 dimensional array
Dim singleChar As Char
singleChar = str.Chars(14)
Somethings with streamreader and writer but not too much, as it confuses me.
Using sr As StreamReader = New StreamReader("C:\MCHCI_Profile.txt")
Do
ListBox1.Items.Add(sr.ReadLine())
Loop Until sr.EndOfStream
End Using
^This seemed to work, it added all the right data into combobox and kept json structure, but I don't know what to do with it.
Final conclusion
It seems like the only real way to do this is with json.net
So please let me know how to read data, add simple objects to it and save it back
Thank you !!!
As of now i don't get what actually you are trying to achieve. Let me assume that
1. You are accepting a text file content to a one dimensional array.
2. then you are selecting a single character from particular index from that array, isn't it?
this will achieve the first option without fail.
Dim str() As String = File.ReadAllLines("D:\sample.txt")
if you want particular line of text then you can take it from the array by using the index value as like the following:
Dim lineOfText As String = str(14)
if you want a single character from particular line of text then you can take it from the array by using the index value as like the following:
Dim singleChar As Char=str(14).ToCharArray()(2)

Corrupt string when writing to Oracle DB

I am serializing some data to xml, then writing the output to an Oracle DB.
The serialized data can be very long and is writing to a column type of LONG (it never will reach the max value of LONG, which is something like 32,000 chars)
Sometimes when my data is written, it appears to corrupt and just display "?" and lots of other control characters, sometimes the write works perfectly.
The function i am using always returns the XML with no problem, the problem occurs when the data is written.
This is my serializer function:
Private Function Serialize(myObject As object)
//serialize the object to a string...
Dim x = New System.Xml.Serialization.XmlSerializer(myObject .[GetType]())
Dim stringWriter = New StringWriter()
x.Serialize(stringWriter, myObject )
Dim test = stringWriter.ToString()
Return stringWriter.ToString()
stringWriter.Close()
End Function
I am then writing the datawhich is returned to the DB using nHibernate, i will not include this code as it is very long and has worked without fail for a long time. The problem seems to be with how Oracle is interpreting the data.
My unitofwork commits without any error - just the data is corrupt when oracle receives it.
UPDATE
If i copy the stringwriter output, then paste this into the column in the database i can commit without a problem
As advised by wolφi in the comments.
The fix for this was to use CLOB as the column data type. XMLType did not exist in my version of Oracle.