How To Read and Write Text Files

The example objects and the text file can be downloaded here.

For data handling in GDL, it can be useful to store and use data from an external text file by using the GDL Text I/O Add-On. This method provides access to data tables with predefined values.

This post explains the following workflows:

  • reading the rows of an external text file dynamically (using only the User Interface script)
  • adding new custom rows to the text file (using only the User Interface script, or a combination of User Interface and Parameter Script)

The text file used for the examples contains the following data:

CODE DESCRIPTION HEIGHT(cm) WIDTH(cm) DEPTH(cm) WEIGHT(kg) Cube (m3)
PEM001 3 Drawer Locker 69.5 39.5 41.5 18.5 0.1
PEM002 4 Drawer Locker 88.5 39.5 41.5 23.5 0.1
PEM003 5 Drawer Locker 107.5 39.5 41.5 29 0.2
PEM004 Door Locker 69.5 39.5 41.5 17 0.1
PEM005 2 Drawer Locker 50.5 39.5 41.5 13.5 0.1
PEM008 4 Drawer Midi Chest 88.5 58 41.5 26 0.2
PEM010 3 Drawer Chest 69.5 76.5 41.5 27.5 0.2

Read data from Text file

In the following example a popup list with text will be created to choose the Drawer of the data table by its name. On the User Interface the header of the data table is displayed in outfields with the attributes of the chosen Drawer, read from the data table:

HowToRWTextFiles_PopupUI

The name of the external text file used for this example is “inputText.txt” and it needs to be loaded with the active libraries. The data columns are separated by tabulators, therefore the file opening command will be the following:

_nameChannel = open("text", "inputText.txt", "separator='\t', mode=ro, Library")

The "stDrawerType" string parameter is used for the Drawer selection. The value list of this parameter is given in the User Interface script by the ui_custom_popup_infield command. The possible Drawer Types are stored in the _stDrawerTypes array.

The rows of the data table are handled dynamically, and the success of reading the Drawer Type Name is always checked: the loop stops after the last row.
However, the loop will not break at an unsuccessful row reading immediately, so to avoid the duplicated appearance of the last Drawer Type, the success of the input command has to be checked before adding the next Drawer Type to the _stDrawerTypes array.

The _name variable is used for storing the actual Drawer Type for each rows while reading the text file. Only if the actual _name and the parameter value of stDrawerType are matching, will the other data in the row be read. For the Code and Drawer Type of the chosen value the _code and _desc string variables are used, the numerical values are stored in the sizes[] array.

! ------------------------------------------------------------------------------
! Input parameters controlled by the user:
! ------------------------------------------------------------------------------
! stDrawerType 		- (String) The Drawer Type in the second column 
! 	 	 	 	   of the data table

! Initialization
dim _stDrawerTypes[]
	_stDrawerTypes[1] = ""

dim _sizes[5]
	for _i = 1 to 5
		_sizes[_i] = 0
	next _i

_iLine 		= 2
_name 		= ""
_code 		= ""
_desc 		= ""

do
	! Start reading data from the second column, read that one data
	_nRetValues = input(_nameChannel, _iLine, 2, _name) 

	if _nRetValues > 0 then
		_stDrawerTypes[_iLine - 1] = _name
		_iLine = _iLine + 1
	endif

	if stDrawerType = _name then
		! Start reading data from the first column, read all data in the row
		n = input(_nameChannel, _iLine - 1, 1, _code, _desc, _sizes[1],
			_sizes[2], _sizes[3], _sizes[4], _sizes[5])
	endif

while _nRetValues > 0

yCurrent 	= 10
dy		= 24

ui_outfield "Select Drawer Type:", 2, yCurrent, 120, 15
ui_custom_popup_infield "stDrawerType", 125, yCurrent - 4, 150, 19,
	0, 0, 1, "", _stDrawerTypes

yCurrent = yCurrent + dy

The column header strings are stored in the _stDescription array to display as outfield strings on the User Interface (as descriptions to the data of the selected Drawer). After reading the column header strings the file handling channel should be closed:

! Initialization
dim _stDescription[7]
	for _i = 1 to 7
		_stDescription[_i] = ""
	next _i

n = input(_nameChannel, 1, 1, _stDescription[1], _stDescription[2], _stDescription[3],
	_stDescription[4], _stDescription[5], _stDescription[6], _stDescription[7])

close _nameChannel

Finally, all data are displayed dynamically by outfields: the column header descriptions and the data of the selected Drawer Type. The numerical values are converted to strings for the outfields with the STR function with hidden 0 decimals and no conversion calculation (the conversion specifier is meter):

for _i = 1 to 7
	ui_outfield _stDescription[_i], 2, yCurrent, 120, 15
	yCurrent = yCurrent + dy
next _i

yCurrent = 34
ui_outfield _code, 125, yCurrent, 120, 15
yCurrent = yCurrent + dy

ui_outfield _desc, 125, yCurrent, 120, 15
yCurrent = yCurrent + dy

