I'm trying to create a find and replace macro for use as an add-in. I'd like to do so with a userform containing two multiline textboxes where users can enter the strings they would like to find and replace. I've figured out how to put these strings into arrays, but cannot figure out how to match the 'find' array with the 'replace' array and run a Replace command.
Is there some way to give each entry in each array a value, and match them up? I.e. the first string in the 'find' textbox gets a value of 1, the second gets a value of 2, and the same for the 'replace' textbox. Then the macro replaces any instances of 'find' string value 1 with 'replace' string value 1, and so on.
Here's the code I've figured out so far, thanks in advance for the help.
Private Sub CommandButton1_Click()
Dim Find_text As String
Dim Replace_text As String
Dim Find_lines As Variant
Dim x As Integer
Dim Replace_Lines As Variant
Dim y As Integer
Dim find As String
Dim Replace2 As String
Find_text = Find1.Text
Replace_text = Replace1.Text
Find_lines = Split(FindReplace2.Find1, vbCrLf)
Replace_Lines = Split(FindReplace2.Replace1, vbCrLf)
For x = LBound(Find_lines) To UBound(Find_lines)
find = Find_lines(x)
For y = LBound(Replace_Lines) To UBound(Replace_Lines)
Replace2 = Replace_Lines(y)
Next y
Next x
End Sub
Related
I got a problem I just cant fix. I have a string, want to split it at ";" (that is working) and then trim the values.
Dim cell As String
Dim objects() As String
cell = Range("X74").Text
objects= Trim(Split(cell, ";"))
I get my error on the Trim-function. I then tried the following approach:
For Each object In objects
object = Trim(object)
Debug.Print object
Next
This works, but doesnt save the trimmed value to my objects-array.
Despite naming your variables objects and object, they are an array of simple Strings resp. a simple String, and in VBA a string is not an object.
In your For Each-Loop, you are copying a string to the variable object, and no matter what you do with it, it doesn't change the content of the objects-array.
If you really need to change the content of the objects-array, use a loop like that:
Dim i As Long
For i = LBound(objects) To UBound(objects)
objects(i) = Trim(objects(i))
Debug.Print objects(i)
Next
And you should think about changing the name of your variables...
I would try to avoid vba names as variables:
Sub tst()
Dim yourcell As String, i As Long
Dim yourobjects() As String
yourcell = Range("X74").Text
yourobjects = Split(yourcell, ";")
For i = LBound(yourobjects) To UBound(yourobjects)
yourobjects(i) = Trim(yourobjects(i))
Debug.Print yourobjects(i)
Next i
End Sub
I'm an extreme beginner with vb and coding in general and this is my first post on this site. I am running into a wall with a project I am working on. This is the smallest block of code in the project but all other functions will pull from the array I'm trying to populate. Essentially I need to populate an array with numbers representing the prices of DVDs from a .txt file. The .txt file is formatted as follows:
The Lord of the Rings, 10.50
Avatar, 5
Gangs of New York, 7.5
etc
Where 10.50 is the value I would want to assign to dblPrices(0). It is required to not change the format of the .txt file. So far, this is what I was using but when testing the output I'm getting back 0's:
'Declare variables.
Dim intCount As Integer = 0
Dim strLine As String
'Open the file for input.
inFile = IO.File.OpenText("availableDVDs.txt")
'Remove alpha characters from string, assign numeric values to array representing price.
Do Until inFile.Peek = -1
strLine = inFile.ReadLine.ToUpper.Replace("[A-Z]", "")
strLine = strLine.Replace(" ", "")
strLine = strLine.Replace(",", "")
Double.TryParse(strLine, dblPrices(intCount))
intCount += 1
Loop
This is related to a school project so I'm not necessarily looking for someone to do my work for me, but perhaps point me in the right direction. Thank you!
If you use List(Of T) (The T stands for Type, like Integer or String or your own type) then you don't need to know the size in advance like an array. Also you don't need to keep track of indexes. You can just use the .Add method and the new item is put at the end of the list.
You can get a head start on getting the data out of the file by using File.ReadAllLines which will return an array of lines in the text file. Then you can just .Split each line on the "," (comma) and use the second element of the resulting array. The little c after the comma in double quotes tells the compiler that you mean this a Char which is the datatype that .Split is expecting.
I used a Decimal datatype instead of Double. When working with money it is safer to use to get the answer you expect.
In the second code sample I used an Interpolated sting indicated by the $ preceding the string. Notice that it is very similar to String.Format only the variable is inserted directly in the braces instead of a placeholder. This is available in Visual Studio 2015 and later.
The array method...
Private Sub OPCode()
Dim Lines = IO.File.ReadAllLines("availableDVDs.txt")
Dim Prices(Lines.Count - 1) As Decimal
Dim index As Integer
Dim price As Decimal
For Each line In Lines
Dim SplitOnComma = line.Split(","c)
If Decimal.TryParse(SplitOnComma(1), price) Then
Prices(index) = price
index += 1
Else
MessageBox.Show(String.Format("Price for {0} is not valid.", SplitOnComma(0)))
End If
Next
End Sub
The list method...
Private Sub UsingList()
Dim Lines = IO.File.ReadAllLines("availableDVDs.txt")
Dim Prices As New List(Of Decimal)
Dim price As Decimal
For Each line In Lines
Dim SplitOnComma = line.Split(","c)
If Decimal.TryParse(SplitOnComma(1), price) Then
Prices.Add(price)
Else
MessageBox.Show($"Price for {SplitOnComma(0)} is not valid.")
End If
Next
End Sub
With Option Infer Off
Private Sub OPCode()
Dim Lines() As String = IO.File.ReadAllLines("availableDVDs.txt")
Dim Prices(Lines.Count - 1) As Decimal
Dim index As Integer
Dim price As Decimal
For Each line In Lines
Dim SplitOnComma() As String = line.Split(","c)
If Decimal.TryParse(SplitOnComma(1), price) Then
Prices(index) = price
index += 1
Else
MessageBox.Show(String.Format("Price for {0} is not valid.", SplitOnComma(0)))
End If
Next
End Sub
I have multiple text files with similar data, for instance file1 would have the following entry:
test1, 1400
Then file2 would have:
test1, 2400
As all of these files are generated by different programs, is it possible to check through each text file for a similar entry, for instance using the files mentioned above, say I wanted to find test1 from both files and calculate the sum of the score and thus get the following data saved to another text file:
test1, 3800
The Programming Language I am using is VB.NET, currently I have read all of the files using:
Dim Array1() As String = IO.File.ReadAllLines("path")
My current logic is to get all of the data into a list or a KeyValuePair, where the list will store the username of the user as well with their score which would be summed at this point. I have currently read all of the data from each text file to an array, with each array in the FormLoad Event I have got it into a form where the data is split with a delimiter with the comma. At the start of the program I have an Input Box which asks the user for their Username and stores it in a variable called UserInput. From there this is what I need help achieving, I need the Program to get value from each array and store it in another array where it sorts the data of each user with their scores, from their I can use: For i = 0 to ar.length - 1 Loop to go through the array and search for the Users username.
You can use the following approach
Dim arr1 As New List(Of String)
arr1.AddRange(IO.File.ReadAllLines("text file 1"))
Dim arr2 As New List(Of String)
arr2.AddRange(IO.File.ReadAllLines("text file 2"))
Dim searchstring As String = "test1"
'You can replace test1 with the string you are searching the text file for
Dim index1 As Integer = 0
Dim index2 As Integer = 0
'Getting the index of the string in the list
'*******************************************
For x As Integer = 0 To arr1.Items.Count - 1
If arr1(x).StartsWith(searchstring) Then
index1 = x
End If
Next
For x As Integer = 0 To arr2.Items.Count - 1
If arr2(x).StartsWith(searchstring) Then
index2 = x
End If
Next
'*******************************************
Dim split1() As String = Split(arr1(index1), ",")
Dim split2() As String = Split(arr2(index2), ",")
Dim sum As Integer = Integer.Parse(Trim(split1(1))) + Integer.Parse(Trim(split2(1)))
'Writing the sum to another test file, the "output.txt" file would be created on your desktop, you can replace the path's string with your custom location
Dim path As String = Path.Combine(My.Computer.FileSystem.SpecialDirectories.Desktop, "output.txt")
Dim finaltext As String = searchstring + "," + sum.ToString
System.IO.File.AppendAllLines(path, finaltext)
The above method creates a new text file "output.txt" on your desktop.
AJD is correct. You need to make an attempt before posting. I answered because I want practice with Linq. Since you have 2 different types of data, a class or a structure is in order (or use a database). I filled a list of the structure by splitting the lines into the string portion and integer portion; setting the properties of the structure. You can add as many files as you wish to the List. I tested with both the Linq method and the Loop method.
Structure TestData
Public TestName As String
Public TestScore As Integer
End Structure
Private TestList As New List(Of TestData)
Private Sub AddToList(path As String)
Dim arr() As String = File.ReadAllLines(path)
For Each line As String In arr
Dim arr2() As String = line.Split(","c)
Dim td As TestData
td.TestName = arr2(0)
td.TestScore = CInt(arr2(1).Trim)
TestList.Add(td)
Next
End Sub
Private Function GetSummWithLinq(NameOfTest As String) As Integer
Dim result As Integer = (From Score In TestList
Where Score.TestName = NameOfTest
Select Score.TestScore).Sum
Return result
End Function
Private Function GetSumWithLoop(NameOfTest As String) As Integer
Dim total As Integer
For Each item In TestList
If item.TestName = NameOfTest Then
total += item.TestScore
End If
Next
Return total
End Function
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim p As String = "C:\Users\SomeUser\Desktop\TestData.txt"
AddToList(p)
Dim a As Integer = GetSummWithLinq("test1")
MessageBox.Show($"The Linq method produces {a}")
Dim b As Integer = GetSumWithLoop("test1")
MessageBox.Show($"The Loop method produces {b}")
End Sub
EDIT
My TestData.txt file that I used to test the code.
test1, 314
test2, 740
test1, 700
test2, 200
I'm struggling to solve a small bit of code. What the code does is to first load a CSV file, line by line (starting by line 3), and add it to an array. Then run a regex match and I want to insert the value in an array.
This is my working code, it shows a msgbox with the actual matches:
Dim file = "C:\Users\David\Desktop\mycsv.csv"
Dim basestatisticspath = Path.GetDirectoryName(file)
Dim statistics() As String = IO.File.ReadAllLines(file)
'Dim x As Integer = statistics.Length
'ReDim Preserve statistics(x)
Dim regexlang As Regex = New Regex("(?<=^"")\[.*\]")
Dim regexlinefilename As Regex = New Regex("(?<=^""\[.*?\]\s).*(?="")")
Dim linefilename As Match = Nothing
Dim langmatch As Match = Nothing
Dim filename() As String
Dim lang() As String
For i = 2 To UBound(statistics)
langmatch = regexlang.Match(statistics(i))
linefilename = regexlinefilename.Match(statistics(i))
MsgBox(langmatch.Value & linefilename.Value)
Next
That works well and the actual matches is what I want. So my next step was to add each match to an array to then use it to generate other files.
Therefore I ended up with this:
Dim file = "C:\Users\David\Desktop\myscv.csv"
Dim basestatisticspath = Path.GetDirectoryName(file)
Dim statistics() As String = IO.File.ReadAllLines(file)
'Dim x As Integer = statistics.Length
'ReDim Preserve statistics(x)
Dim regexlang As Regex = New Regex("(?<=^"")\[.*\]")
Dim regexlinefilename As Regex = New Regex("(?<=^""\[.*?\]\s).*(?="")")
Dim linefilename As Match = Nothing
Dim langmatch As Match = Nothing
Dim filename() As String
Dim lang() As String
' Set all value line by line
For i = 2 To UBound(statistics)
langmatch = regexlang.Match(statistics(i))
linefilename = regexlinefilename.Match(statistics(i))
lang(i) = langmatch.Value.ToString
filename(i) = linefilename.Value.ToString
MsgBox(langmatch.Value & linefilename.Value)
Next
After adding the below the program crashes on that line
lang(i) = langmatch.Value.ToString
filename(i) = linefilename.Value.ToString
I am assuming you can add the value of a regex match to a certain position of a string, but it seems I am wrong.
I´ve been searching for an answer with no results (at least to my poor understanding).
How could I convert each of the matches to a string and add it to the i position of the array?
Thanks in advance!
UPDATE:
As #Tval explained, I solved it by including the size of the array when declaring it. Thanks!
Dim filename(UBound(statistics)) As String
Dim lang(UBound(statistics)) As String
you need to initialize the array before you can reference it or you'll get a null reference error, also you can't reference an index that doesn't exist yet or you'll get an index out of range exception.
right now your using an array with a fixed length, so if you want to add a value to it you'll have to re-declare it one index larger every time.
If you want an array of a variable length id suggest using a list, so you can just append values to it without any issues
Dim myList = New List(Of String)
For Each foo As String In bar
myList.Add(bar)
Next
I'm pretty new to visual basic, but I'm having trouble assigning cell values to members of an array. Basically what I am doing is looping through a column and assigning each cell to a new part of the array. Test code is posted below:
Sub Test()
Dim List(5) As String
Dim celltext As String
For i = 1 To 5
celltxt = ActiveSheet.Range("K" & i).Text
List(i) = celltext
MsgBox List(i)
Next i
End Sub
Each time the message box pops up though, it is blank, meaning that the assignment didn't work. The cells at those coordinates DO have values. Any clues?
You are assigning to "celltxt" but reading from "celltext".
Add Option Explicit at the top of every module -- that will make these types of errors more obvious.
When you Dim List(5) As String. The lowest element in the array is 0 and not 1. You might want to change that to Dim List(1 to 5) As String else your first element will always be blank in the array.
You are using ActiveSheet. Are you sure it is the right sheet?
Try this code
Sub Test()
Dim List(1 To 5) As String
Dim ws As Worksheet
Dim i as Long
Set ws = ThisWorkbook.Sheets("Sheet1")
For i = 1 To 5
List(i) = ws.Range("K" & i).Value
MsgBox List(i)
Next i
End Sub
You might also with to try:
Dim List As Variant
Dim i As Long
List = ActiveSheet.Range("K1:K5")
For i = 1 To UBound(List)
MsgBox List(i, 1)
Next i
This will add performance by only reading from the worksheet once instead of each time the loop is looped.