Skip to main content

I need to define an array within a structure.  I tried "Txt As Variant" and "txt() As Variant" and neither work when try to use Struct.Txt as an array. What is the correct way to define an array within a structure in Extra Basic? It works in VB but not Extra. Please point me in the right direction.

' Example Data
Type RWText
	    Cmd As String
    	FnameA As String
     	FnameB As String
    	Value As Integer
        Txt As Variant
    	Src As String
    	Dst As String
End Type

Dim Struct As RWText
Struct.Txt(1) = "test"


#type
#Attachmate
#MainframeAccess
#Extra!
#structure
#Extra!X-treme

I need to define an array within a structure.  I tried "Txt As Variant" and "txt() As Variant" and neither work when try to use Struct.Txt as an array. What is the correct way to define an array within a structure in Extra Basic? It works in VB but not Extra. Please point me in the right direction.

' Example Data
Type RWText
	    Cmd As String
    	FnameA As String
     	FnameB As String
    	Value As Integer
        Txt As Variant
    	Src As String
    	Dst As String
End Type

Dim Struct As RWText
Struct.Txt(1) = "test"


#type
#Attachmate
#MainframeAccess
#Extra!
#structure
#Extra!X-treme

Hi David;
something like below sample ? The code declares a custom data type named "Employee". It has three fields: name, id and salary. Each field is of a specific data type (string, integer and single precision floating point).n the Main subroutine, an array of type "Employee" is declared with 4 elements, called "employees". The first two elements of the array are then populated with employee data (name, id, and salary).

Finally, the values of the first two elements of the "employees" array are printed to the screen.

TYPE Employee
 name AS STRING * 20
 id AS INTEGER
 salary AS SINGLE
END TYPE


Sub Main

DIM employees(4) AS Employee

employees(0).name = "John Doe"
employees(0).id = 12345
employees(0).salary = 55000.0

employees(1).name = "Jane Doe"
employees(1).id = 12346
employees(1).salary = 60000.0

PRINT employees(0).name, employees(0).id, employees(0).salary
PRINT employees(1).name, employees(1).id, employees(1).salary

End Sub



cheers


Hi David;
something like below sample ? The code declares a custom data type named "Employee". It has three fields: name, id and salary. Each field is of a specific data type (string, integer and single precision floating point).n the Main subroutine, an array of type "Employee" is declared with 4 elements, called "employees". The first two elements of the array are then populated with employee data (name, id, and salary).

Finally, the values of the first two elements of the "employees" array are printed to the screen.

TYPE Employee
 name AS STRING * 20
 id AS INTEGER
 salary AS SINGLE
END TYPE


Sub Main

DIM employees(4) AS Employee

employees(0).name = "John Doe"
employees(0).id = 12345
employees(0).salary = 55000.0

employees(1).name = "Jane Doe"
employees(1).id = 12346
employees(1).salary = 60000.0

PRINT employees(0).name, employees(0).id, employees(0).salary
PRINT employees(1).name, employees(1).id, employees(1).salary

End Sub



cheers

Thank you for the advise, but I don't want the whole structure to be an Array. I only need one item to be an array. I'm thinking I'll have to do the array outside of the structure.


Thank you for the advise, but I don't want the whole structure to be an Array. I only need one item to be an array. I'm thinking I'll have to do the array outside of the structure.

Hi David, 

correct, I can't get an array to work inside a Type either.

Question why are you not using an array outside the type?

e.g.

Type RWText
     Cmd As String
     FNameA As String
     FnameB As String
     Value As Integer
     TxtUBound As Integer   'Size of the array you need
     Src As String
     Dst As String
End Type

Sub main
    Dim myRWText as RWText
    myRWText.TxtUBound = 2
    Dim RWText_Txt(myRWText.TxtUBound) as Sting
    RWText_Txt(1) = "Hello"
    RWText_Txt(2) = "world"
End Sub

What is the goal of this function you are working on?

Tom


Hi David, 

correct, I can't get an array to work inside a Type either.

Question why are you not using an array outside the type?

e.g.

Type RWText
     Cmd As String
     FNameA As String
     FnameB As String
     Value As Integer
     TxtUBound As Integer   'Size of the array you need
     Src As String
     Dst As String
End Type

Sub main
    Dim myRWText as RWText
    myRWText.TxtUBound = 2
    Dim RWText_Txt(myRWText.TxtUBound) as Sting
    RWText_Txt(1) = "Hello"
    RWText_Txt(2) = "world"
End Sub

What is the goal of this function you are working on?

Tom

Good afternoon, Tom,

  On my other bloated macro there are a number of time I need to do file functions and figured i would just have a FileOps() function to be used for all my read, write, etc. needs.  The text array was for any data being written out or read.  This is rudimentary but here's my function.  Don't judge me yet, I'm still playing and figuring out best approach. 

