Why isn't my String updating? - vb.net

I have a small string variable with a length of 400-500 characters spaces included. I've tried a few things as far as removing some parts of the string, while in a Do/While loop. I'm looking to go through the loop, then remove 300 characters from it, however it doesn't seem to be actually removing it from the string.
Are we not actually able to modify a string object and must be forced to SubString the text variable to get the desired result?
Do while stringText.Length >= 300
'stringText.replace(textToRemove, "") This doesn't replace the string variable
'stringText.Remove(0,299) This also doesn't remove the specified range of characters
Loop

Strings in .NET and VB are immutable, meaning that a string can never change once it's been defined. What the various Replace/Remove methods do is return a new, modified string, which you can store to the same variable.
Like this:
Do while stringText.Length >= 300
stringText = stringText.Replace(textToRemove, "")
Loop
It's important to note, though, that this is potentially expensive - a new string object is allocated. If you have a lot of modifications to make to a string separately, each one will create a new copy, and for large strings it might create unnecessary memory allocations.
For this reason, we have the System.Text.StringBuilder class (as mentioned by roryap), which lets us manipulate strings directly. Read up on it.

These functions return a value, you must assign the value returned to the original string for it to be updated:
e.g.
stringText = stringText.replace(textToRemove, "")
Otherwise you are just discarding the value returned - the functions do not mutate the original string

You have to assign string for the return value
stringText =stringText.replace(textToRemove, "")

Related

i want to make a new variable that says shot1 shot2 shot3 so on and forth how do i do this?

