I'm new to programming, and I have one small question. I wrote a code to create a xml file with 5 lines and everything works like a charm. Now I have a textbox and I want the input from the box, named INPUT be written in the middle of one line. This is my code:
Private Sub Entry_Click(sender As Object, e As EventArgs) Handles Entry.Click
Dim data As String() = {
"<?xml version=""1.0"" encoding=""utf-8""?>",
"<EntryQue xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"">",
"<NumberReq>0</NumberReq>",
"<TypeReq>7</TypeReq>",
"<Amount>", INPUT.Text, "</Amount>",
}
File.WriteAllLines("C:/Prog/xml/DATA.xml", data)
The problem is that the INPUT is written in a new line, between amount and /amount, like this:
Amount
123456
/Amount
How can I put it in the same line...for example Amount123456/Amount ?
Your array of string is delimited by commas, so each comma indicates a new line in the output file. Instead of this:
"<Amount>", INPUT.Text, "</Amount>"
Do this:
"<Amount>" & INPUT.Text & "</Amount>"
For details on the string concatenation operators (there are two), see here. I use the & operator because you are concatenating mixed data type (numeric & string):
https://msdn.microsoft.com/en-us/library/te2585xw.aspx
The + Operator (Visual Basic) has the primary purpose of adding two numbers. However, it can also concatenate numeric operands with string operands. The + operator has a complex set of rules that determine whether to add, concatenate, signal a compiler error, or throw a run-time InvalidCastException exception
The & Operator (Visual Basic) is defined only for String operands, and
it always widens its operands to String, regardless of the setting of
Option Strict. The & operator is recommended for string concatenation
because it is defined exclusively for strings and reduces your chances
of generating an unintended conversion.
Related
Im having this error pop up when running my app, i cant seem to find what causes the error, as I'm not even using any Double variables
Private Sub btnCrearListing_Click(sender As Object, e As EventArgs) Handles btnCrearListing.Click
conexion.Open()
Dim CrearListing As New OleDbCommand("INSERT INTO Listing (ID_Listing, precio, cantidad_item, ID_Usuario, ID_Item, Tipo_Listing) VALUES (" + ContadorListing + "," + Val(txtPrecio) + "," + Val(txtCantidad) + "," + Login.JugadorLogeado + "," + ItemListado + ",'" + cboTipoListing.Text + "')", conexion)
ContadorListing = ContadorListing + 1
conexion.Close()
End Sub
If you're going to concatenate strings then use the concatenation operator (&), NOT the addition operator (+). If both operands are String objects then addition maps to concatenation. If the operands are different types though, one will need to be implicitly converted to the other type in order for the addition to be perfromed. In this case, the system is trying to implicitly convert the String to a Double in order to add it to the other number but it obviously fails because that String doesn't represent a number. If you use the concatenation operator then the system knows you want to concatenate, so it will convert the number to a String.
You really ought to have Option Strict On, which would catch bad code like this at compile time, rather than letting it slip through to run time. It won;t tell you how to fix it necessarily but it will at least tell you that there's something to fix. ALWAYS turn Option Strict On in your project properties and also in the VS options, so it will be On by default for all future projects. You can then turn it On at the file level on the rare occasions that you actually need it for specific code.
Having said all that, you shouldn't be building SQL code using string concatenation in the first place. ALWAYS use parameters as it avoids a number of issues. I won't go into specifics here, as that's beyond the scope of the question you actually asked, but you should read this and modify your code accordingly.
I'm experimenting with learning how conversions work between variable types. Right now, I'm looking at using one conversion inside a Try/Catch (for values that can't convert). Is there a way to have a string representation of a value (obtained from a TextBox), convert it to a test type, and then see how that converts to all the other VB standard types in a loop? Or even better if there is a resource that already does this.
I can do this, but the code is very close to being repetitive and I'm hoping for a loop of some kind to simplify and shorten it.
First of all, there is no such thing as variable type in VB.net. May be you confusing with object variables - but this is not the same thing
Dim o As Object
o = 1 ' integer
The type that is stored in o is still integer. It is boxed.
Dim i As Integer = CInt(o)
You just un-boxed it. It works because object is lowest of types and all other derive from it. So, it can "box" any other type.
In UI we use text boxes to collect data. Text boxes can contain only string. And unless you writing these strings to a file like txt or xml you usually need to convert these strings to a type you use in application.
Dim port as Integer = Convert.ToInt32(txtPort.Text)
This is not really the area where you can determine, what type is in that text box. You really need to know upfront - what are you expecting there? You can test your text for being one type or another by using
Integer.TryParse
Date.TryParse
.....TryParse
.............
But the thing is, some data can successfully pass this test fro multiple types.
Good question. While it is possible to declare variables of type type and use them in a loop, these cannot be used in declarations or DirectCast.
Dim types() As Type = {GetType(Integer), GetType(Double)}
Dim testType As Type = GetType(Double)
The easiest way might be to test each value individually something like this (although you'll probably want a try-catch for each or all the items).
Dim xInteger As Integer
xInteger = TextBox1.Text
s &= "Integer: " & xInteger.ToString & vbcrlf ' or some test
Dim xDouble As Double
xDouble = TextBox1.Text
s &= "Double" & ": " & xDouble.ToString & vbcrlf
...
I have a string that is 109000 characters in length, and it wont fit on one line, I get a "line is too long." error.
I know that with normal CODE you can do the "_" at the end of your code like
this code is too long so I will use the _
this code acts like it is on the same line
but in a string it takes the "_" to be part of a string (as it should). There is no information that I could find on this, so here it is for you guys, stackoverflow.
The documentation on the "Line is too long" error states that the maxiumum line length is
65535, so this is why you are getting the error.
There are a few solutions:
You can concatenate the string using the &
Dim s As String = "this code is too long so I will use the" &
"this code acts like it is on the same line"
Note you can also use + to concatenate string but make sure you have Option Strict On if you do (& is safer as the result is always a String). See comparison between the two here: Ampersand vs plus for concatenating strings in VB.NET
You can use a string builder. This may be more efficient if you are continually adding strings to the original string (especially if you do this in a loop):
Dim sb As new StringBuilder
sb.Append("this code is too long so I will use the")
sb.Append("this code acts like it is on the same line")
Debug.Writeline(sb.ToString)
See MSDN for More information about Concatenation here
Dim longString As String = "loooooooooooooooooooooooooo" + _
"ooooooooooooooggggggg"
I am writing a simple program that writes input to a sequential access file and then reads them back and displays them in the list box using .readLine. The numbers need to be formatted for american currency and right aligned. Problem is i cant figure out how to properly write the .readLine to do that. i am working out of a text book, and still new to vb.net, so im looking for the simplest way to solve this problem without re-writing alot of it. The code i have tried is within the DO loop below:
Private Sub btnDisplay_Click(sender As Object, e As EventArgs) Handles btnDisplay.Click
'declare new inFile Varable as a streamreader object
Dim inFile As IO.StreamReader
'opens gross.txt for input
inFile = IO.File.OpenText("gross.txt")
'.Exists() searches /bin folder for gross.txt, returns a boolean value
If IO.File.Exists("gross.txt") Then
inFile = IO.File.OpenText("gross.txt")
'fill the list with the values
Do Until inFile.Peek = -1
lstContents.Items.Add(inFile.ReadLine.PadLeft(7, " ")).ToString("C2")
Loop
Else
MessageBox.Show("The file you have requested does not exist", "Gross Pay Project",
MessageBoxButtons.OKCancel, MessageBoxIcon.Error)
End If
End Sub
We can get this down to a single line:
lstContents.Items.AddRange(File.ReadAllLines("gross.txt").Select(Function(s) Double.Parse(s).ToString("C2").PadLeft(7)).ToArray())
Or in a more readable way, with the error-handling and method defintion back:
Private Sub btnDisplay_Click(sender As Object, e As EventArgs) Handles btnDisplay.Click
Try
lstContents.Items.AddRange( _
File.ReadAllLines("gross.txt").
Select(Function(s) Decimal.Parse(s).ToString("C2").PadLeft(7)).
ToArray() )
Catch ex As IOException
MessageBox.Show("Unable to open the file you requested", "Gross Pay Project",
MessageBoxButtons.OKCancel, MessageBoxIcon.Error)
End Try
End Sub
Now to explain this code. To begin with, I replaced your call to IO.File.Exists() with a Try/Catch block. File.Exists() only checks one reason a file might not open. It ignores other reasons like file permissions and process locking. Even when checking whether a file exists, the file system is volatile and you still have a race condition situation, where a file might be deleted in between when you check if it exists and when you go to open it. It's almost always better to just skip calling File.Exists() entirely and instead use the try/catch block to handle an exception if opening the file fails, as shown above.
Going into the Try/Catch block, I changed the code so that it uses AddRange() instead of adding one item at a time in a loop. This allows us to build an array with the items we want and update the UI in a single step. Building that array may seem like extra work, but .Net provides some features to help us. In this case, the File.ReadAllLines() method reads in the entire file in one step, so that we can start with an array right from the beginning. All we have to do is make the array have the right information.
To get the information we want in the array, I perform a projection or transformation of the existing data. To accomplish that, I used a LINQ select operator (or the .Select() extension method, in this case). The LINQ extension methods generally ask you to build an inline function. In the case of this use of the select operator, that inline function expects a string variable (s) that represents a single line in the original array. I then supply code to transform that original string into the format we need.
Each line in the file begins as a string value, but we know that the string variable holds pricing information... it will be numeric. The best way to transform numeric data is generally to convert it a number, which is what I do. I chose the Decimal type, because when working with money you almost always want to prefer Decimal over Double or Single. In this case, Double may have been okay, but Decimal will still work just fine. Once I have a numeric type like Decimal, I can use a Numeric Format String to get a string back that has the correct currency symbol and formatting. The original code did not work because you were trying to use the format string with a value that was already a string type. The format strings only work with numeric types, like the Decimal we have here. Now that I have a string with the correct text, all I need to do now is pad it so that it will be right-justified when shown in the list.
Finally, you will recall that the AddRange() method expects an array. The LINQ select operator does not produce an array. It produces something called an IEnumerable. This is a type that represents a sequence of some kind. Arrays are one kind of sequence, but they are not the only kind of sequence, and the LINQ system wants to be able to work with many different kinds of sequences. Thankfully, getting back to an array is easy: just call the ToArray() method.
You should definitely use a ListView instead of a listbox. I don't think you can right-align with listbox items.
I have a simple question: How vb.net determine string length and treat string's termination?
I know in C (and its family) null character is end of string. In vb6 null character has no effect on string's termination but in vb.net it seems to be foggy!
Assume this code in vb6:
Private Sub Command1_Click()
Dim Str As String
Str = "Death is a good user," & Chr(0) & " Yes I'm good"
RichTextBox1.Text = Str
RichTextBox1.Text = RichTextBox1.Text & vbNewLine & Len(Str)
End Sub
This what happens when this code runs:
And it's alright. This is similar code in C:
#include "stdafx.h"
#include <string.h>
int main(int argc, char* argv[])
{
char *p="Death is a good user,\0 Yes I'm good";
printf("String:%s\nString length:%d\n",p,strlen(p));
return 0;
}
And this is what happens:
Which is fine too according C rules, but here is the same code in vb.net:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim str As String = "Death is a good user," & Chr(0) & " Yes I'm good"
RichTextBox1.Text = str
RichTextBox1.Text &= vbNewLine & str.Length
End Sub
And what happens:
Which doesn't seems about right!
Edit 1: Writing to file seems to be right:
Edit 2: Mark and tcarvin suggest, it may be UI's problem but it doesn't explain why vb6 shows whole string!
Edit 3: I know Windows and its API,UI,... are written in C, So it would be normal for them to react like C, but as I showed above, they don't.
In VB.NET (and C#) strings are treated very similarly to how they are in VB6, and that is they have an explicit length that is not based on any particular character or characters contained within them.
In regards to the RichTextBox, it would simply appear that it does not support an embedded null character.
There are 3 distinct string types used in your snippets by the underlying runtime support libraries:
BSTR, used by VB6. It is an COM Automation type used by all ActiveX controls that can store a Unicode string and includes an explicit length. BSTR can therefore store embedded zeros.
C strings, used by the C language. No explicit length is stored, a zero indicates end-of-string. The winapi is C based and uses C strings in its functions.
System.String, the .NET string type and used in any .NET code. Similar to a BSTR, it also has an explicit length field and can thus store strings with embedded zeros.
In all three cases interop needs to be used by the underlying runtime support libraries to make the string visible:
VB6 uses an ActiveX control for the RichEditBox. Exactly what the control looks like is hard to guess, it is pretty specific to VB6 and is named richtx32.ocx. It does use the native Windows richedit control as well (riched32.dll) so the ActiveX control very much acts as a wrapper to make the native Windows control usable in a VB6 app. You've conclusively demonstrated that it honors the behavior of a BSTR and handles embedded zeros, like any ActiveX control should.
The C program uses the C Runtime Library which in turn implements printf() by calling a winapi console function, WriteConsole(). This api function is C based but the buck already stopped at printf(), an embedded zero is a string terminator for that function. No surprises here.
The Winforms program uses the .NET RichEditBox class, a managed wrapper for the riched20.dll native Windows control. The underlying mechanism is pinvoke, almost all properties and methods of the class are implemented by pinvoking SendMessage() to send messages like EM_SETTEXTEX, the message that alters the text displayed by the control. This is also a C based api, a zero acts like a string terminator. Unlike the richtx32.ocx wrapper, the .NET RichEditBox wrapper class does not make an effort to properly handle strings with embedded zeros. It simply passes the string as-is and leaves it up to the pinvoke marshaller to convert the .NET string to a C string. Which has no other option than to truncate the string at the zero since C strings don't have a length field.