dBASE PLUS
Exontrol.COM Software - Frequently Asked Questions
DBS.0:
In dBase you can use any of the following versions:
  • /COM indicates the 32-bit edition of the ActiveX version

The application built using /COM version runs on any Windows 32 or 64-bit machine.

DBS.1:
Each of our component comes with the eXHelper tool that helps you to generate source code for different HOW-TO questions. Usually, the tool goes to C:\Program Files\Exontrol\<COMPONENT> folder, with the name ExHelper.
  • Run the eXHelper tool
  • If case, select the component from the upper-left field. By default, the component from the folder you run the tool, is loaded. 
  • Select a question, and double click it
  • The Middle/Template panel will show you the x-script code, while the Right/Running Panel will show the component after running the x-script code
  • Right-Click Middle/Template panel, and select the Convert To ...
  • Choose the dBASE Plus, and the Middle/Template displays the dBASE Plus source code, which you can copy and paste to your form's code
Here's a few movie on how to:
  • Generating Source Code using the eXHelper tool
  • Spying objects of the browsed component using the eXHelper tool

The following screen shot shows the eXHelper tool with main parts:

DBS.2:
The most probably this is happen because in some cases dBASE Plus is not firing any error if a property/method is missing in the component/object.

Due limitation of dBASE Plus language, please consider the following:

  1. a control's property-set with one or more parameters may not work as expected. 

    For instance, Background(exSplitBar) property changes the visual appearance of the control's vertical split bar, so  the code

    oG2antt.Background(18) = 0x1
    should be translated to

    oG2antt.Template = [Background(18) = 0x1]

    For instance, Chart.PaneWidth(Right) property Specifies the width for the left or side pane, so the code

    oG2antt.Chart.PaneWidth(true) = 256
    should be translated to

    oG2antt.Template = [Chart.PaneWidth(true) = 256]

    In other words, you can use the Template / TemplatePut / TemplateDef property to call or change any control's property with one or more parameters.

  2. any object's property-set with one or more parameters may not work as expected. 
  3. For instance, Position property changes changes the column's position, so  the code

    oG2antt.Columns.Add("Default").Position = 0

    should be translated to

    local aColumn
    aColumn = oG2antt.Columns.Add("Default")
    aColumn.Position = 0

    or

    var_Column = oG2antt.Columns.Add("Default")
    with (oG2antt)
    	TemplateDef = [dim var_Column]
    	TemplateDef = var_Column
    	Template = [var_Column.Position = 0]
    endwith
    

    For instance, Def(exCellBackColor) property changes default value for all cells in the column, so  the code

    oG2antt.Columns.Add("Default").Def(4) = 15790320
    should be translated to

    var_Column = oG2antt.Columns.Add("Default")
    with (oG2antt)
    	TemplateDef = [dim var_Column]
    	TemplateDef = var_Column
    	Template = [var_Column.Def(4) = 15790320]
    endwith

    In other words, you can use the Template / TemplatePut / TemplateDef property to call or change any control's property with one or more parameters.

  4. any property-get with one or more parameters should be stored as local variable.
  5.  For instance, Color property changes the visual appearance of the specified bar, so  the code

    oG2antt.Chart.Bars.Item("Task").Color = 0xff

    should be translated to

    local oBar
    oBar = oG2antt.Chart.Bars.Item("Task")
    oBar.Color = 0xff
    

    In other words, you can use the Template / TemplatePut / TemplateDef property to call or change any control's property with one or more parameters.

  6. during an event, no other event can occur.

    For instance, Timer property occurs every specified interval, so during the event no other events can be fired. For instance, you change the layer's Value property which should invoke the Change event, but it won't be called. In order to prevent that you have to call directly the event's handler as follow.

    Let's say that the Timer's event shows as:

    function nativeObject_Timer(TickCount)
    	oGauge = form.EXGAUGEACTIVEXCONTROL1.nativeObject
    	oGauge.Value = oGauge.FormatABC("value + 1/24/60/60",oGauge.Value)
    return
    

    we need to call the Change handler directly such as:

    function nativeObject_Timer(TickCount)
    	oGauge = form.EXGAUGEACTIVEXCONTROL1.nativeObject
    	oGauge.Value = oGauge.FormatABC("value + 1/24/60/60",oGauge.Value)
    	class::nativeObject_Change(0)
    return
    

    where the nativeObject_Change event may looks as:

    function nativeObject_Change(Layer)
    	oGauge = form.EXGAUGEACTIVEXCONTROL1.nativeObject
    	local var_Layer
    	var_Layer = oGauge.Layers.Item("sec")
    		var_Layer.Value = oGauge.Value
    	var_Layer = oGauge.Layers.Item("min")
    		var_Layer.Value = oGauge.Value
    	var_Layer = oGauge.Layers.Item("sec")
    		var_Layer.Value = oGauge.Value
      return

