Access ELF Documentation Access ELF Tutorials Access ELF On-Line Help Access ELF Downloadable Help File Access ELF FAQ VB ELF Documentation VB ELF Tutorials VB ELF On-Line Help VB ELF Downloadable Help File VB ELF FAQ
Configuration & Licensing Options
Critical Opinions
Our Users Talk Back






VB ELF Compatibility Enhancements


This page contains information about the Access ELF 2002 4.0 release (April 2002). Specifically, this details the changes which originated in the version 2.1 upgrade to VB ELF (November 1999), which are now incorporated into Access ELF. It also documents subsequent changes to the script methods and properties made for the release of Access ELF 2002 (XP).

Bug Fixes:


1) [Sort Key] field in the Phrases table now functions correctly. The [Sort Key] determines the order in which (string) phrase substitutions are applied. String phrase substitutions are also called "context-sensitive" substitutions in the Help Text; these are the class of phrase substitutions whose [When I Type] column-entry (also called the "trigger") is enclosed in brackets or double-quotes.

Note however that it is also permissable to use string substitutions for simple string replacements which don't require context-sensitivity. For example,
When I Type: [coffee bean]    I Really Mean: coffee
This example use no context. It simply replaces the string "coffee bean" with the string "coffee" in all cases.

The [Sort Key] field is used to control the order of occurrence of these string substitutions. In contrast, phrase definitions which do not have their trigger enclosed in brackets or quotes are performed AFTER all string substitutions, and always occur in left-to-right order as the triggers appear in the user's question.

One aspect of the use of the [Sort Key] field differs between VB ELF 2.x and Access ELF 4.0. In VB ELF it was possible to use this field to specify particular views for which the substitution should not apply. This was necessary because Phrase lists were associated with databases, not Views; and there can be several Views for a particular database. This has changed in Access ELF 4.0 -- Phrase lists are now associated with a specific View. This means that there is no longer any need to use the [Sort Key] field in this way, since the Phrase list is always applied to one and only one View. Note that the new system does mean that Phrase substitutions which are common to different Views of the same database must be entered independently for each View. If this is a problem, see [TO COME] Sharing Phrases between Views.

For completeness, here is the documentation of this obsolete feature:

***********************************************************************************
One additional feature has been added to the [Sort Key] field. Prior to this release it was not possible to specify that phrase substitutions were to apply to specific Views. Entries in the Phrase table were applied to all Views created for any given database. With the advent of scripted View selection, it's more likely that a given phrase substitution will be designed for use with a particular View, and invalid for another View. To address this problem, we adopt the convention that any Phrase table entry with a sort key containing !ViewName will not be applied in the corresponding View. Notice that this does not affect your ability to use the Sort Key field for positioning (for the views to which it does apply), since !Viewname can be preceded by any alphabetic sequence.

For example, if we wish to have the above string substitution apply to all views except the INVENTORY view, then we could write:
When I Type: [coffee bean]    I Really Mean: coffee     Sort Key: !Inventory

If it was necessary to position the substitution in relation to another string replacement, we might use a sort key of "Z !Inventory" (delays the replacement) or "A !Inventory" (advances the replacement).

This functionality is a "work-around" which will be addressed in a more general way in future releases. Currently, adding !ViewName to a Sort Key affects ONLY string phrase substitutions (it does not apply if the trigger is not enclosed in brackets or double-quotes).
***********************************************************************************


2) Names of fields used in data-aware context-sensitive phrase triggers are now case-insensitive. Example:
When I Type: [{Category} product]    I Really Mean: {1}
This substitution will now work correctly whether the field is named Category or CATEGORY. Its effect, in the Northwind database, would be to change: "Show me the dairy products" into "Show me the dairy". This is because "dairy" is an entry in the Category field. (Notice also that the string replacement algorithm matches "product" to the pluralized form "products"; so in this sense it is not a "strict" string replacement.)

An enhancement to the data-aware replacement algorithm in v4.0 now permits contextless markers. Prior to version 2.1, only triggers of the form
When I Type: [{Category} product]    or
When I Type: [product {Category}]
were permitted; in other words, something had to appear before or after the {FieldName} marker. Beginning with v4.0, it is permissible to write:

When I Type: [{Category}]
by itself.