for _i = 1 to 5
	ui_outfield str("%~m", _sizes[_i]), 125, yCurrent, 120, 15
	yCurrent = yCurrent + dy
next _i

Write data to Text file

In the example file a Create Custom Row checkbox is added to switch between reading or writing function. After setting a custom row and turning the checkbox OFF, the new type appears in the selectable Drawer Types.
HowToRWTextFiles_AddRow

String parameters are used for storing the user defined values which are displayed with outfields on the User Interface:

! ------------------------------------------------------------------------------
! Input parameters controlled by the user:
! ------------------------------------------------------------------------------
! stCode 	- (String) Value of the first column in the text file
! stDesc 	- (String) Value of the second column in the text file
! stHeight 	- (String) Value of the third column in the text file
! stWidth 	- (String) Value of the fourth column in the text file
! stDepth 	- (String) Value of the fifth column in the text file
! stWeight 	- (String) Value of the sixth column in the text file
! stCube 	- (String) Value of the seventh column in the text file

yCurrent = 10
dy		 = 24
ui_outfield "Code: ", 2, yCurrent, 120, 15
ui_infield "stCode", 125, yCurrent - 4, 120, 19
yCurrent = yCurrent + dy

ui_outfield "Description: ", 2, yCurrent, 120, 15
ui_infield "stDesc", 125, yCurrent - 4, 120, 19
yCurrent = yCurrent + dy

ui_outfield "Height (cm): ", 2, yCurrent, 120, 15
ui_infield "stHeight", 125, yCurrent - 4, 120, 19
yCurrent = yCurrent + dy

ui_outfield "Width (cm): ", 2, yCurrent, 120, 15
ui_infield "stWidth", 125, yCurrent - 4, 120, 19
yCurrent = yCurrent + dy

ui_outfield "Depth (cm): ", 2, yCurrent, 120, 15
ui_infield "stDepth", 125, yCurrent - 4, 120, 19
yCurrent = yCurrent + dy

ui_outfield "Weight (kg): ", 2, yCurrent, 120, 15
ui_infield "stWeight", 125, yCurrent - 4, 120, 19
yCurrent = yCurrent + dy

ui_outfield "Cube (m3): ", 2, yCurrent, 120, 15
ui_infield "stCube", 125, yCurrent - 4, 120, 19
yCurrent = yCurrent + dy

To set the action of adding a new line, you have 2 options:

  • a combination of 3 things:
    • User Interface script: function buttons (Append and Reset), input parameters
    • Parameter script: function button follow-up scripts, text channel open, append, close section
    • Run Parameter Script only Once” function of Deatils/Compatibility Options. This way the Parameter script runs exactly once, avoiding the new data line to be added multiple times (without this setting, the Parameter script may run more than once)
  • a combination of 2 things:
    • User Interface script: “bAddRow” boolean button, input parameters, text channel open, append, close section
    • Parameter script: reset option for “bAddRow” boolean

With the output command the user defined values can be added to the text file.
The file opening command only differs from reading by the mode: to add a new row the WA (write only, append at the end of the file) mode should be used.
The recordID should be 1 in order to add the data in a new row.
Note: the text file should end with an empty row.
Example 1
(with Parameter script running exactly once, optional constant variables are inicialized for button IDs in Master script):

! UI script
ui_button ui_function, "Append", 2, yCurrent - 4, 200, 19, BUTTON_ID_APPEND
yCurrent = yCurrent + dy
ui_button ui_function, "Append and Reset Fields", 2, yCurrent - 4, 200, 19, BUTTON_ID_APPEND_AND_RESET

! Parameter script
! append line to the end of the textfile
! use only if "Run Parameter Script only Once" is set in Details/Compatibility Options

if GLOB_UI_BUTTON_ID = BUTTON_ID_APPEND | GLOB_UI_BUTTON_ID = BUTTON_ID_APPEND_AND_RESET then

	_nameChannel = open("text", "inputText.txt", "separator='\t', mode=wa, Library")

	output _nameChannel, 1, 0, stCode, stDesc, stHeight, stWidth, stDepth, stWeight, stCube

	close _nameChannel
endif

Example 2

! UI script
ui_infield{3} "bAddRow", 2, yCurrent - 4, 150, 19,
	5, "", 0, 0, 
	0, 0, 0, 0, 
	"", "Append Custom Row", 0,
	"", "Append Custom Row", 1

yCurrent = yCurrent + dy

! Adding file data

if bAddRow then

	_nameChannel = open("text", "inputText.txt", "separator='\t', mode=wa, Library")

	output _nameChannel, 1, 0, stCode, stDesc, stHeight, stWidth, stDepth, stWeight, stCube

	close _nameChannel
endif

! Parameter script
! reset Append boolean if leaving page
if GLOB_MODPAR_NAME = "bCreateCustom" then
	if bAddRow = 1 then
		bAddRow = 0
		parameters bAddRow = bAddRow
	endif
endif