In case you are using an older version of the component, the TemplateDef and TemplatePut may be missing, so please check the following. 

Let's say we have the following dBASE Plus source code for the eXGrid component as follows:

oGrid = form.EXGRIDACTIVEXCONTROL1.nativeObject
oGrid.LinesAtRoot = -1
var_Column = oGrid.Columns.Add("P1")
	// var_Column.Def(0) = true
	with (oGrid)
		TemplateDef = [Dim var_Column]
		TemplateDef = var_Column
		Template = [var_Column.Def(0) = true]
	endwith
	var_Column.PartialCheck = true

var_Items = oGrid.Items
	h = var_Items.AddItem("Root")
	var_Items.InsertItem(h,null,"Child 1")
	var_Items.InsertItem(h,null,"Child 2")
	// var_Items.ExpandItem(h) = true
	with (oGrid)
		TemplateDef = [Dim var_Items,h]
		TemplateDef = var_Items
		TemplateDef = h
		Template = [var_Items.ExpandItem(h) = true]
	endwith

The code adds two columns, with partial-check feature, and two items, so the code is compiled fine, but at runtime, the partial check will not shown, as it shows in the eXHelper tool

In this case, the missing property is TemplateDef, and dBASE is not firing any exception as it is missing. This is mostly happen because you are using an older version of the component that provides no TemplateDef property. Newer versions provides Template, TemplateDef, TemplatePut and ExecuteTemplate methods.

For instance, here's how you can find out if the component you have installed, has the TemplateDef property:

  • Run the eXHelper tool
  • If case, select the component from the upper-left field. By default, the component from the folder you run the tool, is loaded. 
  • In the Middle/Template panel, remove all text, and paste the following code:
    TemplateDef = "BackColor = 0"
  • Press the CTRL + R, to execute the code, or waits longer
  • If no error occurs, it means that your component provides implementation for TemplateDef property
  • If an error occurs, it means that the control provides no implementation for TemplateDef property as you can see it bellow:
DBS.3:
Unfortunately, dBASE Plus can not handle properties or methods with multiple parameters. In other words, once a property or method with parameters returns an object, after that no property / method of returned object will be known. 

For instance the following code, adds a new hidden column:

oGrid.Columns.Add("Hidden").Visible = false

it is compiled just fine, but the result is not what we expect. The column is shown, as it should be hidden ( Visible = False )

Instead we can use any of the following samples:

oGrid.Template = [Columns.Add("Hidden").Visible = False]

or

var_Column = oGrid.Columns.Add("Hidden")
with (oGrid)
	TemplateDef = [Dim c]
	TemplateDef = var_Column
	Template = [c.Visible = false]
endwith

and the result is what we want, a new hidden column. 

Fortunately, we have the solution for this, as our controls support TemplateDef, Template and ExecuteTemplate properties, which helps you to call any of the control's property/method with or without parameters using our x-script code, that's built to be easy to use. 

Most of our components provides the following properties:

  • TemplateDef property, define the variables to be used in the next Template or ExecuteTemplate call. The first call of TemplateDef property should be "dim <variables>" where <variables> defines the n-variables ( separated by comma character ) to be used in the next call of Template or ExecuteTemplate property. The next n-calls of TemplateDef property defines the variable one by one as you listed in the first call of TemplateDef . For instance TemplateDef = "dim a,b"; TemplateDef = 255; TemplateDef = "default", defines two variables named a with the value 255 and b with the value as string "default"so a and b variables are known for next Template / ExecuteTemplate calls. For instance, if next you call Template = "Columns.Add(b).Def(7) = a" adds a new column with the caption "default", and it's header background color (Column.Def(7) property) to Red ( 255 ).
  • Template property, executes the x-script code. For instance, Template = [Columns{Add("Column 1"){DisplayFilterButton = True};Add("Column 2"){DisplayFilterButton = True}}], adds two columns, each with the DisplayFilterButton property set on True. 
  • ExecuteTemplate property, executes the code, and returns the result. For instance, ? ExecuteTemplate("Columns.Count()"), executes the Columns.Count() x-script, and gets the result, in this case gets the number of columns.

