VB seems to lose newlines when called over COM - vb.net

I have a VB method
Public Sub append_text(ByVal s As String)
f1.TextBox1.AppendText(s)
End Sub
which is called over COM from C++
_bstr_t b(L"test\nnew\nlines\n");
ATLENSURE_SUCCEEDED(t->append_text(b));
But the text box ends up saying
testnewlines
Without the aforementioned new lines.
Why is that then?

For the sake of completeness, posting my comment as an answer (now that I know it's correct...):
Different operating systems consider different character combinations as new lines. The *nixes, for instance, use a single \n, as in your code. Windows, on the other hand, uses the \r\n combination. Therefore, the single \n in your string just isn't enough to be considered a new line marker. Using \r\n will do the trick.

Eran is right.
To fix it on the VB side, try this
Dim s2 As String = s.Replace(vbLf, vbCrLf)
f1.TextBox1.AppendText(s2)
EDIT Sideshow Bob has compiled and tested this.

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

VB 2010: Console application prints some superscript number characters as normal

I just have a small issue with a Visual Basic (2010 Express) .NET application I'm making. It's a console-based application and I want it to print superscript numbers.
Well, I've found out the superscript numbers from Charmap and my code is this:
Public Module MainModule
Public Sub Main()
Console.Write(GetExponentialNumAsStr(12345, 12345)) 'This must be printed as 12345¹²³⁴⁵
Console.ReadKey(True)
End Sub
Public Function GetExponentialNumAsStr$(Number As Double, Exponent%)
If Exponent = 1 Then Return Number : Exit Function
Return Number.ToString & Exponent.ToString.Replace("-", "⁻").Replace("0", "⁰").Replace("1", "¹").Replace("2", "²").Replace("3", "³").Replace("4", "⁴").Replace("5", "⁵").Replace("6", "⁶").Replace("7", "⁷").Replace("8", "⁸").Replace("9", "⁹")
End Function
End Module
Okay, the GetExponentialNumAsString$ function works well and gives 12345¹²³⁴⁵, which is okay (checked through Immediate window), but the only problem is that while printing the same in the Console view gives this:
123451²345
Why is it that only 2 is shown in superscript form and why not the other digits also?
If I try printing 0 to 9 as superscript, it comes like this:
1²345678?°
Well 9 is gone, but the other digits is what confusing me. Only 2 and 0 are shown in superscript form!
I also tried copy-pasting all the superscript numbers in a Command Prompt window... this is what came:
Command Prompt, in fact, when copy-pasted, shows correctly!
So what should I do? Convert those superscript numbers to CP-437 (DOS) encoding and then display it?
Please help me! Thank you everybody!
EDIT: I've tried saving that thing as a file in my Desktop using CP-437 encoding. What appears is like 1ý345678?ø. And when converted back manually to UTF-8 or one of the general encodings, it comes back as 1²345678?°.
Also tried using ECHO ¹²³⁴⁵⁶⁷⁸⁹⁰>Hello123.TXT and what came was the same thing as above. So... has no use.
And I am a bit sure that CP-437 has those superscript characters because Command Prompt can display them!!!
Thanks to Hans Passant's comment, the trick is to set the Console's output encoding to UTF-8, such as
Console.OutputEncoding = System.Text.Encoding.UTF8
And look! It comes!

Determine Number of Lines in a String Read in from an Access Database

I am writing a program in Visual Basic that writes and reads to and from a Microsoft Access Database. When reading from the database, one of the functions that I am trying to perform is to determine the number of lines in a multi-line string that was written to the database and then subsequently read from the database. Here's what I have tried so far with no luck.
Dim stringLines() As String = databaseReader("multilineString").ToString.Split(CChar("Environment.NewLine"))
Dim stringLinesCount As Integer = stringLines.Length
For some reason, this always results in stringLinesCount being equal to one, regardless of how many lines the string has. In this example, I am using Environment.NewLine, but I have tried \n, \r, vbCr, vbLf, and vbCrLf as well, and they all result in a value of one. Since none of these seem to be working, what can I use instead to determine the number of lines?
Edit:
Dim splitCharacters() As Char = {CChar(vbCrLf), CChar(vbCr), CChar(vbLf), CChar(Environment.NewLine), CChar("\n"), CChar("\r")}
Dim stringLines() As String = databaseReader("multilineString").ToString.Split(splitCharacters)
Dim stringLinesCount As Integer = stringLines.Length
Since Chris Dunaway provided the answer that I view as helpful but posted it as a comment, here's what he said:
VB cannot use C# style escape sequences, so CChar("\n") and CChar("\r") is meaningless in VB. Also, calling CChar("Environment.NewLine") is wrong because you are trying to convert the actual string "Environment.NewLine" to a single character, which obviously won't work. You can just use Environment.Newline directly in the call to String.Split.
If Chris decides to post his comment as an answer, please let me know so that I may remove this.

How to replace text to a 'vbcr'

Using vb.net and visual studio 2012.
I have a bunch of strings using custom text replacement.
By that I mean that they are all one-line strings using, for example, "&1" to replace 'vbcr' and so on.
I have to take this string and replace all the "&1" by a vbcr.
I tried using regex and stringbuilder replace. Here is an example:
finaltext = firsttext.Replace("&1", vbcr)
But doing it this way results in replacing the "&1" by a simple space.
I thought that vbcr was the problem but I tried to reverse my code by:
finaltext = firsttext.Replace(vbcr, "&1")
The vbcr were correctly replaced by "&1" so I don't understand why my original code is not working.
I know it's possible using a long complicated custom function but I would prefer to avoid this solution if possible.
According to MSDN, the syntax of String.Replace states that the first argument is the oldValue and the second argument is the one that replaces it.
Also, if you need newlines, you should be using Environment.NewLine:
finaltext = firsttext.Replace("&1", Environment.NewLine)
Environment.NewLine is easier to read and it also takes care of the platform for you, being
A string containing "\r\n" for non-Unix platforms, or a string
containing "\n" for Unix platforms.

Splitting String by New Line VB.NET

I'm writing a program that needs to split text in a RichTextBox by a new line. I've tried
For Each Line As String In RichTextBox1.Text.Split(vbNewLine)
And I've tried
For Each Line As String In RichTextBox1.Text.Split(System.Enviroment.NewLine)
Neither are working. It works if there's only one line of text but not after that. Any suggestions?
I guess the easiest way to do it is to use RichTextBox.Lines like so
For Each Line As String In RichTextBox1.Lines
' Do whatever
Next
Not sure why splitting by Environment.NewLine didn't work for you though, it worked fine for me when I just tested.
Edit: Just noticed the comment on the question, oops. That'll teach me for being slow with posting.