Read a file from text and create loop - vb.net

I have a text file with some line example
I want to loop through each line until an create format line +1 number all words And of course, a max value must be adjustable
Like this
thanks for all the help
My code
Sub homework()
' Dim words(5) As String
Dim words As String() = File.ReadLines("test.txt")
Dim i As Integer
Dim outerLoop As Integer
Dim innerLoop As Integer
For i = 0 To words.Length ' i dont know how to set file line length
words(i) = words(i) & i + 1
Next i
For outerLoop = 0 To UBound(words)
For innerLoop = 0 To UBound(words)
If outerLoop = innerLoop Then
ListBox1.Items.Add(words(outerLoop) & "-" & words(innerLoop))
End If
Next
Next outerLoop
End Sub
after output
The problem here doesn't read all the lines in my text file, it's only processing last line.

File.ReadLines returns and IEnumerable of String whereas File.ReadAllLines returns a good old Array of String. They play by slightly different rules. Right now you will probably be more comfortable with an array.
Using a For Each loop for the outer loop is a bit easier because you don't have to worry about Index out or Range or getting UBound(words) which translates to words.GetUpperBound(0) in .net.
For the inner loop we can start with 1 and go to the value passed to you method.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
homework(3)
End Sub
Sub homework(UpperLimit As Integer)
Dim words = File.ReadAllLines("C:\Users\***\Desktop\test.txt")
For Each word In words
For i = 1 To UpperLimit
ListBox1.Items.Add(word & i & "-" & word & i)
Next
Next
End Sub

The First loop is not required and modify the second loop like below:
Sub homework()
' Dim words(5) As String
Dim words As String() = File.ReadLines("test.txt")
Dim i As Integer
Dim outerLoop As Integer
Dim innerLoop As Integer
' This Loop is not required.
'For i = 0 To words.Length
' words(i) = words(i) & i + 1
'Next i
For outerLoop = 0 To UBound(words)
For innerLoop = 1 To MaxValue
Dim str as string
str = words(outerloop) & "-" & innerLoop
ListBox1.Items.Add(str & "-" & str)
Next
Next outerLoop
End Sub

Related

How can I concatenate endnotes in a Word doc paragraph?

I have a *.docx file with more than 4000 endnotes. My task is to combine endnotes inside every paragraph (where there is 3 and more endnotes) to one big endnote.
For example.
Input:
word word{1} word{2} word word{3} word.
Endnotes:
{1} endnote
{2} endnote
{3} endnote
Output:
word word word word word word{1}.
Endnotes:
{1} endnote; endnote; endnote
So I'll have one big endnote instead of several small ones.
What I have tried:
Sub Macro1()
Dim i As Integer
Dim t As String
Dim tmp As String
tmp = ""
For i = 1 To Selection.Endnotes.Count Step 1
t = Selection.Endnotes(i).Range.Text
If tmp = "" Then
tmp = Selection.Endnotes(i).Range.Text
Else
tmp = tmp & "; " & Selection.Endnotes(i).Range.Text
End If
Next i
For i = Selection.Endnotes.Count To 1 Step -1
Selection.Endnotes(i).Delete
Next i
Selection.Expand wdParagraph
ActiveDocument.Endnotes.Add Range:=Selection.Range, Text:=tmp
End Sub
It works but a user must select proper paragraph by hand. What I don't know is how to do this process automatically - find bad paragraphs with more than 3 endnotes and apply the code above to these paragraphs. ActiveDocument.Paragraphs item don't have Endnotes property.
Please help)
So the decision is:
Sub Macro1()
Dim i As Integer
Dim t As String
Dim tmp As String
Dim p As Paragraph
For Each p In ActiveDocument.Paragraphs
If p.Range.Endnotes.Count > 3 Then
tmp = ""
For i = 1 To p.Range.Endnotes.Count Step 1
t = p.Range.Endnotes(i).Range.Text
If tmp = "" Then
tmp = t
Else
tmp = tmp & "; " & t
End If
Next i
For i = p.Range.Endnotes.Count To 1 Step -1
p.Range.Endnotes(i).Delete
Next i
ActiveDocument.Endnotes.Add Range:=p.Range, Text:=tmp
End If
Next p
End Sub

How to count text file string length and perform the check in VBA