Any of these properties accept x-script code, which is a simple way of calling control/object's properties, methods/events using strings. Exontrol owns the x-script implementation in its easiest way and it does not require any VB, ... engine to get executed. The eXHelper tool uses x-script and provides tons of how-to questions that can be converted to your programming languages. The same way the entire Template/x-script code from the eXHelper can be copied to a single line and pass it to the control's Template property like in the following sample:

  • Run the eXHelper tool
  • Select any question in the left panel, and double-click it or press CTRL + S, so the right/running panel, shows the changes in the control
  • Right-Click the Middle/Template panel, and select "Copy To Single Line"
  • The eXHelper is minimized, and your clipboard contains the entire Template/x-script code, which you can paste to any Template call as shown in the next sample:

For instance, insert the eXGrid to a form, and paste the following code ( which uses Template property only ):

function form_onOpen()
local oGrid
oGrid = form.EXGRIDACTIVEXCONTROL1.nativeObject
oGrid.Template =
[BeginUpdate();Dim rs;Appearance = 0;ColumnAutoResize = False;rs = CreateObject(`ADOR.Recordset`);{;Open(`Orders`,`Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Program Files\Exontrol\ExGrid\Sample\SAMPLE.MDB`, 3, 3 );};DataSource = rs;SortBarVisible = True;SortBarCaption = `Drag a <b>column</b> header here to group by that column.`;AllowGroupBy = True;Columns(0).Width = 96;Layout = `multiplesort="C1:2 C5:1";singlesort=C0:1`;BackColorSortBar = RGB(240,240,240);EndUpdate()]
return

and you should get a picture like follows:

Still, we do NOT recommend using long strings for Template properties, as it is hard to follow, in case something is not working as it should.

DBS.4:
The following code shows how you can enumerate the rowset and add data to eXGrid component:
local oGrid, oQuery,  cTemplate,  nCol, cFieldName, numCols, xValue
oGrid = form.EXGRIDACTIVEXCONTROL1.nativeObject
oQuery=form.query1.rowset
cTemplate=""
numCols=oQuery.fields.size
oGrid.beginUpdate()
    oGrid.template=[items.removeAllItems()]
    //Default Columns & Define Keys
    For i=1 To numCols
        cFieldName=oQuery.fields[i].fieldname.toLowerCase()
        cTemplate += [columns.add("] + cFieldName + [").key="] + cFieldName + [";]
    Next      
    oGrid.template=cTemplate
    //Rows
    oGrid.templateDef=[Dim h;]
    cTemplate=""
    nCol=0
    oQuery.first()                                                    
    Do while not oQuery.endOfSet 
        xValue=oQuery.fields[1].value
        cTemplate += [h=items.addItem("] + xValue  + ["); ]                       
        For i=2 To numCols
            xValue=oQuery.fields[i].value
            nCol = i - 1                                                                                           
            cTemplate += [items.cellValue(h,] + nCol + [)="] + xValue + ["; ]                                                                
        Next
        oQuery.next()
    Enddo                                                   
    oGrid.template=cTemplate
oGrid.endUpdate()
Thanks to Omer Ntumba, who shared the note.
DBS.5:
Get a Specific Table Field Value on the current item selected ? [Using the FieldName, and assuming that the Column key attribute has been set to it.] Of course, It can still be achieved using the column index (?columns.item(2)), the maintenance of this type of coding can be time consuming if the grid structure changes.
local oGrid, cFieldName, nCurItem, nColIndex, cFieldValue, cStr
oGrid = form.EXGRIDACTIVEXCONTROL1.nativeObject
cFieldName=?employeID?
nCurItem=oGrid.ExecuteTemplate("items.selectedItem()")
cFieldName=cFieldName.leftTrim().rightTrim().toLowerCase()
cStr=[columns.item("] + cFieldName + [").index]              
nColIndex=oGrid.ExecuteTemplate(cStr)  //Get the column Index based on the fieldname (previously set as a key)
cStr=[items.cellValue(] + nCurItem + [,] + nColIndex + [)]
cFieldValue=oGrid.ExecuteTemplate(cStr)

