VB.NET - I'm curious, why does the return from "Right" not work as a string? - vb.net

If I have a string like input = "AA["
If Right(input, 1) = "[" Then Do stuff
The If statement returns false, even if I try converting things around to chars, etc etc. But if I do this is returns true:
Dim temp As String = Right(input, 1)
If temp = "[" Then Do Stuff
I like knowing little semantics like this, any idea why it comes out this way?

Or don't use Right at all since this is .Net
Dim s As String = "AAAAAAA]"
If s.Substring(s.Length - 1, 1) = "]" Then
Stop
End If
'or
If s(s.Length - 1) = "]" Then
Stop
End If

I've seen weird behavior like that when debugging.
In fact, today I had something simlar
Dim records As Integer
records = If(o.dr Is Nothing, o.ADO.rs.RecordCount, o.ADO.DS.Tables("tbl").Rows.Count)
That should work, using the rs.RecordCount when dr is nothing, otherwise using the Rows.Count. It didn't, records was ending up as zero. Rewrote it as a full if then/else block and it works.
It's never my first thought that the compiler/debugger/ide is messing things up, but you should keep it in the back of your mind for consideration: the programmers that wrote those programs are just as human and fallible as you or me.

It shouldn't. Are you sure you didn't have a typo? The result of RIGHT is a string, and if the input was truly "AA[" the IF will have passed.
I've never had VB act wonky on something like this.

If the code appears in a form, then the .Right property of the form overrides the string manipulation function. You need to specify the parent namespace - e.g. VisualBasic.Right - to ensure that you get the correct method.

I think you may have some kind of strange overload confusion occuring here.
You are specifiing "Right" (which could be calling a local "Right" function).
The function your implying is "Microsoft.VisualBasic.Strings.Right" in most of my code ends up being "Strings.Right" due to the global import.
I would try changing you code to the below and see if it still happens, in order to rule out some overload/scope confusion. (and/or the reduced "Strings.Right")
If Micosoft.VisualBasic.Strings.Right(input, 1) = "[" Then Do stuff

Related

Why does using Update query give me different result instead of updating data in vb.net