In a text file I have number of lines, and each line is a string. I need to run a check for each line/string until it finds one that is longer than 15 characters. When it finds one it should show a MsgBox and end the loop. As understand I need to use a Do until EOF loop, but can't make check to work.
Sub OpenFileAsText()
Dim FilePath As String
FilePath = "C:\Users\Default\Desktop\test.csv"
Open FilePath For Input As #1
row_number = 0
Loop Until EOF(1)
Line Input #1, LineFromFile
'cant work out the code to do the check
row_number = row_number + 1
Loop
Close #1
End Sub
Thank You for head start. This code does what I need.
Sub Sample()
Dim filename As String
filename = "C:\Users\Default\Desktop\339734.csv"
Dim file As Integer
file = FreeFile
Open filename For Input As #file
Dim rowNumber As Long
rowNumber = 0
Dim match As String
Do Until EOF(file)
rowNumber = rowNumber + 1
Dim line As String
Line Input #file, line
If Len(line) > 15 Then
match = line
Exit Do
End If
Loop
Close #file
If match <> vbNullString Then
MsgBox "Found"
Else
MsgBox "Did not find"
End If
End Sub
#Edvardas:
If you are interested in being informed about all lines that are too long, you can use this:
Sub Sample()
Const MAX_LINE_LENGTH As Integer = 15
Dim filename As String
filename = "C:\Users\Default\Desktop\339734.csv"
Dim file As Integer
file = FreeFile
Open filename For Input As #file
Dim lineNumber As Long
lineNumber = 0
Dim matchingLines As String
Do Until EOF(file)
lineNumber = lineNumber + 1
Dim line As String
Line Input #file, line
If Len(line) > MAX_LINE_LENGTH Then
' Concatenate every found line number to a string
matchingLines = matchingLines & CStr(lineNumber) & ", "
End If
Loop
Close #file
' Check if any line has been found
If Len(matchingLines) > 0 Then
' Remove the last ", ".
matchingLines = Left(matchingLines, Len(matchingLines) - 2)
MsgBox "Found those lines: " & matchingLines
Else
MsgBox "Did not find any"
End If
End Sub
How About this?
Sub Sample()
Const SEARCH_STRING As String = "SearchThis"
Dim filename As String
filename = "C:\Users\Default\Desktop\test.csv"
Dim file As Integer
file = FreeFile
Open filename For Input As #file
Dim rowNumber As Long
rowNumber = 0
Dim match As String
Do Until EOF(file)
rowNumber = rowNumber + 1
Dim line As String
Line Input #file, line
If InStr(line, SEARCH_STRING) > 0 Then
match = line
Exit Do
End If
Loop
Close #file
If match <> vbNullString Then
MsgBox "Found '" & SEARCH_STRING & "' in line #" & rowNumber & ": " & match, vbInformation, "Result"
Else
MsgBox "Did not find '" & SEARCH_STRING & "'", vbInformation, "Result"
End If
End Sub
Explanation:
In the top of the procedure I defined a constant SEARCH_STRING with the string you may want to search for in the file.
Then in the Do Until loop If InStr(line, SEARCH_STRING) > 0 checks if the read line contains the searched string.
Instr returns the position of a substring in a string. If it is not found it returns 0.
If the string has been found, it is stored in the string variable match and the loop is exited by Exit Do
Afterwards match will be checked, if it contains a value, and regarding to this some information will be posted by a message box.

locate exact word in excel VBA

I have more than one text with the word "123" inside Textabc
like a123b , c123erf and 123
but I just wanna locate the exact word "123"
Text_u1 = Mid(Textabc, InStr(Text, "123"))
I tried &123& but not working
Thanks
Option Explicit
Sub GetWord()
Dim Textabc As String, s As Variant, i As Variant, abc As String, sz As Long
Dim foundStart As Long, foundLen As Long
Textabc = "like a123b , c123erf and 123"
abc = "123"
s = Split(Textabc)
For i = 0 To UBound(s)
sz = sz + Len(s(i)) + 1
If Trim(s(i)) = abc Then
foundStart = sz - Len(s(i))
foundLen = Len(Textabc) - (sz - Len(s(i))) + 1
Debug.Print "Textabc length: " & Len(Textabc)
Debug.Print "foundStart: " & foundStart
Debug.Print "foundLen: " & foundLen
Debug.Print Mid(Textabc, foundStart, foundLen)
End If
Next
End Sub
Try one of these two, depending on what you want:
Public Sub TestMe()
Debug.Print InStr("a123b", "123")
Debug.Print Mid("a123b", InStr("a123b", "123"))
End Sub
You can try using Regular Expressions
Sub Test()
Dim regEx As Object
Dim str As String
Set regEx = CreateObject("vbscript.RegExp")
str = "a123b , c123erf and 123"
With regEx
.Global = True
.IgnoreCase = True
.Pattern = "\b(123)"
Debug.Print regEx.Execute(str)(0).FirstIndex + 1
End With
End Sub
This will return the position of the first match it finds that is equal to just 123 everything else will be ignored. If there are more then one match you will need to loop over the output of regEx.Execute(str) to get each position