In the "I Really Mean" field, you can use {1} to represent whatever string was typed by the user and is an element of the Category field of the underlying database. For example, in our Expedia Web demo, we have the following phrase definitions:
When I Type: !notserious
I Really Mean: Is the Pope Catholic?;Get serious, please
When I Type: [{CityName} a city]    I Really Mean: notserious

If a user types: Is Los Angeles a city?, then the question becomes: Is notserious?
"Notserious" is also a trigger. Since it isn't bracketed, it fires AFTER the second one. The initial "!" defines it as a Custom Error definition, and the user sees the above message.

Beginning with v4.0 it is also possible for Phrase Scripts to get access to the data-element which triggered them. For instance
When I Type: [{CityName}]    I Really Mean: -
Sort Key: -    Script Name: PetsByCity

Any question containing the name of a city will be passed to the PetsByCity script. This script has access to the trigger as a global property called PhraseTrigger. The data element is available as a global property called DataTrigger. In this case, the two would have the same value, since there is nothing either before or after the {CityName} trigger. In the preceding example, the PhraseTrigger passed to a script would have the value "Los Angeles a city"; the DataTrigger would have the value "Los Angeles".

Numeric triggers are also available, as the global property NumberTrigger. Numeric triggers are represented in both the [When I Type] and [I Really Mean] fields of the phrase table by the literal {#} and take on the value of any valid numeric expression.

See the section on Scripting (and below) for full documentation of the revised set of global properties available to scripts.


Enhancements:


1) AnswerScripts have been modified to permit their return value to consist not only of a modified SQL expression, but also the name of a pre-existing query within the database. In addition, a global property QueryParms has been added; this allows you to return the name of a parameterized query as the function result of an AnswerScript, while providing any required parameter values in the QueryParms property.

The QueryParms property uses a simple convention: it is a set of paired "ParameterName;Value;" entries. For example, an AnswerScript might return the string "PetFriendlyHotels" which is the name of the following parameterized query:

SELECT HOTELS.HotelName, HOTELS.StreetAddress1, HOTELS.CityName, HOTELS.StateRegionName FROM Amenities INNER JOIN ([Amenity Links] INNER JOIN HOTELS ON [Amenity Links].HotelID = HOTELS.HotelID) ON Amenities.AmenityID = [Amenity Links].AmenityID WHERE (((HOTELS.CityName) Like IIf(Len([CityParm]),[CityParm],"*")) AND ((HOTELS.StateRegionName) Like IIf(Len([StateParm]),[StateParm],"*")) AND ((Amenities.Amenity)="Pets Accepted"));

Prior to returning this value ("PetFriendlyHotels"), the script would be obligated to set the appropriate parameters for the query; for example:
QueryParms = "CityParm;Denver;StateParm;CO"

Access ELF will never set the QueryParms property by itself. It only uses this property to transfer parameters specified within a script into the SQL statement which is the final result of a query. It is also possible to use QueryParms directly with the SQL returned by an AnswerScript; without having a pre-existing query in the database. This might be simpler in some cases than creating the complete SQL statement, since SQL created within scripts might also benefit from the modularity of having replaceable parameters.

Notice that the WHERE clause of the above example is written in such a way that if the parameters are not supplied by the script, the conditions revert to being comparisons to wildcard characters (which always succeed). This will often be a good strategy where the parameters are essentially optional.


2) Custom error messages are no longer restricted to a single row, with an optional header. Prior to version 4.0, custom error messages were a single line. They could be generated in one of two ways -- either by using a !Trigger entry in the phrase table, or using a script to set the QueryResult property to -8 and the ErrorMessage global property to "The Error Message;An Optional Error Header".

An example of the first use would be:
When I Type: !age
I Really Mean: Sorry, inquiries about age are restricted;Invalid query

In general, the technique for the second type of usage was as follows: a ViewScript (or SpellCheckScript) would detect an "illegal" word or phrase in a query. It would then set the PrivateErrorCode property. An AnswerScript would test the value of PrivateErrorCode and in the appropriate cases set the QueryResult and ErrorMessage propertiess; eg.
    QueryResult = -8
    ErrorMessage = "Sorry, inquiries about age are restricted;Invalid query"

Note that developers using ELF to return results via SQL might find it very useful to embed URLs within the ErrorMessage string; for example,
ErrorMessage = "<A HREF='nwdbmap.gif'>Click here;Click below to see tables & relationships"

