Regex expression and match function in text file - arrays

I have problem with my matching function actually I have to count number of lines with specific string and return line number ,so I have one dimensional array of string that contain the unique strings of text file {33,7,77,3 23,6} and text file with the same strings in array I have read lines of text file to array , but with duplicate of these strings ,when I use regex.match it works not bad expect when I check if line 2 contain 3 the function return True it's consider 3 in 23 as 3 , and the above explanation is just example of what I need any help please
Module Module1
Sub Main()
Dim txt As String = File.ReadAllText("e:\ii.txt")
' Use regular expressions to replace characters
' that are not letters or numbers with spaces.
Dim reg_exp As New Regex("[^a-zA-Z0-9]")
txt = reg_exp.Replace(txt, " ")
' Split the text into words.
'Dim words() As String = txt.Split( _
' New Char() {" "c}, _
' StringSplitOptions.RemoveEmptyEntries)
Dim words = txt.Split(New String() {" ", Environment.NewLine}, StringSplitOptions.RemoveEmptyEntries)
' Use LINQ to get the unique words.
Dim word_query = _
(From word As String In words _
Order By word _
Select word).Distinct()
Dim stra() As String = word_query.ToArray()
For i = 0 To stra.Length - 1
Console.WriteLine(" " & stra(i))
Next
Dim lines() As String = IO.File.ReadAllLines("e:\ii.txt")
For i = 0 To lines.Length - 1
Console.WriteLine(lines(1))
Dim linecount = 0
Dim regex As New Regex(stra(i), RegexOptions.ExplicitCapture)
Dim match As Match = regex.Match(lines(1))
If match.Success Then
linecount += 1
Console.WriteLine("linecount= " & linecount)
Else
Console.WriteLine("false")
End If
Next
End Sub
End Module

You many not have to split the text into words. Is your word list very long? From what I understand you want the following:
1.Read a text file and return the line number for a given word or phrase.
Is the word or phrase complex? If not, why not use a the Contains extension method?
For example:
Dim myString = "Hello World"
If myString.Contains("World") Then
'Add line number to line count.
End if
If you are using this as an opportunity to learn regular expressions, I highly recommend "Mastering Regular Expressions" by Jeffrey Friedl. When I first begun I invested in a program RegexBuddy, which is worth the money. But now there are so many online regex testers now, that could be an alternative for something free.

Enhance your regex with anchors. These will ascertain that the whole test string matches instead of a substring. The following code also assembles all match patterns of interest into a single regex pattern which will be used against each line of the target file:
Dim strall As String
strall = ""
For i = 0 To stra.Length - 1
If i > o Then
strall = strall & "|"
End If
strall = strall & stra(i)
Console.WriteLine(" " & stra(i))
Next
strall = "^(" & strall & ")$"
Dim regexall As New Regex(strall, RegexOptions.ExplicitCapture)
'...
Dim linecount = 0
Dim match As Match = regexall.Match(lines(i)) '... was 'lines(1)', probably a typo
If match.Success Then
'...

this code is working with me thanks for all
Public Function countlines(ByVal st As String) As Integer
Dim count As Integer
Dim linecount As Integer = 0
Dim substrings() As String = Regex.Split(st, " ")
Dim stt() As String = {23, 7, 3}
For i = 0 To stt.Length - 1
'For j = 0 To substrings.Length - 1
'Console.WriteLine(substrings(0))
'For i = 0 To substrings.Length - 1
'Console.Write(substrings(i))
Dim matchQuery = From word In substrings Where word.ToLowerInvariant() = stt(i).ToLowerInvariant() Select word
' ' Count the matches.
count = matchQuery.Count()
Console.WriteLine("count=" & count)
If count > 0 Then
linecount += 1
Else
Console.WriteLine(" linecount=" & linecount)
End If
Next
Console.WriteLine("linecount= " & linecount)
Return linecount
End Function
Sub Main()
Dim lines() As String = IO.File.ReadAllLines("e:\ii.txt")
For Each line As String In lines
countlines(line)
Next
End Sub

Related

Using VBA to read a .csv string into a multidimensional array