I'm trying to update data in textbox and this error show up. Is it incorrect query?
Try
Dim Str = "UPDATE userinfo SET firstname='" & TextBox1.Text.ToUpper & "',lastname='" & TextBox3.Text.ToUpper & "'," &
"WHERE id='" & Label15.Text
connection.Open()
Dim mysc2 As New MySqlCommand(Str, connection)
mysc2.ExecuteNonQuery()
MsgBox("User successfully updated!", MsgBoxStyle.Information)
connection.Close()
Me.Close()
Catch ex As Exception
MsgBox(ex.Message)
connection.Close()
End Try
As noted, it not only less then ideal to try and concat all those things together, but as you can see it is ALSO really easy to mess up the sql string.
So, your sql looks wrong. It should be this:
Dim Str as string
Str = "UPDATE userinfo SET firstname = '" & TextBox1.Text.ToUpper & "'," & _
"lastname = '" & TextBox3.Text.ToUpper & "'" & _
" WHERE id= " & Label15.Text
Now of course, we don't know if "ID" is a string, or a number type. And if it is a number, then you do NOT surround the Lable15.Text value with single quotes. And you had a extra "," after the list textbox 3 in your sql.
But, as noted, the suggestion here is to use parameters. While this is a bit wee extra code, such code is LESS prone to concatenation errors, is easier to read, and in fact easier to write. (you can hit ctrl-d in the code editor to duplicate the line you are on!!!).
and of course, using parameters ALSO gives you AUTOMATIC data typing. So you don't have to worry or think about those extra parameters. And not only do numbers have no single quotes around them, date delimiters can even be more of a challenge.
Along without the messy concatenation?
Along without the data type issue (quotes or not????)
We ALSO get protection from SQL injection.
So, we getting a real nice truckload of bonus features. I have ALWAYS lamented that many suggest to use parameters, but then don't point out the benefits (beyond that of sql injection).
So you might wind up with a extra line or two of code, but that code is LESS error prone, and in most cases will be easier to read, but ALSO MUCH more able to allow you to add more parameters - all without messy string concatenations.
So, our code can be this:
Dim Str As String
Str = "UPDATE userinfo SET firstname = #firstName, lastname = #lastname WHERE id = #id"
Using cmdSQL As New MySqlCommand(Str, connection)
cmdSQL.Parameters.Add("#firstname", SqlDbType.NVarChar).Value = TextBox1.Text
cmdSQL.Parameters.Add("#lastname", SqlDbType.NVarChar).Value = TextBox3.Text
cmdSQL.Parameters.Add("#id", SqlDbType.Int).Value = Label15.Text
cmdSQL.Connection.Open()
cmdSQL.ExecuteNonQuery()
End Using
Some interesting things to note:
First: it really nice to read, right?
Second: Easy to code.
When I typed in this:
cmdSQL.Parameters.Add("#firstname", SqlDbType.NVarChar).Value = TextBox1.Text
While on above, I hit ctrl-d two times. that duplicated the above line.
So now, I just "cursor" up/down into the parameter value area almost like editing a column in Excel. (I did not HAVE to type those extra lines - but just edit the values and change the textbox/label values.
And BETTER is while typing in that code, I can EASY see, and read, view the nice sql line right above in code - so I just read off the parameters as I type, and edit the two additonal parameters rows. So, in fact, I actually wind up typing LESS then your posted code. And with the nice sql text in view - I have a LOWER brain work load - I don't have to remember the parameters - I just read them!
Next up:
SQL server does not care about upper vs lower case - so you don't need to worry about upper and lower - they will match regardless.
More next up:
By wrapping the whole deal inside of a using, then we don't have to close the connection - this is correctly handled by the using block (it cleans up for you).
More more next up:
And because we don't use string concatenation for the values, and DO NOT have to worry about quotes or not, and also get sql injection protection?
We ALSO get STRONG data typing.
In other words, the values from the controls are CAST to the correct data types required by sql server. I mean, often you can munge in a number with quotes as a string - sql server might work, might not! - but this way, automatic taking care of the quotes (or no quotes for numbers) is done for you!
so the updated original sql string should work, but give the parameters a try, and while the using block is a extra line of code, we don't have to close the connection, so we get back that 1 line of code!
The major goal here is it not that you must do this, or do that! Often when starting out, such advice is not all that helpful. Saying don't do that? Geesh - what kind of help is that.
In above, I not only said to use parameters, but I ALSO made a long and impassioned case as to why they are better.
The strong data typing is really nice, and protection from SQL injection is in fact a bonus feature here!
The real gold here is that we wound up with not a lot of code, and code that is easier to maintain, easier to read, and even MORE so if we decide in the future to add some more text boxes etc. on the form.
I mean, lets say you have 4 or 5 text boxes. Can you imagine then how absolute difficult that long huge concatenated string will be to edit, look at, and more so try to debug errors!
So must you use parameters? no, you don't have to, but once you try the above?
You adopt the above because the code is less mental effort and work on your part - and that's really what great code is all about.
I not that great of a coder, and thus your long string sql is too hard for me, and too great of a effort. Only those really good coders can figure out that mess. For me, you have to think as me as a one cell creature - limited brain power. The same goes for great pool players. They actually don't make the hard and difficult shots - they set themselves up in such a way that they never have to make those hard shots, or in this case read and maintain difficult and complex code.
Your code can work - but it is beyond my pay grade and ability to read and maintain such code!
Good luck!

Mid() usage and for loops - Is this good practice?

Ok so I was in college and I was talking to my teacher and he said my code isn't good practice. I'm a bit confused as to why so here's the situation. We basically created a for loop however he declared his for loop counter outside of the loop because it's considered good practice (to him) even though we never used the variable later on in the code so to me it looks like a waste of memory. We did more to the code then just use a message box but the idea was to get each character from a string and do something with it. He also used the Mid() function to retrieve the character in the string while I called the variable with the index. Here's an example of how he would write his code:
Dim i As Integer = 0
Dim justastring As String = "test"
For i = 1 To justastring.Length Then
MsgBox( Mid( justastring, i, 1 ) )
End For
And here's an example of how I would write my code:
Dim justastring As String = "test"
For i = 0 To justastring.Length - 1 Then
MsgBox( justastring(i) )
End For
Would anyone be able to provide the advantages and disadvantages of each method and why and whether or not I should continue how I am?
Another approach would be, to just use a For Each on the string.
Like this no index variable is needed.
Dim justastring As String = "test"
For Each c As Char In justastring
MsgBox(c)
Next
I would suggest doing it your way, because you could have variables hanging around consuming(albeit a small amount) of memory, but more importantly, It is better practice to define objects with as little scope as possible. In your teacher's code, the variable i is still accessible when the loop is finished. There are occasions when this is desirable, but normally, if you're only using a variable in a limited amount of code, then you should only declare it within the smallest block that it is needed.
As for your question about the Mid function, individual characters as you know can be access simply by treating the string as an array of characters. After some basic benchmarking, using the Mid function takes a lot longer to process than just accessing the character by the index value. In relatively simple bits of code, this doesn't make much difference, but if you're doing it millions of times in a loop, it makes a huge difference.
There are other factors to consider. Such as code readability and modification of the code, but there are plenty of websites dealing with that sort of thing.
Finally I would suggest changing some compiler options in your visual studio
Option Strict to On
Option Infer to Off
Option Explicit to On
It means writing more code, but the code is safer and you'll make less mistakes. Have a look here for an explanation
In your code, it would mean that you have to write
Dim justastring As String = "test"
For i As Integer = 0 To justastring.Length - 1 Then
MsgBox( justastring(i) )
End For
This way, you know that i is definitely an integer. Consider the following ..
Dim i
Have you any idea what type it is? Me neither.
The compiler doesn't know what so it defines it as an object type which could hold anything. a string, an integer, a list..
Consider this code.
Dim i
Dim x
x = "ab"
For i = x To endcount - 1
t = Mid(s, 999)
Next
The compiler will compile it, but when it is executed you'll get an SystemArgumenException. In this case it's easy to see what is wrong, but often it isn't. And numbers in strings can be a whole new can of worms.
Hope this helps.

String assignment to dataview unexpectedly removes data row

I'm stumped on a problem where VB is removing a row of data upon a simple string assignment. The processing loop is below. If the dvData dataview has 3 rows (i.e., dvData.Count is 3) then the string assignment below is causing the dataview to lose a row (i.e,. after executing the string assignment the dvData.Count is 2). What more odd is that this same string assignment call is used many other times in the same script without causing the loss of a data row.
For Each oneShipment As Shipment In DelShipmentsList
For intRow = 0 To (dvData.Count - 1)
' Example: if dvData.Count is 3 at this point, then....
dvData(intRow)("Result") = " Receipt Transaction Accepted."
' ... now dvData.Count will be 2!
Next
Next
Try examining your RowFilter property for that DataView object. If it's something like this, it would explain the issue:
dvData.RowFilter = "Result NOT LIKE '*Accepted*'"
It looks like we found the answer, albeit completely unforeseen and worthy of much head scratching. Just to be super sure about passing integers and strings explicitly, I had him us CStr() and CInt() where appropriate. Here's what we found:
' This string causes the dataview to change error
dvData(CInt(intRow))(CStr("Result")) = CStr("Receipt Transaction Accepted")
'This string does not.
dvData(CInt(intRow))(CStr("Result")) = CStr("Receipt Transaction Successful")
Apparently there’s something about the word "accepted". We spent quite a while trying different strings to figure out why the Specified string causes the odd behavior that remains otherwise unexplained.

How to send a query string from function

I'm having a hard time coming up with a good title, but i hope i can explain the situation better. I currently have a query with a criteria which is ("11:00 - 21:00" Or "11:01 - 21:00"), this works perfectly fine when executed, however i will need this criteria in multiple queries therefore i decided to come up with function like below
Function timeIntervals()
timeIntervals = "11:00 - 21:00" & " Or " & "11:01 - 21:00"
End Function
and call it in each query, therefore each time i require to modify this string i can do it through that one instance, however when running this string above it does not function, im assuming its caused by the quotes on the Or, ive tried triple quotes """ and chr(34), however it doesn't work, can someone suggest a work around thank you!
As Remou indicated, you won't be able to get this to work. If you really want to do the check via a VBA function, you could write something like this:
Function timeIntervals(Value) As Boolean
If Value = "11:00 - 21:00" Or Value = "11:01 - 21:00" Then
timeIntervals = True
End If
End Function
Pass the value you want to check, and if the resulting function is true you then display the row. Something like: where timeIntervals(myvalue) = true.
Probably the best solution though is to make a table for the timeIntervals. Then in your query simply write something like:
Where MyValue IN(Select timeValue from timeIntervals)
Using this latter method you can update the table which will update the results for all users, and doesn't require a re-release of your front-end.
No matter what you do with quotes, that is not going to work, because Or will be returned as a string, not the boolean Or that you want. You could use a hidden form with two textboxes, then you can say:
WHERE timeIntervals = Forms!MyForm!Text1 Or Forms!MyForm!Text2
as long as the form remains open, your queries and any forms or reports based on them will work, furthermore, it will be very easy to change the intervals without modifying code.

MS-Access: Replace "bracket"

In one of the ms-access table I work with we have a text field with a set size.
At the end of this field there is some extra code that varies depending on the situation.
I'm looking for a way to remove one of these code but even when the last part is truncated by the field maximum size.
Let's call the field "field" and the code I'm looking to remove "abc-longcode".
If I use the replace SQL function with the string abc-longcode the query will only work when the code is complete.
If I also want my update query (that does nothing but remove this specific code at the end of my field) to work on incomplete codes how would that translate into ms-SQL?
It would have to remove (or replace with "" to be precise) all of the following (example of course, not the real codes):
abc-longcode
abc-longcod
abc-longco
abc-longc
abc-long
abc-lon
abc-lo
abc-l
Obviously I could do that with several queries. Each one replacing one of the expected truncated codes... but it doesn't sound optimal.
Also, when the field is big enough to get all of the code, there can sometime be extra details at the end that I'll also want to keep so I cannot either just look for "abc-l" and delete everything that follows :\
This query (or queries if I can't find a better way) will be held directly into the .mdb database.
So while I can think of several ways to do this outside of a ms-sql query, it doesn't help me.
Any help?
Thanks.
You can write a custom VBA replace method that will replace any of the given cases {"abc-longcode", ... "abc-l"}. This is essentially the same tack as your "several queries" idea, except it would only be one query. My VBA is rusty, but something like:
public function ReplaceCodes(str as string) as string
dim returnString as string
returnString = str
returnString = replace(returnString,"abc-longcode","")
// ... etc...
ReplaceCodes = returnString
end function
I may have gotten the parameter order wrong on replace :)
I would use my own custom function to do this using the split function to get the first part of the string. You can then use that value in the update query.
Public Function FirstPart(thetext As String) As String
Dim ret As String
Dim arrSplitText As Variant
arrSplitText = Split(thetext, "-")
ret = arrSplitText(0)
FirstPart = ret
End Function
Can you use:
Left(FieldX,InStr(FieldX,"abc-")-1)
EDIT re Comment
If there is a space or other standard delimiter:
IIf(InStr(InStr(FieldX, "abc-"), FieldX, " ") = 0, Left(FieldX, InStr(FieldX, "abc-") - 1), Replace(FieldX, Mid(FieldX, InStr(FieldX, "abc-"), InStr(InStr(FieldX, "abc-"), FieldX, " ") - InStr(FieldX, "abc-")), ""))