Beginning with v4.0, the ErrorMessage string can also be a complex object, formatted to enable Access ELF to return arbitrary recordsets based on its literal contents. More simply put, it's now possible to set ErrorMessage to be a list of row values and optional header values. As an example, let's say we set ErrorMessage to the following value:
"({not available;Just a reminder:};{Something else}); ({2nd row 1};{2nd row 2});"

Access ELF would then return a recordset which appeared as:

Just a reminder:     "We regret to say:"
not available          Something else
2nd row 1             2nd row 2

Notice that the formatting convention is to enclose each cell, or field element, within a pair of braces. The first row can also specify the header for the column (also within the braces, and following a semi-colon). If no header is specified, then the default is used. The default custom error header is defined in the Advanced tab of the Settings window.

Rows after the first can specify headers according to the same format, but this information will be ignored (it will not override the headers specified in the initial line).

Among other uses, we expect that this feature will make it easier to customize lists of URLs which can be suggestions to the user for alternate paths, particularly in cases where scripts find that the application is unable to supply the exact information desired. Note that it would also be possible in Internet/Intranet applications to use this feature to present a list of e-mailable addresses, possibly with topics pre-filled, making it easy for the user to reach parties who could provide the specific information desired.


3) The Scripting component, which was introduced in Access ELF version 3.0, has been significantly extended. Scripts now have the following global properties available:

Public Question As Variant
Public Connection As Variant ' VB ELF only, not used in Access ELF
Public UserID As Variant
Public Password As Variant ' will act as Static by Session
' - - -
Public PrivateErrorCode As Integer
Public SQL As Variant
Public QueryResult As Integer
Public ExecutionError As Integer
Public ErrorMessage As Variant
Public SpellCheck As Integer
Public SpellCheckIn As Variant
Public SpellCheckOut As Variant
Public CurrentViewName As Variant ' 6/00
' - - - 10/2001 (Version 4.0) VBELF compatibility additions:
Public Resource As Variant ' general purpose
Public QueryParms As Variant ' parm-name;parm-value; pairs
Public PhraseTrigger As Variant ' to pass triggers into script
Public DataTrigger As Variant ' to pass data-aware triggers into script
Public NumberTrigger As Variant ' same for numeric value in trigger
Public WarningCode As Integer ' to allow elfClass to display "cautions" in
Public WarningString As Variant ' addition to recordset results
' - - - end 10/2001 (Version 4.0) VBELF compatibility additions

' - - - Access XP extensions:
Public Phrase As Variant ' 12/01; to help construct appropriate warning messages via script
Public DataTrigger2 As Variant ' 12/01; to pass a second data-trigger to script
Public PhraseReplacement As Variant ' 1/02; the text which will replace the PhraseTrigger text
Public QuestionReplacement As Variant ' 1/02; full results of any replacement (including inversions)
' - - - end Access XP extensions

' Public Methods
Public Sub SetDirectoryPath(PathSpec)
Public Function OpenView(ViewName) As Integer
Public Sub AddAttribute(Entry, myAttribute, myType)
Public Sub SelectGrammarLayer(Layer%)
Public Function ExecuteSQLCustom(SQL, Optional whichDB)
Public Sub AppendFunction(Func, Tokentype, domain, Domain2, range)
Public Sub AddVerbMapping(DBName, Table1, Field1, Table2, Field2, LinkVerb)
Public Function Evaluate(thisStatement)

This new version corrects many errors in the initial release. First, note that there was some confusion in the prior release concerning the lifetime of these properties. In the current release, this has been simplified.

Only the Password property acts as static, meaning that it holds its value between queries. This property is designed to allow you to query a user once (and only once) for a valid password. Subsequently, you can simply validate that the Password property continues to hold a valid entry.

Each of the other settable properties is reinitialized (either to an empty string or zero) prior to each question, and any script can read or write these values. (This does not apply to the Connection and UserID properties, which should be considered read-only and always provide the same information, namely the current OLE DB connection string (in VB ELF), and the ID of the current user.)

The Resource property has been added as a holder for any information that scripts might need to pass between themselves. For instance, a ViewScript might detect keywords in the question, and use the Resource string to store these keywords for acting on later (in an AnswerScript) depending on the outcome of the translation.