Highlighting word excel

I am writing a VBA program that will allow me to mine through a set of Excel data and pull out relevant information which is then copied to another sheet.
I keep trying to make it so that the word that is being searched for is highlighted in yellow, however my program constantly throws "Compile error - expected array on Ubound".
Option Compare Text
Public Sub Textchecker()
'
' Textchecker
'
' Keyboard Shortcut: Ctrl+h
'
Dim Continue As Long
Dim findWhat As String
Dim LastLine As Long
Dim toCopy As Boolean
Dim cell As Range
Dim item As Long
Dim j As Long
Dim sheetIndex As Long
Dim inclusion As String
sheetIndex = 2
Continue = vbYes
Do While Continue = vbYes
findWhat = CStr(InputBox("What word would you like to search for today?"))
inclusion = CStr(InputBox("Do you have any inclusions? Separate words with commas"))
LastLine = ActiveSheet.UsedRange.Rows.Count
If findWhat = "" Then Exit Sub
j = 1
For item = 1 To LastLine
If UBound(inclusion) >= 0 Then
For Each cell In Range("BY1").Offset(item - 1, 0) Then
For Each item In inclusion
If InStr(cell.Text, findWhat) <> 0 And InStr(cell.Text, inclusion) <> 0 Then
findWhat.Interior.Color = 6
toCopy = True
Else
For Each cell In Range("BY1").Offset(item - 1, 0) Then
If InStr(cell.Text, findWhat) <> 0 Then
findWhat.Interior.Color = 6
toCopy = True
End If
Next item
End If
Next
If toCopy = True Then
Sheets(sheetIndex).Name = UCase(findWhat) + "+" + LCase(inclusion)
Rows(item).Copy Destination:=Sheets(sheetIndex).Rows(j)
j = j + 1
End If
toCopy = False
Next item
sheetIndex = sheetIndex + 1
Continue = MsgBox(((j - 1) & " results were copied, do you have more keywords to enter?"), vbYesNo + vbQuestion)
Loop
End Sub
What am I doing wrong here?
In your code, inclusion is declared as a String variable, and contains a String, albeit a String separated by commas. The Ubound function works on arrays.
To fix: Convert the string into an array using the Split function. See the below example for some quick help, and let us know if you need more details.
Sub Tests()
Dim inclusion() As String
inclusion = Split("One, Two, Three", ",")
MsgBox (UBound(inclusion))
End Sub
To answer your last comment.
A variable in For Each must be of type Object or Variant.
To change your 'item' in a Variant, replace 'Dim item As Long' by 'Dim item As Variant', or even by 'Dim item' as a variable declared without a type is a Variant.

Load csv file into a VBA array rather than Excel Sheet