This can be built as function with FieldName as parameter and can be called whenever necessary.

Thanks to Omer Ntumba, who shared the note.
DBS.6:
The most probably, dBASE Plus generates the following error:

Expression expected

when trying to compile a line with a missing parameter.

For instance the following code:

oGrid.Items.InsertItem(,,"Node")

generates this error, while correct it should be:

oGrid.Items.InsertItem(null,null,"Node")
Replace any missing arguments with null variable.
DBS.7:
dBASE Plus generates the following error:

ActiveX control is not licensed for this machine.

when trying to insert the control to a form. 

The most probably this is happen because dBASE PLUS is not able to handle runtime-licensed controls ( IClassFactory2 ). 

If this error is happening with any controls you purchased from us, please contact us ASAP and provide the following information:

  • Company
  • Address
  • City
  • Country

Based on the information you provide we will build and send you a new update that includes the runtime-less version of the component, that can be used on your dBASE PLUS environment, free of charge. The new update includes the information you provided in the License page of the DLL, as you can see bellow:

DBS.8:
Generally, all events are fired as they were designed. Sometime, it may be possible that during an event other events to be invoked. Due limitation of dBASE Plus language, during an event, no other event can occur.

Please follow the next steps to add a Event notification, that occurs every internal event that the control fires:

  • Select the component in design mode, and select the nativeObject from the Inspector
  • Choose the Events page
  • Locate and select the item named Event, and add a handler for it

Adds the code:

function nativeObject_Event(EventID)
	?form.EXG2ANTTCHARTACTIVEXCONTROL1.nativeObject.EventParam(-2)
return

Save and Run the project. This code uses the Event and EventParam to display information about events the control fires.

Once you make changes into the control, the Command panel will display information like follows:

AddColumn/7( [Object] )
AddColumn/7( [Object] )
AddColumn/7( [Object] )
DateChange/50
FocusChanged/109
Change/103( 231755208 , 0 , ='Item 1' )
AddItem/1( 231755208 )
Change/103( 231754368 , 0 , ='Item 2' )
AddItem/1( 231754368 )
Change/103( 231755808 , 0 , ='Item 3' )
AddItem/1( 231755808 )
LayoutChanged/19

For instance, Timer property occurs every specified interval, so during the event no other events can be fired. For instance, you change the layer's Value property which should invoke the Change event, but it won't be called. In order to prevent that you have to call directly the event's handler as follow.

Let's say that the Timer's event shows as:

function nativeObject_Timer(TickCount)
	oGauge = form.EXGAUGEACTIVEXCONTROL1.nativeObject
	oGauge.Value = oGauge.FormatABC("value + 1/24/60/60",oGauge.Value)
return

we need to call the Change handler directly such as:

function nativeObject_Timer(TickCount)
	oGauge = form.EXGAUGEACTIVEXCONTROL1.nativeObject
	oGauge.Value = oGauge.FormatABC("value + 1/24/60/60",oGauge.Value)
	class::nativeObject_Change(0)
return

where the nativeObject_Change event may looks as:

function nativeObject_Change(Layer)
	oGauge = form.EXGAUGEACTIVEXCONTROL1.nativeObject
	local var_Layer
	var_Layer = oGauge.Layers.Item("sec")
		var_Layer.Value = oGauge.Value
	var_Layer = oGauge.Layers.Item("min")
		var_Layer.Value = oGauge.Value
	var_Layer = oGauge.Layers.Item("sec")
		var_Layer.Value = oGauge.Value
  return
DBS.9:
When you are trying to run any of installed samples, you may encounter the Access Denied error. This is happening because you do not have read-write access to that folder / files.

In order to prevent that you can do any of the following:

  • Run the dBASE Plus application as an Administrator
  • Copy / Move the samples to another folder when you have read-write access. 
This error occurs for any program, it is not related to the component or to the environment itself.