I'm trying to automate the import of data into a tool I'm building in Excel. The idea is to read the data from a .csv file either directly into an array, or read the data as a string and then parse it using spaces " " and commas "," as delimiters, followed by an array. I've gotten this far:
Public Sub ImportData()
Dim myData as String, strData() as String
Dim thisFile as String
thisFile = ActiveWorkbook.Path & "\" & "s.csv"
Open thisFile For Binary As #1
myData = Space$(LOF(1))
Get #1, , myData
Close #1
End Sub
This gets me to where "myData" is a now string of data separated by commas and spaces (commas delimiting for a new column, spaces delimiting for a new row).
How do I proceed to reconstruct this as a multidimensional (2D) array so that it can be printed onto the sheet I'm working on, or referenced straight from memory? Or is there an easier way?
This is the implementation suggested by #Tim
Option Explicit
Public Sub OpenFile()
Dim rawData As String, lineArr As Variant, cellArr As Variant
Dim ubR As Long, ubC As Long, r As Long, c As Long
Open ActiveWorkbook.Path & "\" & "s.csv" For Binary As #1
rawData = Space$(LOF(1))
Get #1, , rawData
Close #1
If Len(rawData) > 0 Then
'If spaces are delimiters for lines change vbCrLf to " "
lineArr = Split(Trim$(rawData), vbCrLf)
ubR = UBound(lineArr) + 1
ubC = UBound(Split(lineArr(0), ",")) + 1
ReDim arr(1 To ubR, 1 To ubC)
For r = 1 To ubR
If Len(lineArr(r - 1)) > 0 Then
cellArr = Split(lineArr(r - 1), ",")
For c = 1 To ubC
arr(r, c) = cellArr(c - 1)
Next
End If
Next
ActiveSheet.Range(Cells(1), Cells(ubR, ubC)) = arr 'Place array on the sheet
End If
End Sub

VBA - How to build an array with multiple delimiters of varying sizes?