I am currently able to enter csv file data into Excel VBA by uploading the data via the code below then handling the table, surely not the best way as I am only interested in some of the data and delete the sheet after using the data:
Sub CSV_Import()
Dim ws As Worksheet, strFile As String
Set ws = ActiveSheet 'set to current worksheet name
strFile = Application.GetOpenFilename("Text Files (*.csv),*.csv", ,"Please select text file...")
With ws.QueryTables.Add(Connection:="TEXT;" & strFile, Destination:=ws.Range("A1"))
.TextFileParseType = xlDelimited
.TextFileCommaDelimiter = True
.Refresh
End With
End Sub
Is it possible to simply load the csv into a two dimensional variant array in VBA rather than going through the use of an excel worksheet?
Okay, looks like you need two things: stream the data from the file, and populate a 2-D array.
I have a 'Join2d' and a 'Split2d' function lying around (I recall posting them in another reply on StackOverflow a while ago). Do look at the comments in the code, there are things you might need to know about efficient string-handling if you're handling large files.
However, it's not a complicated function to use: just paste the code if you're in a hurry.
Streaming the file is simple BUT we're making assumptions about the file format: are the lines in the file delimited by Carriage-Return characters or the Carriage-Return-and-Linefeed character pair? I'm assuming 'CR' rather than CRLF, but you need to check that.
Another assumption about the format is that numeric data will appear as-is, and string or character data will be encapsulated in quote marks. This should be true, but often isn't... And stripping out the quote marks adds a lot of processing - lots of allocating and deallocating strings - which you really don't want to be doing in a large array. I've short-cut the obvious cell-by-cell find-and-replace, but it's still an issue on large files.
If your file has commas embedded in the string values, this code won't work: and don't try to code up a parser that picks out the encapsulated text and skips these embedded commas when splitting-up the rows of data into individual fields, because this intensive string-handling can't be optimised into a fast and reliable csv reader by VBA.
Anyway: here's the source code: watch out for line-breaks inserted by StackOverflow's textbox control:
Running the code:
Note that you'll need a reference to the Microsoft Scripting Runtime (system32\scrrun32.dll)
Private Sub test()
Dim arrX As Variant
arrX = ArrayFromCSVfile("MyFile.csv")
End Sub
Streaming a csv file.
Note that I'm assuming your file is in the temp folder:
C:\Documents and Settings[$USERNAME]\Local Settings\Temp
You'll need to use filesystem commands to copy the file into a local folder: it's always quicker than working across the network.
Public Function ArrayFromCSVfile( _
strName As String, _
Optional RowDelimiter As String = vbCr, _
Optional FieldDelimiter = ",", _
Optional RemoveQuotes As Boolean = True _
) As Variant
' Load a file created by FileToArray into a 2-dimensional array
' The file name is specified by strName, and it is exected to exist
' in the user's temporary folder. This is a deliberate restriction:
' it's always faster to copy remote files to a local drive than to
' edit them across the network
' RemoveQuotes=TRUE strips out the double-quote marks (Char 34) that
' encapsulate strings in most csv files.
On Error Resume Next
Dim objFSO As Scripting.FileSystemObject
Dim arrData As Variant
Dim strFile As String
Dim strTemp As String
Set objFSO = New Scripting.FileSystemObject
strTemp = objFSO.GetSpecialFolder(Scripting.TemporaryFolder).ShortPath
strFile = objFSO.BuildPath(strTemp, strName)
If Not objFSO.FileExists(strFile) Then ' raise an error?
Exit Function
End If
Application.StatusBar = "Reading the file... (" & strName & ")"
If Not RemoveQuotes Then
arrData = Join2d(objFSO.OpenTextFile(strFile, ForReading).ReadAll, RowDelimiter, FieldDelimiter)
Application.StatusBar = "Reading the file... Done"
Else
' we have to do some allocation here...
strTemp = objFSO.OpenTextFile(strFile, ForReading).ReadAll
Application.StatusBar = "Reading the file... Done"
Application.StatusBar = "Parsing the file..."
strTemp = Replace$(strTemp, Chr(34) & RowDelimiter, RowDelimiter)
strTemp = Replace$(strTemp, RowDelimiter & Chr(34), RowDelimiter)
strTemp = Replace$(strTemp, Chr(34) & FieldDelimiter, FieldDelimiter)
strTemp = Replace$(strTemp, FieldDelimiter & Chr(34), FieldDelimiter)
If Right$(strTemp, Len(strTemp)) = Chr(34) Then
strTemp = Left$(strTemp, Len(strTemp) - 1)
End If
If Left$(strTemp, 1) = Chr(34) Then
strTemp = Right$(strTemp, Len(strTemp) - 1)
End If
Application.StatusBar = "Parsing the file... Done"
arrData = Split2d(strTemp, RowDelimiter, FieldDelimiter)
strTemp = ""
End If
Application.StatusBar = False
Set objFSO = Nothing
ArrayFromCSVfile = arrData
Erase arrData
End Function
Split2d
Creates a 2-dimensional VBA array from a string:
Public Function Split2d(ByRef strInput As String, _
Optional RowDelimiter As String = vbCr, _
Optional FieldDelimiter = vbTab, _
Optional CoerceLowerBound As Long = 0 _
) As Variant
' Split up a string into a 2-dimensional array.
' Works like VBA.Strings.Split, for a 2-dimensional array.
' Check your lower bounds on return: never assume that any array in
' VBA is zero-based, even if you've set Option Base 0
' If in doubt, coerce the lower bounds to 0 or 1 by setting
' CoerceLowerBound
' Note that the default delimiters are those inserted into the
' string returned by ADODB.Recordset.GetString
On Error Resume Next
' Coding note: we're not doing any string-handling in VBA.Strings -
' allocating, deallocating and (especially!) concatenating are SLOW.
' We're using the VBA Join & Split functions ONLY. The VBA Join,
' Split, & Replace functions are linked directly to fast (by VBA
' standards) functions in the native Windows code. Feel free to
' optimise further by declaring and using the Kernel string functions
' if you want to.
' ** THIS CODE IS IN THE PUBLIC DOMAIN **
' Nigel Heffernan Excellerando.Blogspot.com
Dim i As Long
Dim j As Long
Dim i_n As Long
Dim j_n As Long
Dim i_lBound As Long
Dim i_uBound As Long
Dim j_lBound As Long
Dim j_uBound As Long
Dim arrTemp1 As Variant
Dim arrTemp2 As Variant
arrTemp1 = Split(strInput, RowDelimiter)
i_lBound = LBound(arrTemp1)
i_uBound = UBound(arrTemp1)
If VBA.LenB(arrTemp1(i_uBound)) <= 0 Then
' clip out empty last row: a common artifact in data
'loaded from files with a terminating row delimiter
i_uBound = i_uBound - 1
End If
i = i_lBound
arrTemp2 = Split(arrTemp1(i), FieldDelimiter)
j_lBound = LBound(arrTemp2)
j_uBound = UBound(arrTemp2)
If VBA.LenB(arrTemp2(j_uBound)) <= 0 Then
' ! potential error: first row with an empty last field...
j_uBound = j_uBound - 1
End If
i_n = CoerceLowerBound - i_lBound
j_n = CoerceLowerBound - j_lBound
ReDim arrData(i_lBound + i_n To i_uBound + i_n, j_lBound + j_n To j_uBound + j_n)
' As we've got the first row already... populate it
' here, and start the main loop from lbound+1
For j = j_lBound To j_uBound
arrData(i_lBound + i_n, j + j_n) = arrTemp2(j)
Next j
For i = i_lBound + 1 To i_uBound Step 1
arrTemp2 = Split(arrTemp1(i), FieldDelimiter)
For j = j_lBound To j_uBound Step 1
arrData(i + i_n, j + j_n) = arrTemp2(j)
Next j
Erase arrTemp2
Next i
Erase arrTemp1
Application.StatusBar = False
Split2d = arrData
End Function
Join2D
Turns a 2-dimensional VBA array to a string:
Public Function Join2d(ByRef InputArray As Variant, _
Optional RowDelimiter As String = vbCr, _
Optional FieldDelimiter = vbTab, _
Optional SkipBlankRows As Boolean = False _
) As String
' Join up a 2-dimensional array into a string. Works like the standard
' VBA.Strings.Join, for a 2-dimensional array.
' Note that the default delimiters are those inserted into the string
' returned by ADODB.Recordset.GetString
On Error Resume Next
' Coding note: we're not doing any string-handling in VBA.Strings -
' allocating, deallocating and (especially!) concatenating are SLOW.
' We're using the VBA Join & Split functions ONLY. The VBA Join,
' Split, & Replace functions are linked directly to fast (by VBA
' standards) functions in the native Windows code. Feel free to
' optimise further by declaring and using the Kernel string functions
' if you want to.
' ** THIS CODE IS IN THE PUBLIC DOMAIN **
' Nigel Heffernan Excellerando.Blogspot.com
Dim i As Long
Dim j As Long
Dim i_lBound As Long
Dim i_uBound As Long
Dim j_lBound As Long
Dim j_uBound As Long
Dim arrTemp1() As String
Dim arrTemp2() As String
Dim strBlankRow As String
i_lBound = LBound(InputArray, 1)
i_uBound = UBound(InputArray, 1)
j_lBound = LBound(InputArray, 2)
j_uBound = UBound(InputArray, 2)
ReDim arrTemp1(i_lBound To i_uBound)
ReDim arrTemp2(j_lBound To j_uBound)
For i = i_lBound To i_uBound
For j = j_lBound To j_uBound
arrTemp2(j) = InputArray(i, j)
Next j
arrTemp1(i) = Join(arrTemp2, FieldDelimiter)
Next i
If SkipBlankRows Then
If Len(FieldDelimiter) = 1 Then
strBlankRow = String(j_uBound - j_lBound, FieldDelimiter)
Else
For j = j_lBound To j_uBound
strBlankRow = strBlankRow & FieldDelimiter
Next j
End If
Join2d = Replace(Join(arrTemp1, RowDelimiter), strBlankRow, RowDelimiter, "")
i = Len(strBlankRow & RowDelimiter)
If Left(Join2d, i) = strBlankRow & RowDelimiter Then
Mid$(Join2d, 1, i) = ""
End If
Else
Join2d = Join(arrTemp1, RowDelimiter)
End If
Erase arrTemp1
End Function
Share and enjoy.
Yes read it as a text file.
See this example
Option Explicit
Sub Sample()
Dim MyData As String, strData() As String
Open "C:\MyFile.CSV" For Binary As #1
MyData = Space$(LOF(1))
Get #1, , MyData
Close #1
strData() = Split(MyData, vbCrLf)
End Sub
FOLLOWUP
Like I mentioned below in the comments, AFAIK, there is no direct way of filling a 2d Array from a csv. You will have to use the code that I gave above and then split it per line and finally filling up a 2D array which can be cumbersome. Filling up a column is easy but if you specifically want say from Row 5 to Col 7 Data then it becomes cumbersome as you will have to check if there are sufficient columns/rows in the data. Here is a basic example to get Col B in a 2D Array.
NOTE: I have not done any error handling. I am sure you can take care of that.
Let's say our CSV File looks likes this.
When you run this code
Option Explicit
Const Delim As String = ","
Sub Sample()
Dim MyData As String, strData() As String, TmpAr() As String
Dim TwoDArray() As String
Dim i As Long, n As Long
Open "C:\Users\Siddharth Rout\Desktop\Sample.CSV" For Binary As #1
MyData = Space$(LOF(1))
Get #1, , MyData
Close #1
strData() = Split(MyData, vbCrLf)
n = 0
For i = LBound(strData) To UBound(strData)
If Len(Trim(strData(i))) <> 0 Then
TmpAr = Split(strData(i), Delim)
n = n + 1
ReDim Preserve TwoDArray(1, 1 To n)
'~~> TmpAr(1) : 1 for Col B, 0 would be A
TwoDArray(1, n) = TmpAr(1)
End If
Next i
For i = 1 To n
Debug.Print TwoDArray(1, i)
Next i
End Sub
You will get the output as shown below
BTW, I am curious that since you are doing this in Excel, why not use inbuilt Workbooks.Open or QueryTables method and then read the range into a 2D array? That would be much simpler...
OK, after looking into this, the solution I have arived at is to use ADODB (requires reference to ActiveX Data Objects, this loads the csv file into array without cycling the rows columns. Does require the data to be in good condition.
Sub LoadCSVtoArray()
strPath = ThisWorkbook.Path & "\"
Set cn = CreateObject("ADODB.Connection")
strcon = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & strPath & ";Extended Properties=""text;HDR=Yes;FMT=Delimited"";"
cn.Open strcon
strSQL = "SELECT * FROM SAMPLE.csv;"
Dim rs As Recordset
Dim rsARR() As Variant
Set rs = cn.Execute(strSQL)
rsARR = WorksheetFunction.Transpose(rs.GetRows)
rs.Close
Set cn = Nothing
[a1].Resize(UBound(rsARR), UBound(Application.Transpose(rsARR))) = rsARR
End Sub
To get a known format csv data file into a 2D array I finally adopted the following method, which seems to work well and is quite quick.
I decided that file read operations are fairly fast nowadays, so I run a first pass on the csv file to get the size required for both dimension of the array. With the array suitably dimensioned it is then a simple task to re-read the file, line by line, and populate the array.
Function ImportTestData(ByRef srcFile As String, _
ByRef dataArr As Variant) _
As Boolean
Dim FSO As FileSystemObject, Fo As TextStream
Dim line As String, Arr As Variant
Dim lc As Long, cc As Long
Dim i As Long, j As Long
ImportTestData = False
Set FSO = CreateObject("Scripting.FilesystemObject")
Set Fo = FSO.OpenTextFile(srcFile)
' First pass; read the file to get array size
lc = 0 ' Counter for number of lines in the file
cc = 0 ' Counter for number of columns in the file
While Not Fo.AtEndOfStream ' Read the csv file line by line
line = Fo.ReadLine
If lc = 0 Then ' Count commas to get array's 2nd dim index
cc = 1 + Len(line) - Len(Replace(line, ",", ""))
End If
lc = lc + 1
Wend
Fo.Close
' Set array dimensions to accept file contents
ReDim dataArr(0 To lc - 1, 0 To cc - 1)
'Debug.Print "CSV has "; n; " rows with "; lc; " fields/row"
If lc > 1 And cc > 1 Then
ImportTestData = True
End If
' Second pass; Re-open data file and copy to array
Set Fo = FSO.OpenTextFile(srcFile)
lc = 0
While Not Fo.AtEndOfStream
line = Fo.ReadLine
Arr = Split(line, ",")
For i = 0 To UBound(Arr)
dataArr(lc, i) = Arr(i)
Next i
lc = lc + 1
Wend
End Function 'ImportTestData()
I created this as a Function rather than a Sub to get a simple return value, if required.
Reading a file with 8,500 rows of 20 columns takes approximately 180ms.
This method assumes that the structure (number of delimiters) of the CSV file is the same for every row, typical of a data logging application.
The following solution does not use ActiveX:
I wrote code to import a csv (actually tab-separated) file into an array. That code is the following.
First let's designate the array (initially it is completely void but it will be resized appropriately later):
Dim TxtFile$()
Now for the sub-procedure:
' Fills TxtFile$() array
Sub FillTextFileArray(A$)
'***********************************************************************
' Declarations
'***********************************************************************
Dim I, J As Integer
Dim LineString As String
'***********************************************************************
I = -1: J = 0 ' Will hold array dimentions
Open A$ For Input As #1
Do While Not EOF(1) ' Loop until end of file.
Line Input #1, LineString
LineString = LineString + vbTab ' If not done empty lines give error with Split()
I = I + 1
If J < UBound(Split(LineString, vbTab)) Then J = UBound(Split(LineString, vbTab))
Loop
ReDim TxtFile$(1 To I + 4, 1 To J + 4) ' Not indexed from 0 ! (Plus some room at the end.) This is done to match worksheet format.
Seek #1, 1 ' Reset to start
I = -1 ' Will hold array row index
Do While Not EOF(1) ' Loop until end of file.
Line Input #1, LineString
LineString = LineString + vbTab ' If not done empty lines give error with Split()
I = I + 1
For J = 0 To UBound(Split(LineString, vbTab))
TxtFile$(I + 1, J + 1) = Split(LineString, vbTab)(J)
Next J
Loop
Close #1 ' Close file.
' TxtFile$() now holds the contents of the text file
End Sub
Obviously you can then do what you want with the TxtFile$ array. A$ is the location and name of the text file. As already said, this particular code works with tab-delimited files (vbTab), not comma-delimited (separated), but any adaptation should not be too difficult. It has the advantage of avoiding ActiveX complications.
Alternatively you can use a code like this
Dim line As String, Arr
Dim FSO As Object, Fo As Object
Set FSO = CreateObject("Scripting.FileSystemObject")
Set Fo = FSO.OpenTextFile("csvfile.csv")
While Not Fo.AtEndOfStream
line = Fo.ReadLine ' Read the csv file line by line
Arr = Split(line, ",") ' The csv line is loaded into the Arr as an array
For i = 0 To UBound(Arr) - 1: Debug.Print Arr(i) & " ";: Next
Debug.Print
Wend
01/01/2019 1 1 1 36 55.6 0.8 85.3 95 95 109 102 97 6 2.5 2.5 3.9
01/01/2019 1 2 0 24 0.0 2.5 72.1 89 0 0 97 95 10 6.7 4.9 3.9
01/01/2019 1 3 1 36 26.3 4 80.6 92 92 101 97 97 8 5.5 5.3 3.7
01/01/2019 1 4 0 16 30.0 8 79.2 75 74 87 87 86 10 3.8 4 4.2
These days, GitHub hosts at least three CSV parsers that do exactly what the OP asked for - load a CSV file into a VBA array.
I'm the author of this one:
https://github.com/PGS62/VBA-CSV
It handles a broad variety of CSV files, including those with "embedded" commas, line-feeds etc, and those with a varying number of fields per row. I provide links to alternative VBA CSV parsers in the README file.