Use of the QueryParms property is described in Enhancement #1 above. It permits AnswerScripts to return either parameterized SQL statements (a), or the names of parameterized stored queries and procedures (b). The QueryParms property must be filled in by an AnswerScript prior to returning either (a) or (b) as its function result. ELF will then use the "ParmName;ParmValue;" pairs designated in the QueryParms string to replace the names of the SQL parameters with the desired values.

PhraseTriggers, DataTriggers, and NumberTriggers have been added to allow greater customizability of PhraseScripts. PhraseScripts now have access -- in addition to the Question property itself (which holds the complete text of the user's question) -- to whatever context-sensitive triggers were involved in the process of triggering the script. The PhraseTrigger property will always contain the full literal text of that part of the question corresponding to the phrase trigger (the [When I Type] part of a phrase definition). The DataTrigger property will only have a value if the trigger was of a "data-aware" form; that is, containing the name of a field (in curly braces). This part of the trigger is matched by any word contained in the underlying database in the respective field. Similarly, NumberTriggers will have value only for phrase definitions which use the {#} format as an elastic placeholder for any valid numeric value.

WarningCode and WarningString have been provided as another means of passing information back from a script to a client application. Its main purpose is to account for those cases when either a valid recordset or a customized error message is being returned, but additional information may be required by the client. For example, a script may determine that it ought to provide a given recordset as a "best effort" -- even though the meaning of the question may not have been clear. In this case, the WarningCode and WarningString properties could be used to display a cautionary footnote about using the resulting information, or advice on how to create a less ambiguous query.

For example, we use these properties in our Northwind Web demo as follows: an AnswerScript detects the presence of the "PIVOT" keyword in any successful SQL translation. If present, the WarningCode is set to 100 and the WarningString property is set to a caption explaining that crosstabs are also available in SQL Server and Oracle interfaces. The Web ASP page simply tests for non-zero WarningCodes and displays the WarningString above the result if detected. Although this isn't strictly a "warning", it illustrates the potential for using the additional channel for any auxiliary information.

Like the QueryParms property, the WarningCode and WarningString properties are never set by the ELF application itself. They are only provided as a conduit for developers to pass information back from within scripts to their own client applications. (The single exception is that the Permit Rewordings and Warn on Rewording options, when both active, can cause Access ELF to generate warning messages. If you clear the Warn on Rewordings box, the previous statement is 100% true. This exception also implies that you should use values other than small integers for your own WarningCodes, in case you need to distinguish them from the small integer WarningCodes set by the Rewording function.)


4) A number of other features have been added which relate to scripting. The initial release was a bit inflexible and missing some basic elements.

First, we've added two variants of an "include" statement, one which allows scripts to access text from other panels; and one which allows them to access text from external files.

The include statements are of the form:
#include name = "SomePanelName"
#include file = "c:\path\somefilename.xyz"

Include statements should be used at the top of a given panel, to include information from other locations which will be referenced later in the script.

This allows the creation of global functions, which can be used in common by many different types of script. You might find it effective to create small libraries of these functions. In the original release, each script panel was given a name, which was also the name of the function within the script to call when that script was invoked. Library script panels can have arbitrary names; their names don't have to appear as function names. These names are simply used as identifiers to allow other scripts to get access to their contents.

Depending on your taste, you might prefer to keep all your scripts within external files, and have only references to these files within the script panels. In that case, you can use tried-and-true text editors to manipulate script contents. On the other hand, you might prefer to make the text of these scripts directly available to your users via the script panels. To avoid losing any information, you should back up these scripts, which are contained in the elfUserTableTemplates table of the Custom.mdb database. (Note: this is no longer as much as an issue in Access 2002/XP, since the Zoom Box <Shift-F2> can be used to edit script panel contents, without truncating scripts as sometimes happened in prior versions of Access.) You can also edit this table directly, when doing substantial script revisions. One of the truly nice parts about working with scripts is that they stand outside the application -- you can actually modify them while your interface is running and see the results immediately.

While Access ELF has always been a very powerful tool for creating query interfaces, like most natural language systems it had its own built-in limits beyond which "tuning" was difficult, if not impossible. With the addition of scripting in version 3.0, and the substantial modifications made in this v4.0 release, we think Access ELF is reaching a completely new level of customizability.


Last Updated: March, 2002