How can I build an array if I have multiple delimiters, where some delimiters are single character and others are multiple characters?
Sub Example()
Dim exString As String
Dim myString() As String
exString = "A,B C;D > E"
myString() = Split(exString, "," & " " & ";" & " > ")
End Sub
The result I want in my array is:
myString(0) is A
myString(1) is B
myString(2) is C
myString(3) is D
myString(4) is E
But using Split() in this way doesn't work. I do know that I can use Replace() to replace every single delimiter with a common one, but I have a lot of different delimiters and variations of multiple character delimiters. Using Replace() isn't desirable to me. What can I do?
You can have lots of problems in VBA as well:
'Add a reference to Microsoft VBScript Regular Expressions 5.5 (Tools -> References...)
Dim exString As String
exString = "A,B C;D > E"
Dim re As New RegExp
re.Pattern = "(,| |;|>)+"
re.Global = True
Dim myString() As String
myString = Split(re.Replace("A,B C;D > E", ","), ",")
Setting re.Pattern defines what to look for. | represents finding A or B, so the regular expression will match on , or or ; or >.
Multiple instances should be treated as one (e.g. between the D and the E there are three characters, but there should be only one split), so add a + at the end (and wrap everything else in ()).
Replace then replaces any of the matched patterns with , and gives back a string like this:
A,B,C,D,E
on which we can simply call Split to get back the array.
Reference: VBScript Regular Expressions
Instead of using regular expressions to match the delimiter characters, you could use regexes to match the non-delimiter characters:
Dim re As New RegExp
re.Pattern = "[^, ;>]+" 'The ^ unmatches any characters within the []
re.Global = True
Dim match As Match
For Each match In re.Execute(exString)
'do something with each result here
Debug.Print match.Value
Next
This is sufficient if all you need is to iterate over the results and do something with them. If you specifically need an array with the results:
Dim re As New RegExp
re.Pattern = "[^, ;>]+"
re.Global = True
Dim matches As MatchCollection
Set matches = re.Execute(exString)
ReDim myString(matches.Count) As String
Dim i As Integer
For i = 0 To matches.Count - 1
myString(i) = matches(i).Value
Next
You were on the right track with your function. Using a ParamArray you can easily change the number and position of your delimiters.
Code
Function MultiSplit(SourceText As String, ParamArray Delimiters()) As String()
Dim v As Variant
For Each v In Delimiters
SourceText = Replace(SourceText, v, "•")
Next
MultiSplit = Split(SourceText, "•")
End Function
Test
Sub Test()
Const example As String = "A,B C;D > E"
Dim a1, a2, a3, Incorrect
Incorrect = MultiSplit(example, " ", " > ")
a1 = MultiSplit(example, " > ", ",", ";", " ")
a2 = MultiSplit(example, " > ", ",")
a3 = MultiSplit(example, " > ")
End Sub
Result
NOTE: When using multi-character delimiters, the order that the delimiters are processed matters. Notice that A1 is split proper but Incorrect is not split as intended because the space delimiter came before " > ".
In this situation, I found the following function to be perfect for my needs:
Function MultiSplit(SourceText As String, Optional SingleCharDelimiter As String, Optional MultiCharDelimiter As String, _
Optional Separator As String) As String()
'Created by Tyeler for use by all.
'SourceText is your input string.
'SingleCharDelimiter is a string of desired delimiters.
'SingleCharDelimiter format is a string fully concatenated with no character separation.
' (ex. "-.;:, " MultiSplit will use those 6 characters as delimiters)
'SingleCharDelimiter's will remove blanks from the array in the event two single delimiters
' are next to each other.
'MultiCharDelimiter is a string of specific multi-character delimiters.
'MultiCharDelimiters can be separated by the optional Separator
'Separator is an optional value used to separate multiple MultiCharDelimiters.
' (ex. MultiCharDelimiter = "A A,B B,C C" // Separator = "," // This will make the function
' delimit a string by "A A", "B B", and "C C")
'MultiSplit will make an array based on any delimiter (Including delimiters with
' multiple characters).
If MultiCharDelimiter = "" And SingleCharDelimiter = "" Then Exit Function
Dim i As Integer, n As Integer, dlimit
Dim delColl As New Collection
Dim newString As String: newString = SourceText
Dim delArr() As String, strgArr() As String, delFull() As String
Dim delSep As String, a As Integer: a = 33
Do While InStr(SingleCharDelimiter, Chr(a)) <> 0 Or InStr(MultiCharDelimiter, Chr(a)) <> 0 _
Or InStr(Separator, Chr(a)) <> 0 Or InStr(SourceString, Chr(a)) <> 0 'Find intermediate delimiter
a = a + 1
Loop
delSep = Chr(a)
If MultiCharDelimiter <> "" Then
If Separator <> "" Then 'If there's no delimiter for the delimiter array, assume MultiCharDelimiter is the delimiter
delArr() = Split(MultiCharDelimiter, Separator)
For i = 0 To UBound(delArr)
If InStr(newString, delArr(i)) <> 0 Then newString = Replace(newString, delArr(i), delSep)
Next i
Else
newString = Replace(newString, MultiCharDelimiter, delSep)
End If
End If
Erase delArr
For i = 1 To Len(SingleCharDelimiter) 'Build a collection of user defined delimiters
delColl.Add Mid(SingleCharDelimiter, i, 1)
Next i
For Each dlimit In delColl 'Replace all delimiters in the string with a single common one
newString = Replace(newString, dlimit, delSep)
Next dlimit
strgArr() = Split(newString, delSep)
ReDim delFull(LBound(strgArr) To UBound(strgArr))
n = LBound(strgArr)
For i = LBound(strgArr) To UBound(strgArr) 'Get rid of empty array items
If strgArr(i) <> "" Then
delFull(n) = strgArr(i)
n = n + 1
End If
Next i
n = n - 1
ReDim Preserve delFull(LBound(strgArr) To n)
MultiSplit = delFull 'Send the delimited array
Erase delFull
Erase strgArr
End Function
This function will return an array of values that were separated by user defined delimiters.
To use this function, simply call on it and supply your full string and desired delimiters:
Sub Example1()
Dim exString As String
Dim myString() As String
Dim c, n
exString = "A,B C;D > E"
myString() = MultiSplit(exString, ", ;", " > ")
n = 0
For Each c In myString
Debug.Print "(" & n & ") = " & c
n = n + 1
Next c
End Sub
This will yield the desired result where the array is filled with only ABCDE.
A more complicated example:
Sub Example2()
Dim myString As String, c, n
n = 0
myString = "The,Quickupside-downBrownjelloFox_Jumped[Over] ThegiantLazyjelloDog"
For Each c In MultiSplit(myString, ",_[] ", "upside-down,jello,giant", ",")
Debug.Print "(" & n & ") = " & c
n = n + 1
Next c
End Sub
This will yield the following:
The following is a built-upon version of the code that Thomas Inzina graciously provided.
The following limitations have been removed:
The order that the delimiters are listed in the function.
The temporary delimiter being a set specific character.
The option to include or remove empty array items.
The function changing the reference (ByRef vs ByVal)
Passing an array of delimiters vs listing individual delimiters
Function MultiSplitX(ByVal SourceText As String, RemoveBlankItems As Boolean, ParamArray Delimiters()) As String()
Dim a As Integer, b As Integer, n As Integer
Dim i As Integer: i = 251
Dim u As Variant, v As Variant
Dim tempArr() As String, finalArr() As String, fDelimiters() As String
If InStr(TypeName(Delimiters(0)), "()") <> 0 And LBound(Delimiters) = UBound(Delimiters) Then
ReDim fDelimiters(LBound(Delimiters(0)) To UBound(Delimiters(0))) 'If passing array vs array items then
For a = LBound(Delimiters(0)) To UBound(Delimiters(0)) 'build that array
fDelimiters(a) = Delimiters(0)(a)
Next a
Else
fDelimiters = Delimiters(0)
End If
Do While InStr(SourceText, Chr(i)) <> 0 And i < 251 'Find an unused character
i = i + 1
Loop
If i = 251 Then 'If no unused character in SourceText, use single character delimiter from supplied
For a = LBound(fDelimiters) To UBound(fDelimiters)
If Len(fDelimiters(a)) = 1 Then i = Asc(fDelimiters(a))
Next a
End If
If i = 251 Then 'If no single character delimiters can be used, error.
MsgBox "SourceText uses all character type." & vbCrLf & "Cannot split SourceText into an array.", _
vbCritical, "MultiSplitX Run-Time Error"
Exit Function
End If
Debug.Print i
For a = LBound(fDelimiters) To UBound(fDelimiters) 'Sort Delimiters by length
For b = a + 1 To UBound(fDelimiters)
If Len(fDelimiters(a)) < Len(fDelimiters(b)) Then
u = fDelimiters(b)
fDelimiters(b) = fDelimiters(a)
fDelimiters(a) = u
End If
Next b
Next a
For Each v In fDelimiters 'Replace Delimiters with a common character
SourceText = Replace(SourceText, v, Chr(i))
Next
tempArr() = Split(SourceText, Chr(i)) 'Remove empty array items
If RemoveBlankItems = True Then
ReDim finalArr(LBound(tempArr) To UBound(tempArr))
n = LBound(tempArr)
For i = LBound(tempArr) To UBound(tempArr)
If tempArr(i) <> "" Then
finalArr(n) = tempArr(i)
n = n + 1
End If
Next i
n = n - 1
ReDim Preserve finalArr(LBound(tempArr) To n)
MultiSplitX = finalArr
Else: MultiSplitX = tempArr
End If
End Function
Use of this function doesn't change from how Thomas had it, with the exception that there's an added boolean statement.
Example 1
In this example, RemoveBlankItems has been set to True.
Sub Example1()
Dim myString As String, c, n
n = 0
myString = "The,Quickupside-downBrownjelloFox_Jumped[Over] ThegiantLazyjelloDog"
For Each c In MultiSplitX(myString, True, ",", "-", "upside-down", "jello", " ", "[", "]", "giant", "_")
Debug.Print "(" & n & ") = " & c
n = n + 1
Next c
End Sub
This results in the following output:
Example 2
In this example we have RemoveBlankItems set to False.
Sub Example2()
Dim myString As String, c, n
n = 0
myString = "The,Quickupside-downBrownjelloFox_Jumped[Over] ThegiantLazyjelloDog"
For Each c In MultiSplitX(myString, True, ",", "-", "upside-down", "jello", " ", "[", "]", "giant", "_")
Debug.Print "(" & n & ") = " & c
n = n + 1
Next c
Debug.Print myString
End Sub
This results in the following output:
Example 3
In this example, instead of listing our delimiters in the function, we have them typed out in a string and insert an array in the function instead:
Sub Example3()
Dim myString As String, c, n
Dim myDelimiters As String
n = 0
myString = "The,Quickupside-downBrownjelloFox_Jumped[Over] ThegiantLazyjelloDog"
myDelimiters = ",|-|upside-down|jello| |[|]|giant|_"
For Each c In MultiSplitX(myString, True, Split(myDelimiters, "|"))
Debug.Print "(" & n & ") = " & c
n = n + 1
Next c
Debug.Print myString
End Sub
This has the same result as if they had been listed individually:
The Reason RemoveBlankItems Is Desirable
There are some instances in which you DON'T want to have blanks in your array. An example of this would be if you're using your array as a bank of search words that are cycling through a range on a spread sheet. Another example would be if you're manipulating strings of text based on values in the array.
There are also times when you would want to retain the blanks in the array. As Thomas described, in the event you're using this on a CSV file, where maintaining the spaces as columns is desired. Or you're using it to break apart, for example, HTML coding and wish to retain the line format.
Perhaps:
Sub Example()
Dim exString As String
Dim myString() As String
exString = "A,B C;D > E"
exString = Replace(exString, ",", " ")
exString = Replace(exString, ";", " ")
exString = Replace(exString, ">", " ")
exString = Application.WorksheetFunction.Trim(exString)
myString() = Split(exString, " ")
msg = ""
For Each a In myString
msg = msg & vbCrLf & a
Next a
MsgBox msg
End Sub