Type RWText
     Cmd As String
     FNameA As String
     FnameB As String
     Value As Integer
     Src As String
     Dst As String
End Type


Declare Function FileOps(Struct As RWText, RWText_Txt() As String) 


Sub Main ' testing macro 


     Dim Struct  As RWText
     Dim RWText_Txt(2) As String
     Struct.Value = 0
     Struct.Cmd = "W"
     Struct.FnameA = "Test1.txt"
     Struct.FnameB = ""     
     Struct.Src = "H:\\Dev\\"
     Struct.Dst = "" 
        
     RWText_Txt(0) = "Hello"
     RWText_Txt(1) = "world"
     
   
     Call FileOps(Struct, RWText_Txt)

End Sub


Function FileOps(Struct As RWText, RWText_Txt() As String) 
        Dim fnum
        Dim x As Integer
        
        On error goto ExitSafe
       
  Select case Struct.Cmd
  
  Case "C" ' Check File
         If Dir(Struct.Src & Struct.FnameA) <> "" Then
         msgbox "File " & Struct.FnameA & " exists."
         Else
        msgbox "File " & Struct.FnameA & " doesn't exist."
         End If  
         
  Case "W" ' Write 'overwrite data in whole file'
        x = 0
        fnum = FreeFile()

        Open str(Struct.Src & Struct.FnameA) For Output As #fnum

        Do Until x = UBOUND(RWText_Txt)
        Write #fnum, RWText_Txt(x)
        x = x + 1
        Loop
        
        Close #fnum
        
  Case "A" ' Write 'Append' to add new lines
        x = 0
        fnum = FreeFile()

        Open str(Struct.Src & Struct.FnameA) For Append As #fnum

        Do Until x = UBOUND(RWText_Txt)
        Write #fnum, RWText_Txt(x)
        x = x + 1
        Loop
        Close #fnum
    
  Case "R" ' Read

   Dim strLine As String
   x=0
   Open Struct.Src & Struct.FnameA For Input As #1
   
   Do Until EOF(1)
      Line Input #1, strLine
      x = x + 1
      RWText_Txt(x) = strLine
   Loop
   Close #1
        
   Case "CP" ' copy file
        FileCopy Struct.Src & Struct.FnameA, Struct.Dst & Struct.FnameB

   Case "D"
    ' Delete
    
   Case Else
   
      msgbox "thats all"
      
 end select
 
ExitSafe:
    Close #fnum
    
End Function

Good afternoon, Tom,

  On my other bloated macro there are a number of time I need to do file functions and figured i would just have a FileOps() function to be used for all my read, write, etc. needs.  The text array was for any data being written out or read.  This is rudimentary but here's my function.  Don't judge me yet, I'm still playing and figuring out best approach. 

Type RWText
     Cmd As String
     FNameA As String
     FnameB As String
     Value As Integer
     Src As String
     Dst As String
End Type


Declare Function FileOps(Struct As RWText, RWText_Txt() As String) 


Sub Main ' testing macro 


     Dim Struct  As RWText
     Dim RWText_Txt(2) As String
     Struct.Value = 0
     Struct.Cmd = "W"
     Struct.FnameA = "Test1.txt"
     Struct.FnameB = ""     
     Struct.Src = "H:\\Dev\\"
     Struct.Dst = "" 
        
     RWText_Txt(0) = "Hello"
     RWText_Txt(1) = "world"
     
   
     Call FileOps(Struct, RWText_Txt)

End Sub


Function FileOps(Struct As RWText, RWText_Txt() As String) 
        Dim fnum
        Dim x As Integer
        
        On error goto ExitSafe
       
  Select case Struct.Cmd
  
  Case "C" ' Check File
         If Dir(Struct.Src & Struct.FnameA) <> "" Then
         msgbox "File " & Struct.FnameA & " exists."
         Else
        msgbox "File " & Struct.FnameA & " doesn't exist."
         End If  
         
  Case "W" ' Write 'overwrite data in whole file'
        x = 0
        fnum = FreeFile()

        Open str(Struct.Src & Struct.FnameA) For Output As #fnum

        Do Until x = UBOUND(RWText_Txt)
        Write #fnum, RWText_Txt(x)
        x = x + 1
        Loop
        
        Close #fnum
        
  Case "A" ' Write 'Append' to add new lines
        x = 0
        fnum = FreeFile()

        Open str(Struct.Src & Struct.FnameA) For Append As #fnum

        Do Until x = UBOUND(RWText_Txt)
        Write #fnum, RWText_Txt(x)
        x = x + 1
        Loop
        Close #fnum
    
  Case "R" ' Read

   Dim strLine As String
   x=0
   Open Struct.Src & Struct.FnameA For Input As #1
   
   Do Until EOF(1)
      Line Input #1, strLine
      x = x + 1
      RWText_Txt(x) = strLine
   Loop
   Close #1
        
   Case "CP" ' copy file
        FileCopy Struct.Src & Struct.FnameA, Struct.Dst & Struct.FnameB

   Case "D"
    ' Delete
    
   Case Else
   
      msgbox "thats all"
      
 end select
 
