Build an array from a text file

R

Ryan Jamison

I'm trying to build a 2D array by reading & picking out text from a separate
text file. Best way to describe what I am doing is an example:

I have a file called input_deck that is the main file that I am using and
wanting to edit. But in order to edit the file, I need information from
another file called materials.txt. Problem is materials.txt looks like:

$ Material Record: Aluminum
MAT1 3
$ Material Record: Steel
MAT1 2
$ Material Record: Copper
MAT1 1

And I need to build an array (or similar) that contains the Material name
(Aluminum, Steel, etc) and number (the number after MAT1). Ideally, it would
be something like:

3 Aluminum
2 Steel
1 Copper

Then I would use this array for editing purposes in my original file,
input_deck. So, is there a way to do anything like this, with my working
file being the original file? Any suggestions or hints would be greatly
appreciated! Thanks

Ryan
 
S

Steve Yandl

Ryan,

I think the best approach would be to use two objects from the scripting
runtime.

For reading and parsing your text file, you will want to check out the
"Scripting.FileSystemObject". Assuming the format follows your example
fairly closely (not a lot of blank lines etc.), you can use the InStr and
Split functions to parse through the lines of text. While you could create
an array, you will be better off creating a dictionary object
("Scripting.Dictionary") with the material names as the key and the the
number being the item.

Steve Yandl
 
R

Ryan Jamison

Steve,

Thank you for the reply. I'm having trouble getting started, particularly
with the Scripting.FileSystemObject. Is there anyway you could post some
sample lines of code? Thanks!

Ryan
 
S

Steve Yandl

Ryan,

This should get you started. For my example, I created a text file based on
your example, named it "Materials.txt" and placed it in "C:\Test".

' ------------------------------------------------------

Sub MaterialsList()

Const ForReading = 1

Dim strLine As String
Dim strMaterial As String
Dim strVal As String
Dim strTestCase As String
Dim strResult As String

' Create needed objects
Set objDict = CreateObject("Scripting.Dictionary")
Set FSO = CreateObject("Scripting.FileSystemObject")
Set objFile = FSO.OpenTextFile("C:\Test\Materials.txt")

' Read file line by line to add keys and items to objDict
Do Until objFile.AtEndOfStream
strLine = objFile.ReadLine
If Left(strLine, 18) = "$ Material Record:" Then
strMaterial = Right(strLine, Len(strLine) - 19)
strLine = objFile.ReadLine
If Left(strLine, 4) = "MAT1" Then
strVal = Right(strLine, Len(strLine) - 5)
If Not objDict.Exists(strMaterial) Then
objDict.Add strMaterial, strVal
strMaterial = ""
strVal = ""
End If
Else
strMaterial = ""
strVal = ""
End If
End If
Loop

objFile.Close

' Test dictionary by checking on the value for material Steel
strTestCase = "Steel"

If objDict.Exists(strTestCase) Then
strResult = objDict.Item(strTestCase) & " " & strTestCase
MsgBox strResult
End If

' Release objects used
Set objFile = Nothing
Set FSO = Nothing
Set objDict = Nothing

End Sub


' ------------------------------------------------------

Steve Yandl
 
S

Steve Yandl

Ryan,

The line
Set objFile = FSO.OpenTextFile("C:\Test\Materials.txt")
should be changed to
Set objFile = FSO.OpenTextFile("C:\Test\Materials.txt", ForReading)

It will still work the way I posted above but if you start adding more
operations on text files it might cause issues. When you use the
OpenTextFile method, you open the file 'for reading', 'for writing', or 'for
appending' but only one of those at a time. We want to read your reference
text file but not alter it in any way.

Steve Yandl
 
D

Doug Robbins - Word MVP

Use

Dim Source As Document, Target As Document
Dim rnge1 As Range, rnge2 As Range
Set Target = ActiveDocument
Set Source = Documents.Open("Materials.txt") ' You will need to provide the
full path
For i = 2 To Source.Paragraphs.Count Step 2
Set rnge1 = Source.Paragraphs(i).Range
rnge1.Start = rnge1.Start + InStr(rnge1, " ")
rnge1.End = rnge1.End - 1
Set rnge2 = Source.Paragraphs(i - 1).Range
rnge2.Start = rnge2.Start + InStr(rnge2, ":")
rnge2.End = rnge2.End - 1
Target.Range.InsertAfter rnge1 & rnge2 & vbCr
Next i



--
Hope this helps.

Please reply to the newsgroup unless you wish to avail yourself of my
services on a paid consulting basis.

Doug Robbins - Word MVP
 
R

Ryan Jamison

Thanks for the code Steve! It seems to be working just fine. But I have one
more question...how do you access the created dictionary? If I just wanted
to view whats in the dictionary, how would I do this? If I needed to access
either the numbers or material names, what would I do here? I've never used
dictionaries, so any help would be great! Thanks again

Ryan
 
S

Steve Yandl

Ryan,

The dictionary object has a 'keys' method that returns a 0 based array
containing all the keys in that dictionary. To get corresponding items, use
the item property referencing the specific key as I did in the subroutine.
There is also an 'items' method that returns an array of all the items. If
you were to want to build a two dimensional array from the dictionary
object, there is also a 'count' property that returns a count of key/item
pairs. One additional tidbit, the keys in a dictionary must be unique,
items don't have to be.

__________________________________

Dim vArray As Variant
vArray = objDict.Keys
For i = 0 to objDict.Count - 1
MsgBox objDict.Item(vArray(i)) & " " & vArray(i)
Next
__________________________________

The big advantage of the dictionary object over arrays and collections is
the efficiency when you want to quickly check for the presence of some
unique key. I use it mostly in scripting if I want to eliminate duplicates
from lists of items but I'm guessing it might also work well in the type of
editing operation I'm guessing you're running based on your question.




Steve Yandl
 
R

Ryan Jamison

Thanks Steve, but one more question...are there any commands similar to
ReadLine for the active document? Now that I have created my array, I need
to find lines such as:

MATERIAL 1
..
..
..
MATERIAL 2
..
..
..
etc... and then I will correspond the array number to the number shown and
insert a line. I know how to insert the line I need, etc, but can't quite
figure out how to find the number (1,2,etc) and than coordinate that with my
array. Thanks

Ryan
 
S

Steve Yandl

I suspect that each line in your active document is a new paragraph. Then,
something like
ActiveDocument.Paragraphs(1).Range.Text
would return the text of the first line, etc.

Steve
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top