Here is what i have tried so far , but no new shot variable is being declared
Module Module1
Dim shotlist As New List(Of Boolean)
Dim shono As Integer = 0
Dim shonos As String
Dim shotname As String
Dim fshot As Boolean
Dim shots As String
Sub Main()
For i As Integer = 0 To 1000
Dim ("shots" & i) as String = "shots" & i
fshot = Convert.ToBoolean(shots)
Next
End Sub
End Module
You can't do things this way. The variable names you see when you write a program are lost, turned into memory addresses by the compiler when it compiles your program. You cannot store any information using a variable's name - the name is just a reference for you, the programmer, during the time you write a program (design time)
Think of variables like buckets, with labels on the outside. Buckets only hold certain kinds of data inside
Dim shotname as String
This declares a bucket labelled shotname on the outside and it can hold a string inside. You can put a string inside it:
shotname = "Shot 1"
You can put any string you like inside this bucket, and thus anything you can reasonably represent as a string can also be put inside this bucket:
shotname = DateTime.Now.ToString()
This takes the current time and turns it into a string that looks like a date/time, and puts it in the bucket. The thing in the bucket is always a string, and lots of things (nearly anything actually) can be represented as a string, but we don't type all our buckets as strings because it isn't very useful - if you have two buckets that hold numbers for example, you can multiply them:
Dim a as Integer
a=2
Dim b as Integer
b=3
Dim c as Integer
c=a*b
But you can't multiply strings, even if they're strings trust look like numbers; strings would have to be converted to numbers first. Storing everything as a string and converting it to some other type before working on it then converting it back to a string to store it would be very wearisome
So that's all well and good and solves the problem of storing varying information in the computer memory and giving it a name that you can reference it by, but it means the developer has to know all the info that will ever be entered into the program. shotname is just one bucket storing one bit of info. Sure you could have
Dim shotname1 as String
Dim shotname2 as String
Dim shotname3 as String
But it would be quite tedious copy paste exercise to do this for a thousand shotname, and after you've done it you have to refer to all of them individually using their full name. There isn't a way to dynamically refer to bucket labels when you write a program, so this won't work:
For i = 0 To 1000
shotname&i = "This is shotname number " & i
Next i
Remember, shotname is lost when compiling, and i is too, so shotname&i just flat out cannot work. Both these things become, in essence, memory addresses that mean something to the compiler and you can't join two memory addresses together to get a third memory address that stores some data. They were only ever nice names for you to help you understand how to write the program, pick good names and and not get confused about what is what
Instead you need the mechanism that was invented to allow varying amounts of data not known at the design-time of the program - arrays
At their heart, arrays are what you're trying to do. You're trying to have load of buckets with a name you can vary and form the name programmatically.
Array naming is simple; an array has a name like any other variable (what I've been calling a bucket up to now - going to switch to calling them variables because everyone else does) and the name refers to the array as a whole, but the array is divided up into multiple slots all of which store the same type of data and have a unique index. Though the name of the array itself is fixed, the index can be varied; together they form a reference to a slot within the array and provide a mechanism for having names that can be generated dynamically
Dim shotnames(999) as String
This here is an array of 1000 strings, and it's called shotnames. It's good to use a plural name because it helps remind you that it's an array, holding multiple something. The 999 defines the last valid slot in the array - arrays start at 0, so with this one running 0 to 999 means there are 1000 entries in it
And critically, though the shotnames part of the variable name remains fixed and must be what you use to refer to the array itself(if you want to do something with the entire thing, like pass it to a function), referring to an individual element/slot in the array is done by tacking a number onto the end within brackets:
shotnames(587) = "The 588th shotname"
Keep in mind that "starts at 0 thing"
This 587 can come from anything that supplies a number; it doesn't have to be hard coded by you when you write the program:
For i = 0 to 999
shotnames(i) = "The " & (i+1) & "th shotname"
Next i
Or things that generate numbers:
shotnames(DateTime.Now.Minute) = "X"
If it's 12:59 when this code runs, then shotnames(59), the sixtieth slot in the array, will become filled with X
There are other kinds of varying storage; a list or a dictionary are commonly used examples, but they follow these same notions - you'll get a variable where part of the name is fixed and part of the name is an index you can vary.
At their heart they are just arrays too- if you looked inside a List you'd find an array with some extra code surrounding it that, when the array gets full, it makes a new array of twice the size and copies everything over. This way it provides "an array that expands" type functionality - something that arrays don't do natively.
Dictionaries are worth mentioning because they provide a way to index by other things than a number and can achieve storage of a great number of things not known at design time as a result:
Dim x as New Dictionary(Of String, Object)
This creates a dictionary indexed by a string that stores objects (I.e. anything - dates, strings, numbers, people..)
You could do like:
x("name") = "John"
x("age") = 32
You could even realize what you were trying to do earlier:
For i = 0 to 999
x("shotname"&i) = "The " & (i+1) & "th shotname"
Next i
(Though you'd probably do this in a Dictionary(Of string, string), ie a dictionary that is both indexed by string and stores strings.. and you probably wouldn't go to this level of effort to have a dictionary that stores x("shotname587") when it's simpler to declare an array shotname(587))
But the original premise remains true: your variable has a fixed part of the name (ie x) and a changeable part of the name (ie the string in the brackets) that is used as an index.
And there is no magic to the indexing by string either. If you opened up a dictionary and looked inside it, you'd find an array, together with some bits of code that take the string you passed in as an index, and turn it into a number like 587, and store the info you want in index 587. And there is a routine to deal with the case where two different strings both become 587 when converted, but other than that it's all just "if you want a variable where part of the name is changeable/formable programmatically rather than by the developer, it's an array"

name.split based on multiple delimiters that have some of the same characters

I have files coming into SFTP that are in the following format: 12345678_STLREPT. On occasion, they have two underscores instead of one. ie: 12345678__STLREPT. This throws my sorting program through a loop. So I attempted to do the top line of code below first, it threw an I/O exception. The second line I can make work if I add "__" as a delimiter, but my question is how does Name.Split work. I haven't been able to determine through my google searches if it stops at the first delimiter it finds in the string.
Basically, If it goes through the list of delimiters it would ideally match one of them, perform the split, then stop before performing the rest.
Example:
Say I have a file, named 1234__ASDF.PDF
Would the following code split it once for the first delimiter (__) then two more times for the second (_)? I feel like it would.
fileInfo.Name.Split(New Char() {"__", "_", "-"})
Is anyone aware of a better solution to this problem?
Thank you,
Code, again. Top throws error, bottom is existing code:
fileInfo = fileInfo.Name.Replace("__", "_")
Dim a() As String = fileInfo.Name.Split(New Char() {"_", "-"})
First, be aware of your data types and what you are stuffing into them. A Char holds a single character. Trying to stuff two hyphens into a Char - for shame.
Next, be aware of your tools. The Split function accepts a second parameter that controls how empty elements should be handled. It also includes overloads for accepting a string array.
Dim fileParts As String() = fileInfo.Name.Split(
New Char() {"_", "-"},
StringSplitOptions.RemoveEmptyEntries)

How to remove part of a string backwards?

I have a vb string with this value: c:\program\bin\files
I need to convert this string to this value: files
All i need is the last folder of the path.
The path is not fixed. It can be anything like: d:\app\win\7\sp1\update
In this case the string must be converted to: update
I think that should be done by searching the string backwards for the first occurrence of \ and removing everything before it, including the \ itself.
But obviously i don't know how to do it. :)
Thank you!
EDIT:
I need to use this to fill a ComboBox...
This is what i am using:
ComboBox1.Items.AddRange(IO.Directory.GetDirectories(appPath & "\Updates\Version"))
It gives me a ComboBox like:
c:/program/Updates/Version/Beta1
c:/program/Updates/Version/Beta2
c:/program/Updates/Version/Beta3
c:/program/Updates/Version/Beta4
And i would like to have the ComboBox like:
Beta1
Beta2
Beta3
Beta4
Rather than try to pull apart the string yourself, have a look at the System.IO.Path class.
In your case, the GetFileName method does what you want:
lastFolder = System.IO.Path.GetFileName(path)
To fill a combo box with names you can use a LINQ query like this:
ComboBox1.Items.AddRange(
From path
In IO.Directory.GetDirectories(IO.Path.Combine(appPath, "Updates\Version"))
Select IO.Path.GetFileName(path))
Also, try to use the Path.Combine method when joining path fragments together. It's safer than just joining strings.
In VBScript, which this is tagged you have two choices. This was written before any code was edited into the question.
Use InstrR which is Instr but from back to front of string.
You also have StrReverse which reverses a string.
InStrRev
Returns the position of an occurrence of one string within another, from the end of string.
InStrRev(string1, string2[, start[, compare]])
StrReverse
Returns a string in which the character order of a specified string is reversed.
StrReverse(string1)
If using the File System Object it has a method to do specifically what you want.
GetParentFolderName Method
Returns a string containing the name of the parent folder of the last component in a specified path.
Set fso = CreateObject("Scripting.FileSystemObject")
object.GetParentFolderName(path)

Value of type '1-dimensional array of String' cannot be converted to 'String'. (BC30311)

I have this code which gives an error:
'declaration
Dim strFieldValues As String
'split
strFieldValues = strRecord.Split(",") 'field are separated by commas
Well, the error seems to be pretty self-explanatory to me. You've declared a variable of type String - i.e. it can hold a value of a single String reference:
Dim strFieldValues As String
You've then tried to assign a value to it returned from String.Split():
strFieldValues = strRecord.Split(",")
Now String.Split() returns a String array, not a single string value.
So you have two courses of action open to you:
Change strFieldValues to an array variable
Change the value you assign to it
My guess is that you want the first, but we don't know what you're trying to achieve. The simplest approach would be to combine declaration and initialization:
Dim strFieldValues = strRecord.Split(",")
You may also need to change the arguments to Split - I don't know how VB will sort out that call.
If all you want to do is just retrieve either side of the resulting string array, you could just invoke the left or right part like this:
strFieldValues = strRecord.Split(",")(0) ' Text to the left of the delimiter character
Or
strFieldValues = strRecord.Split(",")(1) ' Text to the right of the delimiter character
Of course, this assumes that the delimiter character does exist, so you should take the necessary precautions to ensure that you won't run into a runtime exception if said character is not found on the string you are splitting.

adding variables numical values (newb question)

Yesterday i had a look at how to set values of variables from nummbers stored in external txt files
the variables then needed to be added up so i used trial and error first
((XVAL) + (NEWVAL))
assuming that XVAL was set to 10 and NEWVAL was set to 20 i expected to get the answer of thirty but waqs presented with the new value of 10 20
VB.net pysicaly added the two values together but i wanted the mathematical product of the two which is ((10) + (20)) = 30
yep its a newb question could anyone explain how to achieve what im affter
XVAL and NEWVAL are strings, so they are simply being concatenated together. You need to convert them to integers, so that VB.NET will treat them as such. To do this, use the Int32.Parse() method.
Dim intXVAL As Integer = Int32.Parse(XVAL)
Dim intNEWVAL as Integer = Int32.Parse(NEWVAL)
Dim result = intXVAL + intNEWVAL
You want to cast them to a number first.
Try CDbl.
See http://msdn.microsoft.com/en-us/library/Aa263426 for more.
edit: Oops, thought you were talking about VBA.
Try using Double.Parse(YOURVALUE) if you're talking about VB.NET.
Have you tried the Val() function?
Val(XVAL) + Val(NEWVAL)
The + operator in VB.NET (for backwards-compatibility reasons) means both add and concatenate depending on the types of the variables it is being used with. With two numeric types (Integer, Single, Double, etc.), it adds the values together as you would expect. However, with String types, it concatenates the two strings.
Presumably, then, your XVAL and NEWVAL variables are String types because they're being read out of a text file, which is causing VB.NET to concatenate them into a new string instead of add them together. To get the behavior you're expecting, you need to convert them to numeric types.
Some of the other answers suggest casting simply casting the string values to numeric types (CInt, CSng, CDbl, etc.), but this may not work as expected if the value contained by your string cannot be converted to number. The Int32.Parse method will throw an exception if the value held by your string cannot be represented as a number. This is especially important to keep in mind if you're reading values from a text file that are not guaranteed to adhere to any particular constraints.
Instead, you probably want to use something like Int32.TryParse, which returns a Boolean value indicating whether or not the conversion succeeded and will not throw an exception.
As you are reading from a text file I assume that you are reading your values out as strings, so when you do this:
((XVAL) + (NEWVAL))
It is effectively concatenating the two strings together. In order to get the mathematical product of the two values these need to be int/integers which is the number type.
There are a number of ways you can do this, but in essence you have to 'cast' the strings to ints and then do your calculation.
So in vb.net it would be something like this (pseudo code):
Dim xval As String = "10"
Dim newval As String = "20"
Dim x As Integer = Int32.Parse(xval)
Dim n As Integer = Int32.Parse(newval)
Dim prod As Integer = x + n
Console.WriteLine(prod)
There are a number of other methods of doing this, for example using:
int.Parse(...)
or
Integer.TryParse(...)
More information on these sorts of type conversions can be found here:
http://dotnetperls.com/integer-parse-vbnet
One thing to bear in mind with these sorts of conversions is that you have to be certain that your input data is convertable. Otherwise your code will throw exceptions. This is where TryParse is useful as you can use this to check the inputs and handle invalid inputs without the need for exceptions.