ExitSafe:
    Close #fnum
    
End Function

Hi David, 

Not wanting to come across the wrong way here, but I don't like that idea at all.

If I was in your shoes I would look to perform your file operations using the Microsoft.Scripting.Runtime library's FileSystemObject object. That should allow you to perform most of the various operations in one line of code. Writing to file may take some extra effort.

Unfortunately as ebedit.exe doesn't have any usable intelisense or object browser, normally when I'm looking to use COM/OLE objects from other libraries I employ VBA to allow me to browse the objects and get the values for constants etc. I just add the relevant reference in the VBA project and boom. Then in my Extra! BAsic macro I just dim everything as a generic Object and replace and constants used in the code to the value of the constant as retrieved from VBA.

e.g. Here is a function to write to file, it will create the file it it doesn't exist and will append to file if it does exist.

Declare Function myWriteToFile(TempFile as String, Overwrite as Integer, myText as String) as Integer

Sub Main
'Extra! objects
Dim mySystem as Object, mySession as Object, myScreen as Object

'File related variables
Dim Overwrite as Integer, TempFile as String, retC as Integer

'Create the Extra! objects
Set mySystem = CreateObject("EXTRA.System")
Set mySession = mySystem.ActiveSession
Set myScreen = mySession.Screen

'*** get the string we want to write to file
'Get the screen into a string
myScreenText = ""
i = 1
For i = 1 to 24
myScreenText = MyScreenText & myScreen.GetString (i,1,80) & Chr$(13) & Chr$(10)
Next i

'*** Get this string to disk !!!
'Set tempFile name
TempFile = "c:\\temp\\HelloWorld.David"
'Overwite my file if is exists
Overwrite = 0

retC = myWriteToFile(TempFile, Overwrite, myScreenText)

'*** Check the Return Code
If retC = 1 then
Msgbox "File Created"
ElseIf retC = 2 then
Msgbox "Text appended to existing file"
Else
Msgbox "Text not saved to file"
End If
End Sub

Function myWriteToFile(TempFile as String, Overwrite as Integer, myText as String) as Integer
'Create File related objects
Dim myFSO as Object, myFile as Object

'Create the FileSystemObject object
Set myFSO = CreateObject("Scripting.FileSystemObject")

'Check if file does not exist or we want to overwrite
If (myFSO.FileExists(TempFile) = 0 or Overwrite = -1) then
Set myFile = myFSO.CreateTextFile(TempFile)

'Write the screen to file
myFile.WriteLine myText
myFile.Close
myWriteToFile = 1
'If files exist and Overwrite is 0, then append
ElseIf (myFSO.FileExists(TempFile) = -1 and Overwrite = 0) then
Set myFile = myFSO.OpenTextFile(TempFile, 8, True, 0)
myFile.WriteLine myText
myWriteToFile = 2
Else
myWriteToFile = 0
End If
End Function


Note: The above will add a blank line between writes, if you don't want the blank file, then use myFile.Write mystring, and you can control the trailing CRFL while you build the string you want to write to file.

Using an array to store the file data is IMHO a bad idea, populating the array and parsing the array is expensive. How will you know the size of the array starting off, if you have to redim preserve it then it becomes very expensive. If you are writing to disk in a loop while indexing through the array then it's even more expensive. 

Here is a screenshot of the FSO object methods, as you can see, almost all one-line calls, so little point in creating a function to handle everything, because if just adds to volume of code you have to maintain.

         

Another thing to watch out for when using external objects is the variable types, e.g. Extra! Basic doesn't do Boolean, so just declare as integer. In general -1 == true and 0 == false, however at one point Windows was returning true as 1, so to be on the safe side if you encounter a Boolean, check if it's 0, if it is not then it's true !! :-)
Similar with TextStream, I just using String, I think the max length for a string is 65K bytes, so if you are reading or writing anything longer you may be out of luck.

If you do go this route, you will likely need a second function myReadFile, so you can check if it exists and return the contents as a string.

Hi David, 

Not wanting to come across the wrong way here, but I don't like that idea at all.

If I was in your shoes I would look to perform your file operations using the Microsoft.Scripting.Runtime library's FileSystemObject object. That should allow you to perform most of the various operations in one line of code. Writing to file may take some extra effort.

