For this assignment I am being ask to "Read the file into parallel string arrays corresponding to the columns in the file".
The columns in the file are: "P_CODE" "P_DESCRIPT" "P_INDATE" "P_QOH" "P_MIN" "P_PRICE".
My question is "What is a parallel array?" and what does it look like. I took a guess at how I would imagine it might done but I'm not sure I'm on the right track.
========== project Inventory ==========
Selecting the Read button shall cause the contents of the
InventoryData.txt file to be read from your project’s default folder.
The file does contain a column header line.
Read the file into parallel string arrays corresponding to the columns in the file. After reading the file, close it. Display the
contents of the file in the parallel arrays, including column titles,
in the List box formatted using the Format() method. Left and right
align columns according to convention for their type of data. Hint:
Set the Font property of you List Box to a nonproportional space font
such as Courier.
Write the contents of the file in the parallel arrays, including
column titles, to a file named InventoryDataOut.txt created in your
project’s default folder. Delimit the columns with the pipe (|)
symbol. Each inventory item to one line of output to the file.
This is what I have done so far. I just started so this is not functioning code.
Private Sub btnRead_Click(sender As Object, e As EventArgs) Handles btnRead.Click
Dim dirPath As String = "C:\Users\...\Inventory\"
Dim filePath As String = dirPath & "InventoryData.txt"
'Arrays
Dim P_CODE As String()
Dim P_DESCRIPT As String()
Dim P_INDATE As String()
Dim P_QOH As String()
Dim P_MIN As String()
Dim P_PRICE As String()
' Open file for reading
Dim textIn As New StreamReader(
New FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.None))
'Read in the lines of text into the String variables in the array;
Dim i As Integer = 0
Do While textIn.Peek <> -1
Dim row As String = textIn.ReadLine
Dim columns As String() = row.Split(CChar(" "))
P_CODE(i) = columns(i)
P_DESCRIPT(i) = columns(i)
P_INDATE(i) = columns(i)
P_QOH(i) = columns(i)
P_MIN(i) = columns(i)
P_PRICE(i) = columns(i)
i = i + 1
Loop
'=====================================
'- After reading the file, close it.
textIn.Close()
I get the following warning and error (for each array) :
Warning 1 Variable 'P_CODE' is used before it has been assigned a
value. A null reference exception could result at
runtime.
Columns as independant arrays ? :/
One line answer : You're doing it right !
However :
there are simplier ways to do this (in terms of usage and readability - not performance)
there are typos in your code.
StackOverflow's main purpose is not to teach basic language reference, but help you overcome a specific problem with the appropriate coding (while keeping in mind an answer can't be an answer if it doesn't provide the elements to answer OP's question)
The error you stated is not really related to the question "what is a parallel array". "Variable used before it has been assigned a value". Of course ! Your array is Null. The variable is declared but no instance of it has been created. And Arrays are that strict in dotNet (unlike JavaScript)
What's your real question ?
It's more related to "how should I assign values to (parallel) array(s)" and could be reformulated like "How to read string values stored in a text file in parallel arrays and write them back ?"
Homework questions usually disallows the use of alternative approaches (and sometimes such homework questions are downvoted)
Different approaches like (using a database with linq or) :
Use File.ReadAllLines() to know the number of lines right from the beginning...
Declare your arrays top level : you won't be able to access them outside your btnRead Click otherwise.
Private P_CODE As String()
Private P_DESCRIPT As String()
' ...
Private P_PRICE As String()
Load the file content inside your btnRead Click...
Dim AllLines As String() = File.ReadAllLines(filePath)
' ^^ the above will open and close the file XD
Dim Columns As String()
' Initialize your arrays...
ReDim(P_CODE, AllLines.Length - 1)
ReDim(P_DESCRIPT, AllLines.Length - 1)
' ...
ReDim(P_PRICE, AllLines.Length - 1)
' set each cell value.
For LineIndex As Int32 = 0 To P_CODE.Length - 1
Columns = AllLines(LineIndex).Split(" "c)
P_CODE(LineIndex) = Columns(0)
P_DESCRIPT(LineIndex) = Columns(1)
' ...
P_PRICE(LineIndex) = Columns(5)
' Hey ! Your File Datas are ordered horizontaly,
' so Columns must be indexed from 0 to 5
' instead of you "i" in your code in order
' to correctly feed your parallel arrays
Next
Your teacher wanna force you to open the file using StreamReader and teach you to not forget to close the file... and use StreamReader.ReadLine() ... Okay..!
' ...
Dim LineIndex As Int32 = 0
Dim textIn As New StreamReader(filePath)
' ^^ why do you bother using a FileStream ?
Dim Row As String = textIn.ReadLine()
Dim Columns As String()
Do While row IsNot Nothing
Redim Preserve P_CODE(LineIndex)
Redim Preserve P_DESCRIPT(LineIndex)
' ...
Redim Preserve P_PRICE(LineIndex)
Columns = Row.Split(" "c)
P_CODE(LineIndex) = Columns(0)
P_DESCRIPT(LineIndex) = Columns(1)
' ...
P_PRICE(LineIndex) = Columns(5)
Row = textIn.ReadLine()
LineIndex = LineIndex + 1
Loop
textIn.Close() ' Voila !
' /!\ Add at least a Try Catch enclosing your Do/Loop if you're lazy.
Tell your teacher you're gonna use Using because he forces you to use StreamReader.Peek() (is .Peek() necessary ?)
Using textIn As New StreamReader(filePath)
Dim LineIndex As Int32 = 0
Dim Columns As String()
Do While textIn.Peek() <> -1
Redim Preserve P_CODE(LineIndex)
Redim Preserve P_DESCRIPT(LineIndex)
' ...
Redim Preserve P_PRICE(LineIndex)
Columns = textIn.ReadLine().Split(" "c)
P_CODE(LineIndex) = Columns(0)
P_DESCRIPT(LineIndex) = Columns(1)
' ...
P_PRICE(LineIndex) = Columns(5)
LineIndex = LineIndex + 1
Loop
End Using ' StreamReader closed ! XD
No ! Don't ask me to use a FileStream ! I would if I know the size of each data chunck in the file and I'm using structures of fixed size. FileStream is best used when manipulating large buffer of datas as it directly works in memory with appropriate asynchronous checks.
Just to read lines ? No ! For this part, read the documentation.
String.Format()
Dim Row As String
MyListBox.Items.Clear()
For LineIndex As Int32 = 0 To P_CODE.Length - 1
Row = String.Format("{0, -12}{1,-16}{2,10}{3,10}{4,8}{5,10}", _
P_CODE(LineIndex), _
P_DESCRIPT(LineIndex), _
P_INDATE(LineIndex), _
P_QOH(LineIndex), _
P_MIN(LineIndex), _
P_PRICE(LineIndex))
MyListBox.Items.Add(Row)
Next
Write file to InventoryDataOut.txt..
Dim Separator As String = "|"
Dim FileContent As New StringBuilder() ' System.Text
' Prepare File content...
If P_CODE.Length > 0 Then
For LineIndex As Int32 = 0 To P_CODE.Length - 2 ' Note the -2
FileContent.AppendLine(String.Format("{0}{6}{1}{6}{2}{6}{3}{6}{4}{6}{5}", _
P_CODE(LineIndex), _
P_DESCRIPT(LineIndex), _
P_INDATE(LineIndex), _
P_QOH(LineIndex), _
P_MIN(LineIndex), _
P_PRICE(LineIndex), _
Separator)))
Next
FileContent.Append(String.Format("{0}{6}{1}{6}{2}{6}{3}{6}{4}{6}{5}", _
P_CODE(P_CODE.Length - 1), _
P_DESCRIPT(P_CODE.Length - 1), _
P_INDATE(P_CODE.Length - 1), _
P_QOH(P_CODE.Length - 1), _
P_MIN(P_CODE.Length - 1), _
P_PRICE(P_CODE.Length - 1), _
Separator)))
' This ensures we don't add unnecessary line at the end of the file
' which would make your application explode !
' best move is to check for null entries upon file parsing.
' (Again : File.ReadAllLines() + RemoveEmptyString parameter to keep it simple)
End If
' Create your file using the stream object
' you're forced to use by your teacher,
' then dump the the content of your StringBuilder inside like
MyDummyStream.Write(FileContent.ToString())
' And close you dummy stream or use Using XD
Does your teacher has a bunch of CSV-like files which needs separator conversion from space to pipe ?
It seems he's just lazy to write the code to dispatch each column in several parallel arrays for display or other purpose. Or why would you use the space as separator upon loading the content of your file while using pipe instead to write them ?
If its a typo, just don't bother reading this. Otherwise, your teacher is just asking you to create a small program that converts the space separator to pipe... (while giving you the mission to learn manipulate (parallel) arrays, streams I/O, and String.Format)
.
Related
Using visual basic. Trying to load a series of reports onto a listview, listview consists of 3 columns (location, date and severity level) everytime it loads it crashes due to 'index being outside the bounds of the array'.Specifically around DOI = reportdetails(1) in my code. It is loading off of a textfile. I have the data within the textfile so I am unsure of why it is saying I am asking for information that doesnt exist. The program also encypts the textfile.
Dim locate, DOI, SeverityLevel, ReportTitles, EReportTitles, ReportDetails(2) As String
Dim Index As Integer 'Define Variables
Dim FileNum As Integer = FreeFile()
Dim IncidentReport As ListViewItem
lstReports.Items.Clear()
If Dir("ReportTitles.txt") <> "" Then 'If the directory of the file exits then continue
FileOpen(FileNum, "ReportTitles.txt", OpenMode.Input) 'open file
Do Until EOF(FileNum) 'Repeat until the end of the file is reached
EReportTitles = "" 'Clear variables, to safeguard against crashes or errors
ReportTitles = ""
EReportTitles = LineInput(FileNum) 'EReportTitles is equal to the current file line
Dim FileName As String = "ReportTitles.txt" 'Define variables
Dim I, C As Integer
Dim Last As Integer = EReportTitles.Length - 1
Dim ThisChar As Char
For I = 0 To Last 'Begin for loop
ThisChar = EReportTitles.Chars(I) 'Decryption of file
C = Asc(ThisChar) Xor 22
ThisChar = Chr(C)
ReportTitles += ThisChar
Next
If ReportTitles <> "" Then
ReportDetails = Split(ReportTitles, ",") 'Split the lines when a "," is encountered
locate = ReportDetails(0) 'Assosciate to relevant value in array
DOI = ReportDetails(1)
SeverityLevel = ReportDetails(2)
IncidentReport = New ListViewItem
IncidentReport.Text = locate 'Add relevant values to IncidentReport ListViewItem variable
IncidentReport.SubItems.Add(DOI)
IncidentReport.SubItems.Add(SeverityLevel)
lstReports.Items.Add(IncidentReport) 'Transfer IncidentReport to listview
Else
End If
Loop
FileClose(FileNum) 'close file
End If
Expected result is to load all of the report location, dates and severity levels onto the listview.
Also sorry about the formatting of this question, i'm new to stack overflow.
There's no point declaring ReportDetails like this:
ReportDetails(2) As String
because that creates an array that you never use. Here:
ReportDetails = Split(ReportTitles, ",")
you are creating a new array anyway and the length of that array will be determined by the number of delimiters in ReportTitles. If you're being told that 1 is an invalid index for that array then that array must only contain 1 element, which means that ReportTitles didn't contain any delimiters.
This is not something that we should have to explain to you because you can easily see it for yourself by debugging and you should ALWAYS debug BEFORE posting here. Set a breakpoint at the top of the code, step through it line by line and examine the state at each step. You can easily see the contents of ReportTitles and ReportDetails and anything else to see whether they are what you expect them to be.
If the point here is to read a CSV file then you really ought to be using the TextFieldParser class. The documentation for that class includes a code example.
This requires .Net Standard 2.1, and so I'm not sure if VB.Net can use the required SpanAction for the String.Create() method, but if it is supported it should greatly outperform the original.
lstReports.Items.Clear()
'Read and "Decrypt" (and I use that term loosely) the file with only a single heap allocation
Dim file As String
Using fs As FileStream = File.OpenRead("ReportTitles.txt")
file = String.Create(fs.Length, fs,
Sub(chars, stream)
For i As Integer = 0 To stream.Length - 1
'THIS IS NOT ENCRYPTION! At best, it's obfuscation.
chars(i) = Chr(fs.ReadByte() Xor 22)
Next
End Sub)
End Using
'Use an actual CSV parser
Using reader As New StringReader(file), _
parser As New TextFieldParser(reader)
parser.TextFieldType = FileIO.FieldType.Delimited
parser.Delimiters = New String() {","}
Dim row As String()
While Not parser.EndOfData
row = parser.ReadFields()
If row.Length >= 3 Then
Dim IncidentReport As New ListViewItem()
IncidentReport.Text = row(0) '
IncidentReport.SubItems.Add(row(1))
IncidentReport.SubItems.Add(row(2))
lstReports.Items.Add(IncidentReport)
End If
End While
End Using
If you are not able to use that version, this is not quite as good, but still a better approach than the original:
lstReports.Items.Clear()
'Load and "Decrypt" the file
Dim file As String
Using fs As FileStream = File.OpenRead("ReportTitles.txt")
Dim builder As New StringBuilder(fs.Length)
For i As Integer = 0 To fs.Length - 1
'THIS IS NOT ENCRYPTION! At best, it's obfuscation.
builder.Append(Chr(fs.ReadByte() Xor 22))
Next
file = builder.ToString()
End Using
'Use an actual CSV parser
Using reader As New StringReader(file), _
parser As New TextFieldParser(reader)
parser.TextFieldType = FileIO.FieldType.Delimited
parser.Delimiters = New String() {","}
Dim row As String()
While Not parser.EndOfData
row = parser.ReadFields()
If row.Length >= 3 Then
Dim IncidentReport As New ListViewItem()
IncidentReport.Text = row(0) '
IncidentReport.SubItems.Add(row(1))
IncidentReport.SubItems.Add(row(2))
lstReports.Items.Add(IncidentReport)
End If
End While
End Using
In both cases, use Try/Catch rather than Dir() to check whether the location exists. Just try to open the file. Dir() costs an extra disk seek, and there are precious few things in programming slower than disk I/O.
This works fine, assuming there are no line breaks in certain cells.
dgvResults.SelectAllCells()
dgvResults.ClipboardCopyMode = DataGridClipboardCopyMode.IncludeHeader
ApplicationCommands.Copy.Execute(Nothing, dgvResults)
Dim result As [String] = DirectCast(Clipboard.GetData(DataFormats.CommaSeparatedValue), String)
Clipboard.Clear()
dgvResults.UnselectAllCells()
Try
Dim file As New System.IO.StreamWriter("c:\export.csv")
file.WriteLine(result)
file.Close()
Process.Start("c:\export.csv")
Catch ex As Exception
MessageBox.Show(ex.Message, "Error")
End Try
This is how I add line breaks
Dim x As New List(Of String)
For Each item In res.Properties("proxyaddresses")
x.Add(item)
Next
AllSMTPAddresses = String.Join(ControlChars.Lf, x)
When I export this, it doesn't take into consideration there are line breaks, and completely ignores them... so the excel formatting is a little wonky. I've tried: Environment.NewLine, vbCrLf, and now ControlChars.Lf. I think excel doesn't know what to do with the line breaks, so it just does w.e it wants, and creates new rows with them.
Any idea on how I would attack this?
Updated results #Jimmy
This is what it's supposed to look like...
I don't believe this will be possible without modifying those rows prior to the export. I found some example code that may help,
Public Sub writeCSV(grid1 As Object, outputFile As String)
' Create the CSV file to which grid data will be exported.
Dim sw As New StreamWriter(outputFile)
' First we will write the headers.
Dim dt As DataTable = DirectCast(grid1.DataSource, DataSet).Tables(0)
Dim iColCount As Integer = dt.Columns.Count
For i As Integer = 0 To iColCount - 1
sw.Write(dt.Columns(i))
If i < iColCount - 1 Then
sw.Write(",")
End If
Next
sw.Write(sw.NewLine)
' Now write all the rows.
For Each dr As DataRow In dt.Rows
For i As Integer = 0 To iColCount - 1
sw.Write("""") 'lets encapsulate those fields in quotes, quoted csv file!
If Not Convert.IsDBNull(dr(i)) Then
sw.Write(dr(i).ToString())
End If
sw.Write("""")
If i < iColCount - 1 Then
sw.Write(System.Globalization.CultureInfo.CurrentCulture.TextInfo.ListSeparator)
End If
Next
sw.Write(sw.NewLine)
Next
sw.Close()
End Sub
modified from here
As a beginner to VBA I'm trying to learn most of this content ad-hoc, so pardon my dust.
I have a subroutine I'm writing for reading through lines in a text file. Each line is space delimited with ' as a text identifier. I require each line to be split into fields as a multidimensional array.
Sub ReadLines()
Dim LineValues() As String
Dim row As Long, col As Long
Dim DataArray() As String
Dim TempArray() As String
Dim FileContent As String
Dim FilePath As String
FilePath = "c:\mytextfile.txt"
row = 0
TextFile = FreeFile
Open FilePath For Input As TextFile
FileContent = Input(LOF(TextFile), TextFile)
Close TextFile
LineValues = Split(FileContent, vbCrLf)
For X = LBound(LineValues) To UBound(LineValues)
If Len(Trim(LineValues(X))) <> 0 Then
DataArray = Split(LineValues(X), "'")
col = UBound(DataArray)
TempArray = DataArray
ReDim DataArray(col, row)
For i = LBound(TempArray) To UBound(TempArray)
DataArray(i, row) = TempArray(i)
Next i
End If
row = row + 1
Next X
I came to this bit of code after struggling against the multidimensional problems with ReDim Preserve. (only being able to modify the last dimension) The multidimensional array in my text file will have unknown columns and rows depending on user input.
This code does the process correctly...but just can't store the array elements correctly! The intent above was to use a temporary array (TempArray) while I ReDim (and empty) the array I am interested in (DataArray) and then copy back the elements originally from DataArray into the resized dimensions.
However when stepping through the code I can see each row being placed correctly but then erased with each iteration at line,
DataArray = Split(LineValues(X), "'")
I essentially have a matrix that is sized by the total number of rows but only by the number of columns on the last row (and only the values from the last row) as a result of this.
I realise why this is happening but can anyone here propose a solution? As a beginner this is all a bit maddening!
EDIT, Full Problem Description
To clarify fully, this is a subroutine I will call as part of a script reading through a text file which contains irrelevant data. This text file looks a little something like this, (vagueness of the references is intentional)
'<irrelevant text I want to ignore until seeing pattern 'NumberOfVariables?'>
...
...
NumberOfVariables?
NUMBEROFVARIABLES
'for the end user, I need to be able to pull information from each of these fields assigned to a variable to create strings as headers as per a specific format
'note that variable and variable type
Variable#1 VARIABLETYPE Location? LOCATION UNITS DESCRIPTION 'text for each field is enclosed as follows '' (code formatting on site prevents me doing this)
Variable#2 VARIABLETYPE Location? LOCATION UNITS DESCRIPTION
...
Variable#NUMBEROFVARIABLES
' from here there is a column of data that is assigned to each variable such that
Variable#1Element1 Variable#2Element1 'etc until #NUMBEROFVARIABLES
Variable#1Element2 Variable#2Element2
Variable#1Element3 Variable#2Element3
Variable#1FinalElement Variable#2FinalElement
Main goal is use the script in original post to get these fields in a multidimensional matrix that I can then use against some conditional statements to get the header strings as per the end user desires.
From here I would then find a way to have the columns of data match up with each variable such that it can be automated into Excel.
A step further would be some sort of MsgBox w/ a pulldown that would select variables to copy across but that's pie in the sky thinking at my stage of development right now!
Try this. I've not tested it:
Sub ReadLines()
Const FilePath$ = "c:\mytextfile.txt"
Dim iFile%, c&, i&, j&, k&, Content$, Lines, Temp, Data
c = 499
Open FilePath For Input As #iFile
Content = StrConv(InputB(LOF(iFile), iFile), vbUnicode)
Close #iFile
Lines = Split(Content, vbCrLf)
ReDim Data(0 To UBound(Lines), 0 To c)
For i = 0 To UBound(Lines)
If Len(Trim$(Lines(i))) Then
Temp = Split(Lines(i), "'")
If k < UBound(Temp) Then k = UBound(Temp)
If k > c Then
c = k * 2
ReDim Preserve Data(0 To UBound(Lines), 0 To c)
End If
For j = 0 To UBound(Temp)
Data(i, j) = Temp(j)
Next
End If
Next
ReDim Preserve Data(0 To UBound(Lines), 0 To k)
End Sub
I require each line to be split into fields as a multidimensional array.
Well I don't know if this is actually true, because i'm not sure what you're ultimately doing with the data, but in any case, a super simple alternative would be to read the .txt file in to a workbook structure.
To do this, use the Workbooks.OpenText method with parameter: TextQualifier:=xlTextQualifierSingleQuote (there are some additional optional parameters which may be needed depending on your use-case).
This should open the text file, properly delimited, in to the "fields" (Columns in the worksheet).
From there, you can assign the sheet's UsedRange.Value to a variant array.
Alright, this one has been driving me up a wall for the past few hours, and I feel like I can almost taste victory, but I am stuck.
I am writing files into a directory based on user supplied requirements, and this particular section deals with assigning a new Version Number to the new file. So basically, this creates the new file using a naming convention of:
Path\FileName_ver1
Path\FileName_ver2
And so on. The issue is, I cannot figure out how to determine if a file with similiar naming (minus the _ver# string) exists in the directory, and then parse the name to find out the current version number, and then create the new file using the version number and adding 1 to it.
If you look at my current code, the issue at the moment is arising when it goes into the loop, telling me that the array is out of bounds, even though the file does exist within the directory.
Dim strPossibleFilename() As String = Directory.GetFiles(savePath, saveName & "_ver*" & saveExt)
Dim intVersionNumber As Integer = 1
For i = 0 To strPossibleFilename.Length - 1
If File.Exists(strPossibleFilename(i)) Then
Dim fileInfo As New FileInfo(strPossibleFilename(i))
Dim fullName As String
Dim strVersionNumber As String
fullName = fileInfo.FullName
Dim versionPosition As Integer = fullName.IndexOf("_ver")
Dim dotPosition As Integer = fullName.IndexOf(".")
Dim versionCharacterCount As Integer = dotPosition - versionPosition
strVersionNumber = fullName.Substring(versionPosition, versionCharacterCount)
If intVersionNumber < strVersionNumber Then
intVersionNumber = strVersionNumber
End If
End If
Next i
If intVersionNumber > 1 Then
saveLocation = savePath & saveName & "_ver" & intVersionNumber + 1 & saveExt
fstr = New FileStream(saveLocation, FileMode.CreateNew, FileAccess.ReadWrite)
fstr.Write(inBuf, 0, bytesRead)
Else
saveLocation = savePath & saveName & "_ver1" & saveExt
fstr = New FileStream(saveLocation, FileMode.CreateNew, FileAccess.ReadWrite)
fstr.Write(inBuf, 0, bytesRead)
End If
P.S. All of the other functionality works, as far as the writing and everything, I am doing this in multiple places in my code, including assigning other varied strings to file names when one already exists...
Please let me know if you need more information.
EDIT:
Made a couple changes based on the answers given, and now it is finding the file, but this brings up a new problem... So I cannot figure out how to ONLY grab the number that is AFTER "_ver" to assign that to intVersionNumber.. Any ideas?
EDIT 2:
Okay, to solve that issue, I added:
Dim strVersionString As String
And added a few other things, so now the for loop looks like this:
For i = 0 To strPossibleFilename.Length - 1
If File.Exists(strPossibleFilename(i)) Then
Dim fileInfo As New FileInfo(strPossibleFilename(i))
Dim fullName As String
Dim strVersionString As String
Dim strVersionNumber As String
fullName = fileInfo.FullName
Dim versionPosition As Integer = fullName.IndexOf("_ver")
Dim dotPosition As Integer = fullName.IndexOf(".")
Dim versionCharacterCount As Integer = dotPosition - versionPosition
strVersionString = fullName.Substring(versionPosition, versionCharacterCount)
Dim rPosition As Integer = strVersionString.IndexOf("r") + 1
strVersionNumber = strVersionString.Substring(rPosition, strVersionString.Length - rPosition)
If intVersionNumber < strVersionNumber Then
intVersionNumber = strVersionNumber
End If
End If
Next i
And now it is working :D Thanks for all the help!
You are doing it right, I have a sneaking suspicion here with this line
For i = 0 To strPossibleFilename.Length
change it to
For i = 0 To strPossibleFilename.Length -1
and then unless you kissed BillGates daughter and he's pissed off, it should work!
For the second part of your question, how to get the number after the _ver
' consider padding the version number
' with leading zeros
' and using a second underscore
' to make it easier to parse for number
Dim fileName As String = "filename_ver_001"
Dim parts As String() = fileName.Split("_"c)
Dim verNumber As Integer = Integer.Parse(parts(2))
If you add a second underscore, you can use the String.Split to break the filename into an array.
FWIW, if you want a more sortable file list pad out the number with leading zeros. Otherwise filename_ver11 is ordered before filename_ver2
I am not very familiar with VBA but need to use it for a new software program I am using (not Microsoft related)
I have a text file that has columns of data I would like to read into VBA.
Specifically the text file has 4 entries per row. Thus I would like to load in the column vectors (N by 1).
The text file is separated by a space between each entry.
So for example I want to load in column one and save it as array A, then column two and save as array B, then column three and save as array C, and then column four and save as array D.
This code snippet found below from http://www.tek-tips.com/faqs.cfm?fid=482 is something I found that can load in text to an array, but I need to adapt it to be able to save the columns as different arrays as specified above...
Open "MyFile.txt" For Input As #1
ReDim Txt$(0)
Do While Not EOF(1)
ReDim Preserve Txt$(UBound(Txt$) + 1)
Input #1, Txt$(UBound(Txt$))
Loop
Close #1
For this example, you will need a file called schema.ini in the same directory as the text file. It should contain:
[Import.txt]
Format=Delimited( )
Where Import.txt is the name of the file (http://msdn.microsoft.com/en-us/library/ms709353(VS.85).aspx).
You can then use this, which should work in VBScript or VBA with very little tampering:
Set cn = CreateObject("ADODB.Connection")
'Note HDR=Yes, that is, first row contains field names '
'and FMT delimted, ie CSV '
strCon="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\Docs\;" _
& "Extended Properties=""text;HDR=Yes;FMT=Delimited"";"
cn.Open strcon
strSQL="SELECT * FROM Import.txt" _
set rs = createobject("adodb.recordset")
rs.open strSQL,cn
MsgBox rs(2)
MsgBox rs.GetString
The first message box should return the third column of the first row, it is a test that it works.
The second message box should return the whole file, so don't use it with a large set. The recordset can be manipulated, or you can use .GetRows to create an array of values (http://www.w3schools.com/ado/met_rs_getrows.asp)
Seems the remaining problem is to convert from an array of lines to four arrays of columns.
Maybe this snippet helps
Option Explicit
Option Base 0
Sub import()
Dim sTxt() As String
Dim sLine As Variant
Dim iCountLines As Long
Dim iRowIterator As Long
Dim i As Long
Dim sRow() As String
Dim sColumnA() As String
Dim sColumnB() As String
Dim sColumnC() As String
Dim sColumnD() As String
' read in file '
Open "MyFile.txt" For Input As #1
ReDim sTxt(0)
Do While Not EOF(1)
Input #1, sTxt(UBound(sTxt))
ReDim Preserve sTxt(UBound(sTxt) + 1)
Loop
Close #1
' dim array for each columns '
iCountLines = UBound(sTxt)
Debug.Print "working with ", iCountLines, "lines"
ReDim sColumnA(iCountLines)
ReDim sColumnB(iCountLines)
ReDim sColumnC(iCountLines)
ReDim sColumnD(iCountLines)
' "transpose" sTxt '
iRowIterator = 0
For Each sLine In sTxt
sRow = Split(sLine, " ")
If UBound(sRow) = 3 Then
sColumnA(iRowIterator) = sRow(0)
sColumnB(iRowIterator) = sRow(1)
sColumnC(iRowIterator) = sRow(2)
sColumnD(iRowIterator) = sRow(3)
iRowIterator = iRowIterator + 1
End If
Next sLine
' now work with sColumnX '
Debug.Print "Column A"
For i = 0 To iCountLines
Debug.Print sColumnA(i)
Next i
End Sub
There is few detais in your question, but i would suggest using "Text to column"
If you're not very familiar with VBA programming try recording macro with this steps:
Import file to Excel
select column A
select "Text to columns" form tools menu
choose delimited by space
This way you'll get array of data you asked for, now assigning to any variables you want shouldn't be a problem.
EDIT (Without using Excel):
Take a look on that FSO method.
by replacing
MsgBox strLing
with some kind of split function, like
strTemp = Split(strLine, " ")
You'll be able to loop through all the values in your source file, would that work?