vba mapping function behaving unexpectedly

why the function below works sometimes and fails at others?
The function idea
a string gets passed to this function by a user or a procedure
the string will be split by multiple delimiters into an array of words
each word is cleaned from non-letter characters except for the characters (dash and single quote mark inside the word) an example of words having these two char. would be (man's spirit, life-loving)
if the single quote marks are found surrounding the word, they get trimmed too
after processing each word in the string, and if the word is not empty it gets stored into the array Along with it's starting position and end position
the start and end positions refer to the position of that word within the input string and excluding any non-letter characters that might surround the word.
Here's the code
Sub test()
Dim d$: d = ThisDocument.Range.Text
Dim Arr(), i&
Arr = ExtractWordsFromDoc_2(d)
For i = 0 To UBound(Arr)
ThisDocument.Range(Arr(i)(1) - 1, Arr(i)(2)).HighlightColorIndex = wdBrightGreen
Next
End Sub
Function ExtractWordsFromDoc_2(ByRef doc As Document, Optional ByVal Delimiters)
' Take a string, and return it as a one dimensional array of individual arrys, each array
' has three values (single delimited string, start range of delimited str, end range of delimited str)
' the input string is delimited by any of several characters. None of those characters are returned in
' the result. Provide a default list of Delimiters, which Should come from registry.
' But allow override.
'===================================================================================================================
Dim InputString$: InputString = doc.Range.Text
'return an array of empty string when input string is empty
If InputString = "" Then
ExtractWordsFromDoc_2 = Array("", 0, 0)
Exit Function
End If
'===================================================================================================================
Dim DelimitList As Variant, ArrayOfWords() As Variant, TmpArr() As Variant
Dim OneChar$, TempWord$, WordCount&, InputStringLength&, CharIndex&, ArrUbound&
'===================================================================================================================
'if delimiters are missing, We should get these from a Registry
If IsMissing(Delimiters) Then
DelimitList = Chr(34) & Chr(147) & Chr(148) & Chr(32) & "," & "." & vbCr & vbTab & "/" & "!" & "|" & ";" & ")" & "(" & "?"
'Chr(34)= straight double quotes mark
'Chr(147) & Chr(148) =opening and closing double quotes marks
'Chr(32) = space
Else
DelimitList = Delimiters 'user can override if needed
End If
'===================================================================================================================
InputStringLength = Len(InputString) 'get the input string length
For CharIndex = 1 To InputStringLength 'loop through each character
OneChar = VBA.Strings.Mid(InputString, CharIndex, 1) 'Read one character at a time
Select Case InStr(DelimitList, OneChar) 'Test if the character is a delimiter character
Case 0 'it is not a delimiter
TempWord = TempWord & OneChar 'Add the character to the current word
Case Is <> 0, Is = InputStringLength 'it is a delimiter or it is the last character
'if the temp word is not empty and not a quotation mark
If TempWord > "" And Not (TempWord = "'" Or TempWord = Chr(145) Or TempWord = Chr(146)) Then
TmpArr = TrimSingQuotes(TempWord) 'send that word to be cleaned from single quotaion mark
If (Not TmpArr(0) = "") Then 'if the returned word has length, count it
WordCount = WordCount + 1
ArrUbound = WordCount - 1 'set the new upper dimension for the storing array
ReDim Preserve ArrayOfWords(ArrUbound) 'expand storing array when we have a cleaned word with length
'Save new word in the last place inside the array, along with the word start and end ranges
ArrayOfWords(ArrUbound) = Array(TmpArr(0), _
CharIndex - Len(TempWord) + TmpArr(1) - 1, _
CharIndex - Len(TempWord) + TmpArr(2) - 1)
End If
TempWord = "" 'reset the Temp Word
End If
End Select
Next CharIndex
'===================================================================================================================
ExtractWordsFromDoc_2 = ArrayOfWords 'Return the storing array through function name
'do some cleaning
Erase ArrayOfWords
Erase TmpArr
End Function
Sub testTrimSingQuotes()
TrimSingQuotes (Empty)
End Sub
Function TrimSingQuotes(ByVal TempWord$)
'SSQP =starting single quote position
'ESQP = ending single quote position
'==================================================================
If TempWord = "" Then
TrimSingQuotes = Array("", 0, 0)
Exit Function
End If
'==================================================================
Dim SSQP&: SSQP = 1
Dim ESQP&: ESQP = Len(TempWord)
'==================================================================
'trim starting single quotes
Do While (Mid(TempWord, SSQP, 1) = "'" Or Mid(TempWord, SSQP, 1) = Chr(145) Or Mid(TempWord, SSQP, 1) = Chr(146)) And SSQP < ESQP
SSQP = SSQP + 1
Loop
'==================================================================
'trim ending single quotes
Do While (Mid(TempWord, ESQP, 1) = "'" Or Mid(TempWord, ESQP, 1) = Chr(145) Or Mid(TempWord, ESQP, 1) = Chr(146)) And (ESQP > SSQP)
ESQP = ESQP - 1
Loop
'==================================================================
'get the trimmed word
TempWord = Mid(TempWord, SSQP, ESQP - SSQP + 1)
'==================================================================
'test the trimmed word for output
If TempWord > "" And Not (TempWord = "'" Or TempWord = Chr(145) Or TempWord = Chr(146)) Then
TrimSingQuotes = Array(TempWord, SSQP, ESQP)
Else
TrimSingQuotes = Array("", 0, 0)
End If
End Function
To be honest, I didn't spend a lot of time (i.e. none) figuring out why your code isn't working as intended. I suspect it has something to do with calculating your position in the input string.
It is much simpler to leverage the build in Split function to do your heavy lifting, and probably much more performant than relying on the string functions like Instr and Mid. Note that this relies on 2 quirks of the Split function:
First, if you call Split on an empty string, it returns an array with a UBound of -1.
Second, VBA's version of Split doesn't remove empty entries - so, Split("foo", "foo") results in the array { vbNullString, vbNullString }. This is good, because you can tell by the result how many delimiters were in the string based on the size of the resulting array (number of delimiters in the input will always equal the number of array elements minus one. In VBA terms, delimiterCount = UBound(Split(inputString, delimiter)).
Your requirement makes this easy in that your delimiters are all 1 character.
Try something like this:
Private Function MultiSplit(inValue As String, delimiters() As Variant) As Variant()
Dim output() As Variant
Dim bound As Long
ReDim Preserve output(bound)
Dim tokens() As String
Dim index As Long
tokens = Split(inValue, delimiters(0))
If UBound(tokens) = -1 Then
MultiSplit = Array(vbNullString, 0, 0)
Exit Function
End If
'Process each delimiter.
For index = 1 To UBound(delimiters)
tokens = SubSplit(tokens, CStr(delimiters(index)))
Next index
Dim position As Long
For index = LBound(tokens) To UBound(tokens)
If tokens(index) = vbNullString Then
'This means a delimiter was removed, so increment the position to account for it.
position = position + 1
Else
'Resize the output array and write the result for the remaining token.
ReDim Preserve output(bound)
output(bound) = Array(tokens(index), position, position + Len(tokens(index)) - 1)
position = position + Len(tokens(index)) + 1
bound = bound + 1
End If
Next index
MultiSplit = output
End Function
Private Function SubSplit(inValue() As String, delimiter As String) As String()
Dim tokens() As String
Dim substring As Variant
Dim token As Variant
Dim output() As String
output = Split(vbNullString)
For Each substring In inValue
tokens = Split(substring, delimiter)
'Test for an empty token - these need to be preserved in the output.
If UBound(tokens) = -1 Then
ReDim Preserve output(UBound(output) + 1)
Else
For Each token In tokens
ReDim Preserve output(UBound(output) + 1)
output(UBound(output)) = token
Next token
End If
Next substring
SubSplit = output
End Function
Test code:
Private Function TestCode()
Dim delims() As Variant
Dim results() As Variant
Dim test As String
delims = Array(Chr(34), Chr(147), Chr(148), Chr(32), ",", ".", vbCr, vbTab, "/", "!", "|", ";", ")", "(", "?")
test = "foo|||bar,,baz?crux"
results = MultiSplit(test, delims)
Dim result As Variant
For Each result In results
Debug.Print result(0) & vbTab & result(1) & vbTab & result(2)
Next result
End Function
Note that I didn't examine the existing code even far enough to determine if your output positions were 1 or 0 based. The example above is 0 based. If you need 1 based, insert position = 1 after Dim position As Long.
Quote removal is left as an exercise for the reader.

I keep getting and error message 'Index was outside the bounds of the array'

I am trying to display information from a text file into a multiline textbox. I run the code but the system displays an error message 'Index was outside the bounds of the array'. There are no obvious error messages and I can't seem to manipulate the code to get rid of this problem. Take a look:
Public Class TeachCon
Dim layout As String
Dim Contacts(6) As Details
Structure Details
Dim Name As String
Dim Email As String
Dim RoomNum As String
Dim number1, number2 As Integer
End Structure
Sub LoadTeachContacts(ByRef Contacts() As Details)
Dim TextFile As String = "\\Sjcdom01\mstudent\LHeywood\documents\A2\Computing\Comp 4 - Smail\Project\Text Files\Teacher Contact List.txt"
Dim TextLine As String = ""
Dim ArrayCounter As Integer = 0
Dim objReader As New System.IO.StreamReader(TextFile)
'loop through text file and load all contacts
Do While objReader.Peek() <> -1
'read next line from file
TextLine = TextLine & objReader.ReadLine() & vbNewLine
'declare an array and use it to split line from file
Dim TempArray() As String = Split(TextLine, ",")
'transfer each array element into the appropriate part of the contacts stucture
Contacts(ArrayCounter).Name = TempArray(0)
*Contacts(ArrayCounter).Email = TempArray(1)*
Contacts(ArrayCounter).RoomNum = TempArray(2)
Contacts(ArrayCounter).number1 = TempArray(3)
Contacts(ArrayCounter).number2 = TempArray(4)
'empty string before reading next line from file
TextLine = ""
'increment array counter
ArrayCounter = ArrayCounter + 1
Loop
End Sub
Private Sub ButShow_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Dim ArrayCounter As Integer = 0
LoadTeachContacts(Contacts)
Do Until ArrayCounter = 3
layout = Contacts(ArrayCounter).Name & "," & Contacts(ArrayCounter).Email & "," & Contacts(ArrayCounter).RoomNum & "," & Contacts(ArrayCounter).number1 & "," & Contacts(ArrayCounter).number2
If ArrayCounter = 0 Then
TextBox7.Text = layout
End If
ArrayCounter += 1
Loop
End Sub
End Class
The text enclosed by the * is where the system says it is outside the bounds of the array.
Well, one of your lines probably splits into an array that is shorter than you expect, and hence the index does not exist. Check the length of the array before you get the value. Maybe something like this
If TempArray.Length > 0 Then Contacts(ArrayCounter).Name = TempArray(0)
If TempArray.Length > 1 Then Contacts(ArrayCounter).Email = TempArray(1)
If TempArray.Length > 2 Then Contacts(ArrayCounter).RoomNum = TempArray(2)
If TempArray.Length > 3 Then Contacts(ArrayCounter).number1 = TempArray(3)
If TempArray.Length > 4 Then Contacts(ArrayCounter).number2 = TempArray(4)
Don't know exactly what your TextFile contains in it. But inorder to handle the exception change the code as below
'declare an array and use it to split line from file
Dim TempArray() As String = Split(TextLine, ",")
'transfer each array element into the appropriate part of the contacts stucture
If TempArray.Length > 0 Then
Contacts(ArrayCounter).Name = TempArray(0)
*Contacts(ArrayCounter).Email = TempArray(1)*
Contacts(ArrayCounter).RoomNum = TempArray(2)
Contacts(ArrayCounter).number1 = TempArray(3)
Contacts(ArrayCounter).number2 = TempArray(4)
End If
'empty string before reading next line from file
TextLine = ""
It would be helpful if you could give the content of the file also:
"\Sjcdom01\mstudent\LHeywood\documents\A2\Computing\Comp 4 - Smail\Project\Text Files\Teacher Contact List.txt"
I think that you should check if the line is empty or not, because the item 0 will be available without error as a Null String, but the item 1 will throw 'Index was outside the bounds of the array' In LoadTeachContacts Sub
'read next line from file
If objReader.ReadLine().Trim = "" Then Continue Do
TextLine = TextLine & objReader.ReadLine() & vbNewLine

Vbscript: Convert text string in small pieces and put it into a array

I need to break a long text string into smaller pieces approximately once every 500 characters (not a special character), forming an array of all the sentences and then put them together separated by a specific character (eg / /). Something as follows:
"This text is a very very large text."
So, I get:
arrTxt(0) = "This is"
arrTxt(1) = "a very"
arrTxt(2) = "very large text"
...
And finally:
response.write arrTxt(0) & "//" & arrTxt(1) & "//" & arrTxt(2)...
Due to my limited knowledge of classic asp, the closest I came to a desired result was the following:
length = 200
strText = "This text is a very very large."
lines = ((Len (input) / length) - 1)
For i = 0 To (Len (lines) - 1)
txt = Left (input, (i * length)) & "/ /"
response.write txt
Next
However, this returns a repeated and overlapping text string: "this is / / this is a / / this is a text //...
Any idea with vbscript? Thank you!
Without using an array, you can just build the string as you go
Const LIMIT = 500
Const DELIMITER = "//"
' your input string - String() creates a new string by repeating the second parameter by the given
' number of times
dim INSTRING: INSTRING = String(500, "a") & String(500, "b") & String(500, "c")
dim current: current = Empty
dim rmainder: rmainder = INSTRING
dim output: output = Empty
' loop while there's still a remaining string
do while len(rmainder) <> 0
' get the next 500 characters
current = left(rmainder, LIMIT)
' remove this 500 characters from the remainder, creating a new remainder
rmainder = right(rmainder, len(rmainder) - len(current))
' build the output string
output = output & current & DELIMITER
loop
' remove the lastmost delimiter
output = left(output, len(output) - len(DELIMITER))
' output to page
Response.Write output
If you really need an array, you can then split(output, DELIMITER)
Here is a try:
Dim strText as String
Dim strTemp as String
Dim arrText()
Dim iSize as Integer
Dim i as Integer
strText = "This text is a very very large."
iSize = Len(stText) / 500
ReDim arrText(iSize)
strTemp = strText
For i from 0 to iSize - 1
arrText(i) = Left(strTemp, 500)
strTemp = Mid(strTemp, 501)
Next i
WScript.Echo Join(strTemp, "//")

Resources