Unfortunately as ebedit.exe doesn't have any usable intelisense or object browser, normally when I'm looking to use COM/OLE objects from other libraries I employ VBA to allow me to browse the objects and get the values for constants etc. I just add the relevant reference in the VBA project and boom. Then in my Extra! BAsic macro I just dim everything as a generic Object and replace and constants used in the code to the value of the constant as retrieved from VBA.

e.g. Here is a function to write to file, it will create the file it it doesn't exist and will append to file if it does exist.

Declare Function myWriteToFile(TempFile as String, Overwrite as Integer, myText as String) as Integer

Sub Main
'Extra! objects
Dim mySystem as Object, mySession as Object, myScreen as Object

'File related variables
Dim Overwrite as Integer, TempFile as String, retC as Integer

'Create the Extra! objects
Set mySystem = CreateObject("EXTRA.System")
Set mySession = mySystem.ActiveSession
Set myScreen = mySession.Screen

'*** get the string we want to write to file
'Get the screen into a string
myScreenText = ""
i = 1
For i = 1 to 24
myScreenText = MyScreenText & myScreen.GetString (i,1,80) & Chr$(13) & Chr$(10)
Next i

'*** Get this string to disk !!!
'Set tempFile name
TempFile = "c:\\temp\\HelloWorld.David"
'Overwite my file if is exists
Overwrite = 0

retC = myWriteToFile(TempFile, Overwrite, myScreenText)

'*** Check the Return Code
If retC = 1 then
Msgbox "File Created"
ElseIf retC = 2 then
Msgbox "Text appended to existing file"
Else
Msgbox "Text not saved to file"
End If
End Sub

Function myWriteToFile(TempFile as String, Overwrite as Integer, myText as String) as Integer
'Create File related objects
Dim myFSO as Object, myFile as Object

'Create the FileSystemObject object
Set myFSO = CreateObject("Scripting.FileSystemObject")

'Check if file does not exist or we want to overwrite
If (myFSO.FileExists(TempFile) = 0 or Overwrite = -1) then
Set myFile = myFSO.CreateTextFile(TempFile)

'Write the screen to file
myFile.WriteLine myText
myFile.Close
myWriteToFile = 1
'If files exist and Overwrite is 0, then append
ElseIf (myFSO.FileExists(TempFile) = -1 and Overwrite = 0) then
Set myFile = myFSO.OpenTextFile(TempFile, 8, True, 0)
myFile.WriteLine myText
myWriteToFile = 2
Else
myWriteToFile = 0
End If
End Function


Note: The above will add a blank line between writes, if you don't want the blank file, then use myFile.Write mystring, and you can control the trailing CRFL while you build the string you want to write to file.

Using an array to store the file data is IMHO a bad idea, populating the array and parsing the array is expensive. How will you know the size of the array starting off, if you have to redim preserve it then it becomes very expensive. If you are writing to disk in a loop while indexing through the array then it's even more expensive. 

Here is a screenshot of the FSO object methods, as you can see, almost all one-line calls, so little point in creating a function to handle everything, because if just adds to volume of code you have to maintain.

         

Another thing to watch out for when using external objects is the variable types, e.g. Extra! Basic doesn't do Boolean, so just declare as integer. In general -1 == true and 0 == false, however at one point Windows was returning true as 1, so to be on the safe side if you encounter a Boolean, check if it's 0, if it is not then it's true !! :-)
Similar with TextStream, I just using String, I think the max length for a string is 65K bytes, so if you are reading or writing anything longer you may be out of luck.

If you do go this route, you will likely need a second function myReadFile, so you can check if it exists and return the contents as a string.

Sorry for my slow reply I'm back to working doubles again due to a shortage of foremen, this was extremely helpful and I'm back at re-coding all my file operations. Since I don't have an IDE with decent intelisense, I just ordered myself a copy of   "VB & VBA in a Nutshell: The Language" from O’Reilly books.  Are there any other books you would recommend?  Later tonight I'm going to post a different question about hotspots that I believe is specific to Extra X-treme.  Thank you again, I greatly apricate the directions you have pointed me. 


Sorry for my slow reply I'm back to working doubles again due to a shortage of foremen, this was extremely helpful and I'm back at re-coding all my file operations. Since I don't have an IDE with decent intelisense, I just ordered myself a copy of   "VB & VBA in a Nutshell: The Language" from O’Reilly books.  Are there any other books you would recommend?  Later tonight I'm going to post a different question about hotspots that I believe is specific to Extra X-treme.  Thank you again, I greatly apricate the directions you have pointed me. 

Hi David, 

in terms of intelisense, you could use VB6 or a newer Visual Studio.

As for books, invariably if I can't copy and paste it, it sounds like a lot of work :-)..

e.g. searching on Google for
               VBA File object  
       gives several relevant results.

Tom