ComponentOne True DataControl 8.0

Constant Reference

True DataControl 8.0 Reference

VbScript Reference

XArrayDB Reference


Overview

Welcome to ComponentOne True DataControl 8.0, an end-user-oriented ActiveX control that serves as an OLE DB/ADO data source for building applications.

True DataControl was designed to be a powerful, versatile, and easy-to-use data source tool. Programmers can use True DataControl and True DataControl Lite to create fully functional database connections that can be fully interacted with by the user.

True DataControl is a query control for Microsoft Visual Studio, developed by ComponentOne LLC.

ComponentOne has a user-friendly distribution policy. We want every programmer to obtain a copy of True DataControl 8 to try for as long as they wish. Those who like the product and find it useful may buy a license for a reasonable price. The only restriction is that unlicensed copies of True DataControl 8 will display a ComponentOne banner every time they are loaded to remind developers to license the product.

We are confident that you'll like True DataControl 8. If you have any suggestions or ideas for new features or tools that you'd like to see included in a future version please call us or write:

Corporate Headquarters

ComponentOne LLC
4516 Henry Street
Suite 500
Pittsburgh, PA 15213 USA
412.681.4343
412.681.4384 (Fax)

http://www.componentone.com


Product Profile

True DataControl is an ActiveX control that serves as an OLE DB/ADO data source for building applications. It is a “better data source control;” a replacement for standard data sources such as the Microsoft ADO data control (ADODC) and Visual Basic's DataEnvironment. It is mainly designed for Visual Basic 6.0, but can also be used in other environments, including web-based applications.

True DataControl Lite (TDataLite) is a freeware version of True DataControl, it can be downloaded from the ComponentOne web site www.componentone.com and used free of charge, see True DataControl Lite.

True DataControl is not just a new data source; it is a data source with logic. It enables developers to specify application logic where it belongs – in the data source. Enforcing application logic in the source as a set of business rules frees developers from the need to code all kinds of event procedures in various bound controls. It makes the application robust, manageable, and scalable.

True DataControl also provides important improvements to standard ADO regarding its performance and stability issues. It amends ADO by rectifying serious problems that were plaguing developers, such as long delays on startup, bugs in adUseServer mode, adding and deleting rows in batch update mode, etc.

True DataControl provides important built-in features that are ready for use in applications. These include standard database functions, and such advanced features as ad-hoc queries, and Find and Bookmarks dialogs. These are all accessible to the user with a set of toolbar-style buttons.

The True DataControl Query Mode enables you to add full ad-hoc query capabilities, i.e., Query By Example, to your applications in a matter of minutes. It includes the Filter By Form functionality found in a Microsoft Access database, but goes much further, providing this functionality in a much more flexible and versatile way. In fact, this feature is so useful that it alone justifies using True DataControl as your data source!

True DataControl enables Rapid Application Development in an easy, robust, code-free manner. One of its main goals is to eliminate the need for manual coding whenever possible. Tutorials included with the product show how applications that formerly required coding can now be created without any code at all! You specify the application logic, data relationships, and user interface features in a nonprocedural manner, as a set of rules, and True DataControl will enforce them at run time. This nonprocedural logic can be easily combined with procedural code.

True DataControl can store data in its internal memory without connecting to a database, which enables you to leverage the power of data-aware controls by building "non-database" user interfaces.


Feature List

True DataControl is a complete framework for creating intuitive applications with the least possible effort. True DataControl remains a compact ActiveX control. It is just like your standard ADO data control, only enriched with application logic and built-in features, some of which are listed here.

Performance and stability

True DataControl eliminates long delays connecting to database occuring in standard ADO data sources (CursorLocation=adUseServer must be used), and rectifies multiple ADO and OLE DB provider problems. And for ComponentOne True DBGrid 8.0, you don’t event need to purchase the full True DataControl version, free True DataControl Lite edition provides the same improvements.

Binding Flexibility

True DataControl can now be bound at design-time to any ADO/OLE DB data source (for example, to VB DataEnvironment) using the new properties DataSource and DataMember. This eliminates the need for True DataControl to create a SourceRecordset at run time.

Calculated fields

All you need to create a calculated field dependent on the values of other fields is to define a formula. True DataControl will maintain the field’s value and update it automatically.

Control properties

You can assign formulas to any properties of any controls on the form, even if they are not data-aware. True DataControl will automatically change the property each time the formula changes.

Field modifications

True DataControl can recognize changes to fields made by the end-user at the moment a change has been made, so you don’t have to write event procedures for different types of controls. No more Click events in your code!

Master-detail relationships

True DataControl makes it very easy to specify one data source (detail) as dependent on another (master). Master-detail relationships are optimized for the best performance and are natively combined with all other True DataControl features.

Ad-hoc query forms

True DataControl simplifies the construction of query forms by completely eliminating manual coding and the need for an in-depth understanding of SQL.

Query mode

True DataControl brings you the Filter By Form functionality from Microsoft Access, but greatly enhanced and much more flexible. You can now do Query By Example in Visual Basic, without writing any code!

SQL with parameters

A limitation of all standard Visual Basic data sources is the inability to use parameters in the underlying SQL statement at design time. True DataControl remedies this limitation and even allows expressions to be assigned to parameters, so they may be used without any manual coding.

Field and record constraints

Validation conditions, or constraints, can be imposed upon individual fields and/or upon the record as a whole. True DataControl will take care of testing the constraints when the user changes a field or posts a modified record.

Default values

You can specify the value to be assigned to a field in a new record, and even make it dependent on parameters.

Filters

True DataControl supports filter expressions restricting the contents of the data source.

One-to-one links

In addition to master-detail (one-to-many) relationships, a data source may be placed into one-to-one correspondence with another data source.

Crosstab (matrix) grid

Version 8.0 of True DataControl or True DataControl Lite supports crosstab data presentation. Integrated with ComponentOne True DBGrid 8.0, it enables you to build crosstabs easily and without restrictions. Crosstabs can even be modifiable.

Decision support (OLAP)

Version 8.0 of True DataControl or True DataControl Lite supports OLAP (decision support, pivot tables, decision cube). Working in conjunction with ComponentOne True DBGrid 8.0, it enables you to build OLAP front-end without relying on external tools and benefiting from full customizability and other powerfull features of ComponentOne True DBGrid.

Data in memory

True DataControl can be used to manage data in memory arrays/variables in exactly the same way as it manages the data of a database origin. Just define the fields at design time, and True DataControl will create internal memory storage. This powerful feature enhances all Microsoft and third-party data-aware controls, enabling them to be used in applications and forms that are not necessarily database-related.

Custom data sources

As an alternative to database and memory array data sources, you can create customized data sources with event-driven code. This advanced feature is ideal for legacy data and proprietary file formats.

Side-by-Side Support

True DataControl now supports the Microsoft Side-By-Side specifications.

Excellent documentation

True DataControl includes an extensive manual and online help with tutorials.

Responsive technical support

Free technical support via e-mail, phone, fax, and peer-to-peer newsgroups. Product updates, sample programs, and answers to frequently asked questions are also available from the ComponentOne Web site at www.componentone.com.

Free run-time distribution

No royalty fees required.


True DataControl Lite

True DataControl Lite (TDataLite) is a freeware control, it can be downloaded from ComponentOne web site www.componentone.com and used free of charge.

The purpose of True DataControl Lite is twofold:

•

It enables additional functionality in ComponentOne True DBGrid 8.0 and other controls. Using TDataLite as the data source for your TDBGrid controls, you can add powerful features to your applications, such as ad-hoc queries, calculated fields, field and record constraints, etc, and the new presentation modes, such as crosstab data presentation and OLAP support (decision support functionality, pivot table). You must be a registered owner of ComponentOne TDBGrid 8.0 to take advantage of these features, but you don’t have to pay additional price for TDataLite control.

•

TDataLite adds features to database applications even when used with non- ComponentOne data-aware controls, such as Microsoft DataGrid. Most of TDataLite features are available to non-ComponentOne controls as well. You can use most of True DataControl Rapid Application Development and built-in features, see Feature List.

TDataLite is a “junior” version of ComponentOne True DataControl. If you find TDataLite useful, we encourage you to explore the great features of True DataControl. You can dowload a trial version of True DataControl from the ComponentOne web site at www.componentone.com.

Among the valuable additions to TDBGrid functionality now available with TDataLite 8.0, is the new crosstab data presentation, see Tutorial 2, and the new pivot table (OLAP, decision support) data presentation, see Tutorial 10.

Several important features of True DataControl are unavailable in the Lite edition:

•

True DataControl master-detail relationships are unavailable in TDataLite.

•

True DataControl (TData) is a self-sufficent ADO/OLE DB data source, a replacement for standard ADO data sources such as Microsoft ADO Data Control (ADODC) and Visual Basic DataEnvironment. Unlike TData, TDataLite needs a standard data source to become functional, it must be bound to a standard ADO data control or another data source.

•

True DataControl offers significant enhancements to ADO performance and stability. It amends ADO by rectifying serious problems, such as long delays on startup, adUseServer mode problems, adding and deleting rows in batch update mode, etc. None of these enhancements are available in TDataLite, mainly because TDataLite always uses a standard data source, so it cannot influence its performance.

•

If you bind a non-ComponentOne control to a TDataLite control, the bound control will essentially be bound to the underlying standard data source (TDataLite.DataSource), not to the TDataLite itself. TDataLite does not expose its field structure and the resulting recordset to non-ComponentOne bound controls (unless in memory array or query modes). Most of TDataLite features (such as constraints, property expressions, etc) will still be available, but some (for example, calculated fields and filters) are only available to ComponentOne controls, such as TDBGrid 8.0, because they require direct access to TDataLite field and data structure.

On the other hand, TDataLite is not just a limited version of TData. There is one scenario where TDataLite can do what TData cannot. This is when you bind controls to a standard data source and benefit from TDataLite features without actually binding your controls to TDataLite. TData can only function as a data source, when your controls are bound (their DataSource property set) directly to the TData control. TDataLite, on the other hand, can be used “on the side”. For example, you bind a grid to an ADODC control, bind a TDataLite to the same ADODC control and define constraints in the TDataLite control. The constraints will be enforced, but the grid will still be bound to the same ADODC control, without TDataLite as a go-between.


Installation

To install True DataControl8, use the SETUP.EXE utility provided on the installation CD or diskettes. When you are prompted, enter the registration key (found on the CD case or the diskette) exactly as it is printed and click REGISTER to complete the registration.

The following files will be installed into your Windows\System directory or, if you use Windows NT, into your WinNT\System and WinNT\System32 directories. To use True DataControl8 in your Visual Basic projects, you must include these files in the project:

TRUEDC8.ocx

xadb8.ocx

TDBWSNK6.ocx

The following folders will be created by the setup utility:

ComponentOne

Directory used to store ComponentOne control information.

ComponentOne\Product

Contains sample projects and a README.TXT file with information about Product.


Adding True DataControl 8 to a Visual Basic Project

When you install True DataControl 8, the following new components will appear in the Visual Studio’s toolbox customization dialog box:

•

True DataControl 8

•

True DataControl Lite

After you have opened a new or existing project in Visual Basic 6.0, you can add True DataControl 8.0 and True DataControl Lite to the Visual Basic Toolbox by following these instructions:

•

On Visual Basic’s menu, select Project, then select Components... to display the Components dialog.

•

The controls will be listed as ComponentOne True DataControl 8.0 in the Controls page of the Components dialog. Select the control's check box, and then press the OK or Apply button.

Adding XArrayDB to a Visual Basic Project

True DataControl uses the ComponentOne XArrayDB object to implement memory-based data sources (if DataMode = 1 – Memory Array). However, your project need not reference XArrayDB explicitly unless you manipulate such objects directly in code.

If you need to include an XArrayDB reference in your project, follow these instructions:

•

On Visual Basic’s menu, select Project, then select References... to display the References dialog.

•

The object will be listed as ComponentOne XArrayDB Object in the References dialog. Select the object’s check box, and then press the OK or Apply button.

Adding ADO Library to a Visual Basic Project

True DataControl is based on ADO (ActiveX Data Objects), Microsoft object layer over OLE DB. You will most probably need the ADO library in all your projects. True DataControl does not add a reference to the ADO library to your project automatically, you have to do it manually, if you need it.

The ADO library (ADODB) is not always necessary for True DataControl, but some True Data events use the ADODB.Error object, which is defined in the ADO library. Also, you need a reference to ADODB if you use constants defined there, such as adLockOptimistic, adOpenStatic, etc.

If you need to include an ADODB reference in your project, follow these instructions:

•

On Visual Basic’s menu, select Project, then select References... to display the References dialog.

The libtrary will be listed as “Microsoft ActiveX Data Objects 2.1 Library” in the References dialog. Select the its check box, and then press the OK or Apply button.


End-User License Agreement

IMPORTANT-READ CAREFULLY: This End User License Agreement (this "EULA") contains the terms and conditions regarding your use of the SOFTWARE (as defined below). This EULA contains material limitations to your rights in that regard. You should read this EULA carefully and treat it as valuable property.

I. THIS EULA.

1.

Software Covered by this EULA. This EULA governs your use of the ComponentOne, LLC ("C1") software product(s) enclosed or otherwise accompanied herewith (individually and collectively, the "SOFTWARE"). The term "SOFTWARE" includes, to the extent provided by C1: 1) any revisions, updates and/or upgrades thereto; 2) any data, image or executable files, databases, data engines, computer software, or similar items customarily used or distributed with computer software products; 3) anything in any form whatsoever intended to be used with or in conjunction with the SOFTWARE; and 4) any associated media, documentation (including physical, electronic and on-line) and printed materials (the "Documentation").

2.

This EULA is a Legally Binding Agreement Between You and C1. If you are acting as an agent of a company or another legal person, such as an officer or other employee acting for your employer, then "you" and "your" mean your principal, the entity or other legal person for whom you are acting. However, importantly, even if you are acting as an agent for another, you may still be personally liable for violation of federal and State laws, such as copyright infringement.

This EULA is a legally binding agreement between you and C1. You intend to be legally bound to this EULA to the same extent as if C1 and you physically signed this EULA. By installing, copying, or otherwise using the SOFTWARE, you agree to be bound by the terms and conditions contained in this EULA. If you do not agree to all of the terms and conditions contained in this EULA, you may not install or use the SOFTWARE. If, for whatever reason, installation has begun or has been completed, you should cancel installation or un-install the SOFTWARE, as the case may be. (You may click on the "exit" button or its equivalent to immediately abort installation.) If you do not agree to all of these terms and conditions, then you must promptly return the SOFTWARE to the place of business from which you obtained it in accordance with any return policies of such place of business. Return policies may vary between or among resellers, and you must comply with your particular reseller's return policies as agreed at the point of purchase. If the place of business from which you purchased the SOFTWARE does not honor a complete refund for a period of thirty (30) days from the date of proof of purchase, then you may return the SOFTWARE directly to C1 for a period of thirty (30) days from the date of your purchase. To return the product directly to C1, you must obtain a C1 Return Authorization Number by contacting C1, and you must forward all items purchased, including the proof of purchase, directly to C1. The return must be postage-prepaid, and post-marked within thirty (30) days from the proof of purchase, time being of the essence. The return option to C1 is only available to the original purchaser of an unopened factory packaged item.

II. YOUR LICENSE TO DEVELOP AND TO DISTRIBUTE.

As provided in more detail below, this EULA grants you two licenses: 1) a license to use the SOFTWARE to develop other software products (the "Development License"); and 2) a license to use and/or distribute the Developed Software (the "Distribution License"). Both of these licenses (individually and collectively, the "Licenses") are explained and defined in more detail below.

1.

Definitions. The following terms have the respective meanings as used in this EULA:

"Network Server" means a computer with one or more computer central processing units (CPU's) that operates for the purpose of serving other computers logically or physically connected to it, including, but not limited to, other computers connected to it on an internal network, intranet or the Internet. "Web Server" means a type of Network Server that serves other computers more particularly connected to it over an intranet or the Internet.

"Developed Software" means those computer software products that are developed by or through the use of the SOFTWARE. "Developed Web Server Software" means those Developed Software products that reside logically or physically on at least one Web Server and are operated (meaning the computer software instruction set is carried out) by the Web Server's central processing unit(s) (CPU). "Developed Legacy Software" means those Developed Software products that are not Developed Web Server Software, including, for example, stand-alone applications and applications accessed by a file server only. "Redistributable Files" means the SOFTWARE files or other portions of the SOFTWARE that are provided by C1 and are identified as such in the Documentation for distribution by you with the Developed Software. "Developer" means a human being or any other automated device using the SOFTWARE in accordance with the terms and conditions of this EULA.

"Developer Seat License" means that each Developer using or otherwise accessing the programmatic interface or the SOFTWARE must obtain the right to do so by purchasing a separate End User License. "Network Server CPU License" means that a separate End User License must be purchased for each CPU operating the computer software at issue in the reference.

“Source Code” shall mean computer software code or programs in human readable format, such as a printed listing of such a program written in a high-level computer language. The term "Source Code" includes, but is not limited to, documents and materials in support of the development effort of the SOFTWARE, such as flow charts, pseudo code and program notes.

2.

Your Development License. You are hereby granted a limited, royalty-free, non-exclusive right to use the SOFTWARE to design, develop, and test Developed Software, on the express condition that, and only for so long as, you fully comply with all terms and conditions of this EULA.

The SOFTWARE is licensed to you on a Developer Seat License basis.

The Developer Seat License means that you may perform a single install of the SOFTWARE for use in designing, testing and creating Developed Software by a single Developer on a single computer with a single set of input devices, so long as such computer is used only by one Developer. Conversely, you may not install or use the SOFTWARE on a computer that is a network server or a computer at which the SOFTWARE is used by more than one Developer. You may not network the SOFTWARE or any component part of it, where it is or may be used by more than one Developer unless you purchase an additional Development License for each Developer. You must purchase another separate license to the SOFTWARE in order to add additional developer seats, whether the additional developers are accessing the SOFTWARE in a stand-alone environment or on a computer network. If the SOFTWARE is used to create Developed Web Server Software, then you may perform a single install of the SOFTWARE for use in designing, testing and creating Developed Web Server Software by a single Developer on a single computer or Network Server, either with a single CPU only. An additional Network Server CPU License is required for each additional CPU on the single computer or Network Server, as the case may be, upon which the SOFTWARE and/or the Developed Web Server Software is installed and a separate license for each separate computer. That is, for Developed Web Server Software, if the computer or Network Server operating the SOFTWARE has 2 CPU's, then you would need to purchase one additional Network Server CPU License (beyond the one Developer Seat License granted in this EULA).

In all cases, you may not use C1's name, logo, or trademarks to market your Developed Software without the express written consent of C1; (b) you must include the following C1 copyright notice in your Developed Software documentation and/or in the "About Box" of your Developed Software, and wherever the copyright/rights notice is located in the Developed Software (“Portions Copyright © ComponentOne, LLC 1991-2002. All Rights Reserved.”); (c) agree to indemnify, hold harmless, and defend C1, its suppliers and resellers, from and against any claims or lawsuits, including attorney's fees that may arise from the use or distribution of your Developed Software; (d) you may use the SOFTWARE only to create Developed Software that is significantly different than the SOFTWARE.

3.

Your Distribution License.

a. License to Distribute Developed Legacy Software. Subject to the terms and conditions in this EULA, you are granted the license to use and to distribute Developed Legacy Software on a royalty-free basis, provided that the Developed Legacy Software incorporates the SOFTWARE as an integral part of the Developed Software in machine-language compiled format (customarily an ".exe", or ".dll", etc.). You may not distribute, bundle, wrap or subclass the SOFTWARE as Developed Software which, when used in a "designtime" development environment, exposes the programmatic interface of the SOFTWARE. You may distribute, on a royalty-free basis, Redistributable Files with Developed Legacy Software only.

b. License to Distribute Developed Web Server Software. Subject to the terms and conditions in this EULA, you are granted the license to use and to distribute Developed Web Server Software, provided that you must purchase one Network CPU License for each CPU operating the Developed Web Server Software (and/or Redistributable Files called or otherwise used directly by the Developed Web Server Software). You may purchase an additional Network CPU License by purchasing an additional separate End User License for the SOFTWARE; one Network CPU License is included in this EULA. Notwithstanding the foregoing, however, you may distribute or transfer, free of royalties, the Redistributable Files (and/or any Developed Legacy Software) to the extent that they are used separately on a single CPU on the client/workstation side of the network served by the Web Server.

4.

Specific Product Limitations. Notwithstanding anything in this EULA to the contrary, if the license you have purchased is for any of the following products, then the following additional limitations will apply:

a. C1 ReportDesigner. C1ReportDesigner includes at least: 1) one dynamic link library (c1.win.c1reportdesigner.dll) file known as C1ReportDesigner Component, 2) one executable (ReportDesigner.exe) file known as C1ReportDesigner Application and, 3) the Source Code of the C1ReportDesigner Application. The C1ReportDesigner Component is subject to the general terms and restrictions set forth in this EULA. The C1ReportDesigner Application is an executable file used to design and prepare reports; the C1ReportDesigner Application may be distributed, free of royalties, only in conjunction with the Developed Software.

Subject to the terms and conditions in this EULA, C1 hereby grants you the right to use the C1ReportDesigner Application Source Code. You are hereby also granted the right to modify such Source Code and to create derivative works that are based on the licensed Source Code. You may distribute the derivative works that you develop, solely in object code format and exclusively in conjunction with and/or as a part of the Developed Software. You are expressly not granted the right to distribute, disclose or otherwise make available to any third party the licensed Source Code, any modified version, derivative work, or any portion thereof, in source code format.

C1 shall retain all right, title and interest in and to the licensed Source Code, and all C1 updates, modifications or enhancements thereof. Nothing herein shall be deemed to transfer any ownership or title rights in and to the licensed Source Code from C1 to you.

SOURCE CODE IS LICENSED TO YOU AS IS. C1 DOES NOT AND SHALL NOT PROVIDE YOU WITH ANY TECHNICAL SUPPORT FOR YOUR SOURCE CODE LICENSE.

b. VS View Reporting Edition. VS View Reporting Edition includes at least one executable file listed as “VSRpt7.exe”, known as “Designer.” The file "VSRpt7.exe”, or any upgrade or future versions of the Designer, are subject to the restrictions set forth in this EULA and may not be distributed with your Developed Software or in any other way.

c. VSForum. VSForum is intended to be installed on a Network Server. C1 grants to you the following rights to the SOFTWARE: a) Installation: You may install one copy of the SOFTWARE on a single Network Server; b) Use: When installed and initialized, the SOFTWARE creates a database file which contains the embodiment of a discussion forum (the database hereinafter referred to as the "Forum"). You may use the SOFTWARE to create one Forum on one Network Server only, which server may be connected at any point to an unlimited number of workstations or computers operating on one or more networks. You are specifically NOT LICENSED to create or operate multiple Forums. To create or to operate more than one FORUM, you must purchase one additional SOFTWARE license for each additional Forum.

d. Doc-to-Help. You may use Doc-To-Help to create online help, manuals or other documentation in electronic or printed format (the "Output Documents"). You may distribute and incorporate in such Output Documents those files identified in the documentation as Redistributable Files. Except for those specific Redistributable Files, you MAY NOT distribute the SOFTWARE, in any format, to others.

e. Studio Products. You may not share the component parts of the Studio Products licensed to you with other Developers, nor may you allow the use and/or installation of such components by other Developers.

5.

Updates/Upgrades; Studio Subscription. Subject to the terms and conditions of this EULA, the Licenses are perpetual. Updates and upgrades to the SOFTWARE may be provided by C1 from time-to-time, and, if so provided by C1, are provided upon the terms and conditions offered at that time by C1 in its sole discretion. C1 may provide updates and upgrades to the SOFTWARE for free or for any charge, at any time or never, and through its chosen manner of access and distribution, all in C1's sole and complete discretion.

C1 licenses certain of its separately-licensed products bundled together in a product suite, called the C1 "Studio" product line (the "Studio Products"). The exact separately-licensed products that are bundled into the Studio Products may change from time-to-time in C1's sole discretion. If the SOFTWARE is identified as a C1 "Studio" product, then the SOFTWARE is one of the Studio Products. The SOFTWARE and the Studio Products are revised from time-to-time (meaning, for example, revised with updates, upgrades and, in the case of Studio products, possibly changes to which specific products are included in the bundle). For you to be entitled to receive any such revisions to the SOFTWARE or the Studio Products, as the case may be, you must have a valid SOFTWARE license or a valid Studio subscription. The original purchaser of the SOFTWARE or of a Studio product receives a one-year subscription from the date of purchase of the SOFTWARE. After one year, the Studio subscription and/or the SOFTWARE license must be renewed to continue to be entitled to receive the SOFTWARE and/or the Studio Products revisions as the case may be.

6.

Serial Number. Within the packaging of the SOFTWARE, a unique serial number (the "Serial Number") is included, which allows for the registration of the SOFTWARE. The Serial Number is subject to the restrictions set forth in this EULA and may not be disclosed or distributed either with your Developed Software or in any other way. The disclosure or distribution of the Serial Number shall constitute a breach of this EULA, the effect of which shall be the automatic termination and revocation of all the rights granted herein.

7.

Evaluation Copy. If you are using an "evaluation copy" or similar version, specifically designated as such by C1 on its website or otherwise, then the Licenses are limited as follows: a) you are granted a license to use the SOFTWARE for a period of thirty (30) days counted from the day of installation (the "Evaluation Period"); b) upon completion of the Evaluation Period, you shall either i) delete the SOFTWARE from the computer containing the installation, or you may ii) contact C1 or one of its authorized dealers to purchase a license of the SOFTWARE, which is subject to the terms and limitations contained herein; and c) any Developed Software may not be distributed or used for any commercial purpose.

III. INTELLECTUAL PROPERTY.

1.

Copyright. You agree that all right, title, and interest in and to the SOFTWARE (including, but not limited to, any images, photographs, animations, video, audio, music, text, and “applets” incorporated into the SOFTWARE), and any copies of the SOFTWARE, and any copyrights and other intellectual properties therein or related thereto are owned exclusively by C1, except to the limited extent that C1 may be the rightful license holder of certain third-party technologies incorporated into the SOFTWARE. The SOFTWARE is protected by copyright laws and international treaty provisions. The SOFTWARE is licensed to you, not sold to you. C1 reserves all rights not otherwise expressly and specifically granted to you in this EULA.

2.

Backups. You may either: (a) copy the SOFTWARE solely for backup or archival purposes; or (b) install the SOFTWARE on a single computer, provided you keep the original solely for backup or archival purposes. Notwithstanding the foregoing, you may not copy the Documentation.

3.

General Limitations. You may not reverse engineer, decompile, or disassemble the SOFTWARE, except and only to the extent that applicable law expressly permits such activity notwithstanding this limitation.

4.

Software Transfers. You may not rent or lease the SOFTWARE. You may transfer the SOFTWARE to another computer, provided that it is completely removed from the computer from which it was transferred. You may permanently transfer all of your rights under the EULA, provided that you retain no copies, that you transfer all the SOFTWARE (including all component parts, the media and printed materials, any dates, upgrades, this EULA and, if applicable, the Certificate of Authenticity), and that the recipient agrees to the terms and conditions of this EULA as provided herein. If the SOFTWARE is an update or upgrade, any transfer must include all prior versions of the SOFTWARE.

5.

Termination. Without prejudice to any other rights it may have, C1 may terminate this EULA and the Licenses if you fail to comply with the terms and conditions contained herein. In such an event, you must destroy all copies of the SOFTWARE and all of its component parts.

6.

Export Restrictions. You acknowledge that the SOFTWARE is of U.S. origin. You acknowledge that the license and distribution of the SOFTWARE is subject to the export control laws and regulations of the United States of America, and any amendments thereof, which restrict exports and re-exports of software, technical data, and direct products of technical data, including services and Developed Software. You agree that you will not export or re-export the SOFTWARE or any Developed Software, or any information, documentation and/or printed materials related thereto, directly or indirectly, without first obtaining permission to do so as required from the United States of America Department of Commerce's Bureau of Export Administration ("BXA"), or other appropriate governmental agencies, to any countries, end-users, or for any end-uses that are restricted by U.S. export laws and regulations, and any amendments thereof, which include, but are not limited to, the following:

Restricted Countries: Restricted Countries currently include, but are not necessarily limited to Cuba, Iran, Iraq, Libya, Montenegro, North Korea, Serbia, Sudan, and Syria.

Restricted End-Users: Any End-User whom you know or have reason to know will use SOFTWARE or Developed Software in the design, development, or production of missiles and missile technology, nuclear weapons and weapons technology, or chemical and biological weapons. Any national of any of the Restricted Countries, wherever located, who intends to transmit or transport the SOFTWARE or Developed Software to one of the Restricted Countries.

Restricted End-Uses: Any use of SOFTWARE and Developed Software related to the design, development, or production of missiles and missile technology, nuclear weapons and weapons technology, or chemical and biological weapons.

These restrictions change from time to time. You represent and warrant that neither the BXA nor any other United States federal agency has suspended, revoked or denied your export privileges. C1 acknowledges that it shall use reasonable efforts to supply you with all reasonably necessary information regarding the SOFTWARE and its business to enable you to fully comply with the provisions of this Section. If you have any questions regarding your obligations under United States of America export regulations, you should contact the Bureau of Export Administration, United States Department of Commerce, Exporter Counseling Division, Washington DC. U.S.A. (202) 482-4811, http://www.bxa.doc.gov.

7.

U.S. Government Restricted Rights. The SOFTWARE and documentation are provided with RESTRICTED RIGHTS. For solicitations issued before December 1, 1995, by the United States of America, its agencies and/or instrumentalities (the "Government"), other than the Department of Defense, the use, duplication or disclosure of the software and documentation provided to the Government under this EULA shall be subject to the RESTRICTED RIGHTS as set forth in subparagraphs (c)(1) and (2) of the Commercial Computer Software - Restricted Rights clause at 48 CFR ch.1 52.227-19. For solicitations issued before September 29, 1995, by the Department of Defense, the use, duplication or disclosure of the software and documentation provided under this EULA shall be subject to the RESTRICTED RIGHTS as set forth in subparagraph (c)(1)(ii) of the Rights in Technical Data and Computer Software clause at 48 CFR ch.2 252.227-7013. You will comply with any requirements of the Government to obtain such RESTRICTED RIGHTS protection, including without limitation, the placement of any restrictive legends on the SOFTWARE, and any license agreement used in connection with the distribution of the SOFTWARE. Manufacturer is ComponentOne, LLC, 4516 Henry Street, Suite 501, Pittsburgh, Pennsylvania 15213 USA. For solicitations issued by the Government on or after December 1, 1995 and the Department of Defense on or after September 29, 1995, the only rights provided in the software and documentation provided herein shall be those contained in this EULA. Under no circumstances shall C1 be obligated to comply with any Governmental requirements regarding the submission of or the request for exemption from submission of cost or pricing data or cost accounting requirements. For any distribution of the SOFTWARE that would require compliance by C1 with the Government's requirements relating to cost or pricing data or cost accounting requirements, you must obtain an appropriate waiver or exemption from such requirements for the benefit of C1 from the appropriate Government authority before the distribution and/or license of the SOFTWARE to the Government.

IV. WARRANTIES AND REMEDIES.

1.

Limited Warranty. C1 warrants that the original media, if any, are free from defects for ninety (90) days from the date of delivery of the SOFTWARE. EXCEPT AS OTHERWISE PROVIDED IN THE PRECEDING SENTENCE, AND TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, C1 EXPRESSLY DISCLAIMS ANY WARRANTY FOR THE SOFTWARE, DOCUMENTATION AND ANYTHING ELSE PROVIDED BY C1 HEREBY AND C1 PROVIDES THE SAME IN “AS IS” CONDITION WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE AND DOCUMENTATION REMAINS WITH YOU. THIS LIMITED WARRANTY GIVES YOU SPECIFIC LEGAL RIGHTS. YOU MAY HAVE OTHERS WHICH VARY FROM STATE TO STATE.

2.

Limited Remedy. C1's entire liability and your exclusive remedy under this EULA shall be, at C1's sole option, either (a) return of the price paid for the SOFTWARE; (b) repair the SOFTWARE through updates distributed online or otherwise in C1's discretion; or (c) replace the SOFTWARE with its reasonable, provided that you return the SOFTWARE in the same manner as provided in Section I.2 for return of the SOFTWARE for non-acceptance of this EULA. Any media for any repaired or replacement SOFTWARE will be warranted for the remainder of the original warranty period or thirty (30) days, whichever is longer. THESE REMEDIES ARE NOT AVAILABLE OUTSIDE OF THE UNITED STATES OF AMERICA. TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, IN NO EVENT SHALL C1 BE LIABLE FOR ANY DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFIT, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR ANY OTHER PECUNIARY LOSS) ARISING OUT OF THE USE OR INABILITY TO USE THE SOFTWARE, EVEN IF C1 HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. BECAUSE SOME STATES/JURISDICTIONS DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES IN CERTAIN CASES, THE ABOVE LIMITATION MAY NOT APPLY TO YOU.

V. MISCELLANEOUS.

1.

This is the Entire Agreement. This EULA (including any addendum or amendment to this EULA included with the SOFTWARE) is the final, complete and exclusive statement of the entire agreement between you and C1 relating to the SOFTWARE. This EULA supersedes any prior and contemporaneous proposals, purchase orders, advertisements, and all other communications in relation to the subject matter of this EULA, whether oral or written. No terms or conditions, other than those contained in this EULA, and no other understanding or agreement which in any way modifies these terms and conditions, shall be binding upon the parties unless entered into in writing executed between the parties, or by other non-oral manner of agreement whereby the parties objectively and definitively act in a manner to be bound (such as by continuing with an installation of the SOFTWARE, "clicking-through" a questionnaire, etc.) Employees, agents and other representatives of C1 are not permitted to orally modify this EULA.

2.

You Indemnify C1. You agree to indemnify, hold harmless, and defend C1 and its suppliers and resellers from and against any and all claims or lawsuits, including attorney's fees, that arise or result from this EULA.

3.

Interpretation of this EULA. If for any reason a court of competent jurisdiction finds any provision of this EULA, or any portion thereof, to be unenforceable, that provision of this EULA will be enforced to the maximum extent permissible so as to effect the intent of the parties, and the remainder of this EULA will continue in full force and effect. Formatives of defined terms shall have the same meaning of the defined term. Failure by either party to enforce any provision of this EULA will not be deemed a waiver of future enforcement of that or any other provision. Except as otherwise required or superseded by law, this EULA is governed by the laws of the Commonwealth of Pennsylvania, without regard to its conflict of laws principles. The parties consent to the personal jurisdiction and venue of the Commonwealth of Pennsylvania, in the County of Allegheny, and agree that any legal proceedings arising out of this EULA shall be conducted solely in such Commonwealth. If the SOFTWARE was acquired outside the United States, then local law may apply.


Redistributable Files

Applications including True DataControl can be distributed to users along the same guidelines as with most other ActiveX controls. Before you do this, make sure you have read and fully understood this section of this document. You can only provide your users with run-time capabilities. It is illegal to distribute any part of True DataControl for development purposes. Unlike True DataControl, you can freely distribute True DataControl Lite as freeware.

You can use Application Setup Wizard to create a setup program for your application, or you can do it manually. Application Setup Wizard includes all components needed by True DataControl into your application setup program automatically. If you choose not to automate this process, you will need the following information for enabling True DataControl run-time functionality on your users’ systems.

True DataControl depends on three DLLs for its run-time functionality:

TRUEDC8.OCX

True DataControl. For True DataControl Lite, the file is TDCL8.OCX.

xadb8.OCX

ComponentOne XArrayDB Object. Must be registered on the user system, if you use True DataControl in memory array mode (DataMode = 1 – Memory Array).

TDBWSNK6.OCX

Auxiliary DLL. Must be registered on the user system, if True DataControl is used with Visual Basic 6.0. (This file is not used in True DataControl Lite.)

All three DLLs must be registered on the user system with REGSVR32.EXE.

True DataControl also depends on the VBScript functionality enabled on the user machine:

VBSCRIPT.DLL

Microsoft VBScript DLL

The VBScript DLL is installed, for example, when you install Microsoft Internet Explorer on your system.

True DataControl does not depend on any other products, such as MFC DLLs, or other non-system DLLs.

End-users of your applications are not licensed to use True DataControl for development, and may not redistribute any of the above control files.

You are not licensed to distribute any True DataControl file to users for development purposes. You are not allowed to add or transfer the True DataControl license key to the registry of your users' computer(s).

In particular, if you create a control using a True DataControl component as a constituent control, you are not licensed to distribute the control you created with the True DataControl component to users for development purposes.

It is your responsibility to make such restrictions clear to your users.


Technical Support

ComponentOne True DataControl is developed and supported by ComponentOne LLC, a company formed by the merger of APEX Software Corporation and Videosoft. You can obtain technical support using any of the following methods:


ComponentOne Web Site

The ComponentOne Web site at www.componentone.com provides a wealth of information and software downloads for True DataControl users:

•

Descriptions of the various support options available through the ComponentOne Service Team.

•

Answers to frequently asked questions (FAQ's) about True DataControl, organized by functionality. Please consult the FAQ's before contacting us directly, as this can save you time and also introduce you to other useful information pertaining to True DataControl.

Free product updates, which provide you with bug fixes and new features.


Internet E-mail

For technical support through the Internet, e-mail us at:

support.truedata@componentone.com

To help us provide you with the best support, please include the following information when contacting ComponentOne:

•

Your ComponentOne product serial number.

•

The version and name of your operating system.

•

Your development environment and its version.

For more information on technical support, go to:

www.componentone.com/support


Peer-to-Peer Newsgroup

ComponentOne also sponsors a peer-to-peer newsgroup for ComponentOne True DataControl users. ComponentOne does not offer formal technical support in this newsgroup, but instead sponsors it as a forum for users to post and answer each other's questions regarding ComponentOne True DataControl. However, ComponentOne may monitor the newsgroup to ensure accuracy of information and provide comments when necessary. You can access the newsgroup from the ComponentOne Web site at: www.componentone.com/newsgroups.


Using True DataControl as Your Data Source

Most of the material in this section is standard for all OLE DB/ADO data sources in Visual Basic and other environments. For True DataControl Lite specifics, see Using True DataControl Lite.


Binding Your Controls to True DataControl

Any control supporting OLE DB data binding can be bound to a True DataControl (TData) as its data source. This includes complex controls, such as ComponentOne True DBGrid, and simple controls, such as TextBox, ComboBox and many others.

To bind a control to a TData control, set the control’s DataSource property to the TData control's name. The bound control’s DataMember property should be empty. The binding can be done at design time by selecting the TData control name in the DataSource combo in Visual Basic Properties window, or at run time by setting the DataSource property:

Set TDBGrid1.DataSource = TData1

Caution:

1.

Microsoft Visual Basic 6.0 supports two different data binding specifications: (a) OLE DB data binding, supported by True DataControl, and (b) ICursor data binding, a legacy binding protocol supported in Visual Basic 6.0 for backward compatibility reasons. ActiveX data bound controls (such as ComponentOne True DBGrid, for example) usually come in two varieties: OLE DB and ICursor. Make sure you use the OLE DB version. Data-aware controls based on the ICursor specification cannot be bound to a TData control.

2.

Visual Basic 5.0 does not support OLE DB data binding. Although controls supporting OLE DB can be bound to True Data at run time, this cannot be done in Visual Basic 5.0 at design time. We recommend that you upgrade to Visual Basic 6.0 if you plan to use True Data Control.


Using the Recordset Property

Whenever you need programmatic access to the underlying data, use the True DataControl’s Recordset property, which returns the ADO recordset object representing the TData control’s data, its recordset.

The Recordset property is read-only, in the sense that you can’t set it to another recordset object. True DataControl has a separate property, SourceRecordset, which can be set to an ADO recordset. Differences between Recordset and SourceRecordset properties are discussed in Data Source Mode.

Most programmatic access to True DataControl is done through its Recordset property. Some typical uses are:

1.

Use Recordset.Bookmark to get the current record bookmark; set Recordset.Bookmark to move the current record to a bookmark.

2.

Call Recordset.AddNew to add records.

3.

Call Recordset.Delete to delete records.

4.

Call Recordset.Update to send changes to the database, or call Recordset.UpdateBatch in batch update mode, that is, if LockType=adLockBatchOptimistic.

See the ADO documentation for complete reference.

True DataControl provides two methods, UpdateFields and CancelUpdate, which complement the standard ADO Recordset functionality.

1.

We recommend using TData.CancelUpdate instead of TData.Recordset.CancelUpdate, because Recordset.CancelUpdate does not revert the value in a bound control until that value is updated to the recordset field.

2.

Call TData.UpdateFields if you need to update the recordset field with the value in a bound control without waiting until the user moves focus out of the bound control or leaves the current record. This functionality is missing in the ADO Recordset.

You can modify data in the current record by setting recordset field values in the following manner:

TData1.Recordset(“Amount”) = 10.0

There is nothing wrong with this line, but we suggest an alternative way, provided by the True DataControl Fields property:

TData1.Fields(“Amount”).Value = 10.0

or, in abbreviated form:

TData1(“Amount”) = 10.0

This is not only shorter than one using Recordset, but it also allows more control, such as setting several fields at once without updating dependencies, using the ChangeInProgress property.

In order to use ADO recordsets in code without restrictions, you must add a reference to the ADODB type library (Microsoft ActiveX Data Objects) to your project.

For better performance, we strongly recommend that you create an object variable for the Recordset object and use it each time to access a method or property. For example, although it is possible to write:

TData1.Recordset.UpdateBatch

...

TData1.Recordset.Bookmark = Bmk

it can cause performance degradation, since a recordset object is created and immediately destroyed by every such call. The right way is to define a variable:

Dim RS As ADODB.Recordset

and set it in the OpenDataComplete event (fired when the True DataControl’s recordset has been successfully created):

Private Sub TData1_OpenDataComplete()

Set RS = TData1.Recordset

End Sub

Then you can use that variable:

RS.UpdateBatch

...

RS.Bookmark = Bmk


Using Recordset Events

True DataControl fires events when a change occurs in its recordset. The recordset events fired by True DataControl are essentially the same as the corresponding events of the standard ADO data control (Microsoft ADODC), with the exception of the WillChangeField event. These events occur when current record position changes, recordset fields change, recordset rows change, and when the whole recordset changes. The difference in WillChangeField is due to a poor design of the standard ADO WillChangeField event, which does not provide the new value that is about to be assigned to a field. Knowing this value is essential to the programmer, so True DataControl uses different arguments in its WillChangeField event. All other recordset events adhere to the ADO specification. You can look them up either in the ADO documentation, or in the Reference section of this document.

WillMove

Occurs before the current record position changes.

MoveComplete

Occurs after the current record position has changed.

WillChangeField

Occurs before a field value changes

FieldChangeComplete

Occurs after a field value has changed

WillChangeRecord

Occurs before a record is added/deleted/updated/restored

RecordChangeComplete

Occurs after a record has been added/deleted/updated/restored

WillChangeRecordset

Occurs before the whole recordset is changed

RecordsetChangeComplete

Occurs after the whole recordset has changed


Using True DataControl Lite


Binding TDataLite to a Data Source

Unlike True DataControl, True DataControl Lite cannot be used as an independent data source. For a TDataLite to function properly, it must be bound to a standard ADO data source, such as ADODC control or DataEnvironment. This is the main difference between the Light and Full editions: True DataControl Lite modifies behavior of a standard data source, whereas True DataControl is a data source by itself, does not need an additional data source control or DataEnvironment.

To bind a TDataLite control to a data source, set its DataSource and DataMember properties, either at design time in the Properties window, or at run time:

TDataLite1.DataMember = “”

Set TDataLite1.DataSource = Adodc1

or

TDataLite1.DataMember = “Command1”

Set TDataLite1.DataSource = DataEnvironment1

Once you set up the data source of your TDataLite control, you can use bound controls with it in one of two different modes:


Binding Data-Aware Controls and TDataLite to the Same Standard Data Source

You can bind controls to the same data source that TDataLite1 is bound to:

Set TDataLite1.DataSource = Adodc1

Set DataGrid1.DataSource = Adodc1

In this case, TDataLite works “on the side”, but you still can use most of its features. For example, constraints specified in TDataLite will be enforced. However, data-aware controls are not bound to TDataLite, so they cannot use features requiring direct binding, for example, calculated fields.

In this mode, you can use TDataLite with any data bound controls, not just ComponentOne controls. For example, you can use it with Microsoft DataGrid and other Microsoft and third-party data bound controls.

ComponentOne controls, such as True DBGrid 8.0 can be bound to TDataLite directly, thus having complete access to all TDataLite features, see Binding data-aware controls to a TDataLite control. If you use True DBGrid 8.0, we recommend to bind it directly to TDataLite.

You can also bind other, non-ComponentOne controls to TDataLite directly, specify TDataLite as their DataSource. But in this case, TDataLite will delegate to the standard data source, so any non-ComponentOne control bound to TDataLite will effectively be bound to the standard data source, TDataLite.DataSource. Exceptions to this rule are special modes: memory array mode (DataMode = 1 – Memory Array), query mode (QueryMode = True) and pivot mode (Pivot = True). In these modes, TDataLite serves as a fully functional data source, not just to ComponentOne controls, but to any data-aware controls bound to it. It allows you to use these features, memory-stored data, query mode, pivot (OLAP) support, with data-aware controls of your choice.

Restriction: For all data-aware controls except True DBGrid 8.0, True DataControl Lite can be used only with data sources using client-side cursors (CursorLocation = adUseClient).


Binding Data-Aware Controls to a TDataLite Control

You can bind controls to TDataLite directly:

Set TDataLite1.DataSource = Adodc1

Set Grid1.DataSource = TDataLite1

•

For ComponentOne controls, such as True DBGrid 8.0, it means that TDataLite is used as its fully functional data source.

•

For non-ComponentOne controls in standard mode (TDataLite.DataMode = 0 – DataSource, TDataLite.QueryMode = False, TDataLite.Pivot = False), the real data source will not be the TDataLite control, but the standard data source behind it, TDataLite1.DataSource.

•

For non-ComponentOne controls in one of the above modes, TDataLite will be their real data source, just as for ComponentOne controls. This exception allows you to use the special TDataLite features, memory-stored data, query mode, pivot (OLAP) support, with data-aware controls of your choice.

Use direct binding in the following cases:

•

Using ComponentOne True DBGrid 8.0, bind it directly to TDataLite control, to have complete access to all TDataLite features.

•

Using non-ComponentOne data-aware controls, bind them directly to TDataLite if you use one of the special TDataLite modes: memory array mode, query mode or pivot mode, see Binding data-aware controls and TDataLite to the same standard data source. Since QueryMode can be changed at run time, use direct binding at all times if you intend to enable query mode.

Even with direct binding, the same restriction from Binding data-aware controls and TDataLite to the same standard data source still applies: you can only use server-side cursors (CursorLocation = adUseServer) with True DBGrid 8.0, you must not bind other controls to TDataLite bound to a server-side cursor data source. Problems in server-side cursor implementation will not allow TDataLite work properly unless it takes full responsibility as a data source, which can be only with True DBGrid 8.0.


Improvements Over Standard ADO Data Sources

True DataControl provides many enhancements to ADO data sources, allowing to add application logic to them. In addition to that, it also provides important improvements to ADO regarding its performance and stability issues.

Performance on Large Recordsets

Fixing Problems with adUseServer

Microsoft Access Problem with Refreshing Recordsets from Database

Reused (pooled) Connections


Performance on Large Recordsets

Problem

Connecting to a large database table or result set (10,000 rows and more), a standard ADO application will take a lot of time to start, several minutes or even more, depending on the database and hardware. This delay is usually proportional to the size of the data. No matter what settings you use with ADO recordset, it still is that slow.

Solution

Using True DataControl with CursorLocation=adUseServer, you won't encounter such long delays.

Note

True DataControl Lite will provide the same improvement for ComponentOne True DBGrid 8.0. So you can use True DataLite (free of charge) to solve ADO performance problems for True DBGrid 8.0. To benefit from this improvement using other, non-ComponentOne bound control, you must purchase the full True DataControl version.

Explanation

If you use CursorLocation=adUseClient in ADO, all rows of data are first fetched from the server and only then your recordset becomes operational. It does not only take long time, it also uses up large amounts of memory. That is why adUseClient is completely inappropriate for large recordsets. True DataControl can not improve performance with adUseClient either.

So, the solution seems obvious: use CursorLocation=adUseServer. In practice, however, this does not really alleviate the performance problem with ADO, unless you use True DataControl. The long time delay on start up will still be there if you use the ADO recordset with some data-bound controls and other OLE DB consumers. It is caused by the provider’s implementation of OLE DB IRowsetScroll interface using row count that triggers realization of the recordset, i.e., fetching all its rows on the server. Although it is somewhat faster than using adUseClient, it still depends on the data size and can take very long time to perform.

Using True DataControl with CursorLocation=adUseServer will remedy this situation, help you avoid the long delay that can't be eliminated by any standard ADO means. True DataControl, working as an intermediary between the ADO recordset and data-bound controls, eliminates this problem.


Fixing Problems with adUseServer

Problem

Developers experience serious problems using ADO with CursorLocation=adUseServer setting. Many of these problems are bugs in OLE DB providers themselves. Especially problematic is using adUseServer in conjunction with LockType=adLockBatchOptimistic, so called "batch update mode". It just won't work with some OLE DB providers, when you add or delete rows.

Solution

If you use True DataControl with CursorLocation=adUseServer, you won't experience many of these problems, True DataControl will work around them. You must bear in mind, however, that some of the provider problems can be resolved only if you set TData.SafeMode=True. This is because working around them can affect performance. Working around LockType=adLockBatchOptimistic problems does not require SafeMode=True. Other problems, such as those concerning Recordset.Filter (also occuring in connection with TData query mode), require SafeMode=True. Of course, there can be provider problems that TData is unable to work around.

Note

True DataControl Lite will provide the same improvement for ComponentOne True DBGrid 8.0. So you can use True DataLite (free of charge) to solve adUseServer problems for True DBGrid 8.0. To benefit from this improvement using other, non-ComponentOne bound control, you must purchase the full True DataControl version.

Explanation

It is not accidental that adUseServer causes problems, nor it is surprising that they are especially bad in batch update mode. The problems are not in ADO itself, as it may seem, but in OLE DB providers used with ADO. Using CursorLocation=adUseClient means that you are not working with an OLE DB provider directly. Instead, adUseClient brings an intermediary into the picture, Microsoft Client Cursor Engine (CCE). CCE fetches all the data into memory first (thus causing a performance problem sometimes, see Performance on large recordsets) and then it operates on memory-resident data, which is much simpler, so it naturally is more stable. But you can't always rely on adUseClient, both for its performance problems and because it disables some functionality such as dynamic recordsets (reflecting the changes made by other users), database validation rules, etc. When you switch to adUseServer, the CCE component no longer stands between your application and the OLE DB provider, ADO talks directly to the provider, and this is when provider problems start to show up. Using batch update mode aggravates the situation because it means that more than one row can have pending updates at any given time. Many OLE DB providers simply can't handle this situation correctly.

Using True DataControl will help you to avoid this situation. True DataControl, working as an intermediary between OLE DB providers and your application, eliminates these problems. Obviously, we cannot guarantee that it will solve all OLE DB provider problems forever, but it eliminates most problems with batch update mode, notification non-reentrancy and others.


Microsoft Access Problem with Refreshing Recordsets from Database

Problem

When you need to refresh a recordset with the data currently stored in the database, you use Recordset.Requery. With all databases except MS Access it brings you the latest data from the database, including modifications made by other users. In MS Access, however, all changes are held in an internal cache that is flushed to the disk every five seconds (this constant can be changed in the Registry). This cache is unavailable across connections. So, if you use two different ADO connections to the same database, Requery will only bring you the data as it was 5 seconds ago. If you use the same Connection object for different recordsets, each of those recordsets will reflect the latest data without delay when you call its Requery method, which is the correct behavior. But this is unacceptable for a multi-user application, because then every user must have a separate database connection.

Solution

If you use an Access database through True DataControl, it will take care of correct refreshes, flushing the Access cache when necessary. Use TData.SourceRecordset.Requery to refresh a True DataControl with the current database data. This will still include a short delay (a fraction of a second) between sending updates to the database by one user and its availability to another. It is acceptable for multi-user applications, but if you need to synchronize data between different True DataControl controls in one form or application, make sure they have identical connection properties (so Connection Pooling will take effect) or use TData.SourceConnection property to ensure that they use the same connection.

Note

This improvement is unavailable in True DataControl Lite.


Reused (pooled) Connections

This improvement only concerns True DataControl in comparison with the standard Microsoft ADODC control. Using Visual Basic DataEnvironment or coding for ADO Recordset objects, you can control ADO Connection objects that the recordsets belong to.

With ADODC control, however, each control creates its own Connection object, which is a performance-heavy operation for most databases. Connection objects proliferation leads to considerable performance degradation and other problems (see Microsoft Access problem with refreshing recordsets from database).

You don't have this problem with True DataControl, since it uses connection pooling and also allows you to take full control over connections with the SourceConnection property. The connection pooling feature ensures that different controls having identical ConnectionString settings normally use only one single connection (some other conditions apply for pooling to take effect, see Connection Pooling for detail).

Note

Connection pooling is unavailable in True DataControl Lite.


Tutorials - True DataControl

Tutorials – True DataControl

Sixteen tutorials are presented to help you master True DataControl. The tutorials assume that you are familiar with programming in Visual Basic and have a general knowledge of how to use ADO/OLE DB data sources with bound controls. The tutorials provide step-by-step instructions and require no prior knowledge of True DataControl. By following these instructions, you will be able to create projects demonstrating a variety of True DataControl features. You will also get a good sense of what True DataControl can do and how to do it.

The tutorials use an Access database, called TDBGDEMO.MDB. The database file TDDEMO.MDB and the tutorial projects can be found in the ComponentOne Common directory.

We encourage you to run the tutorial projects in Visual Basic and experiment with your own modifications. This is the best and quickest way to learn how to realize the full potential of True DataControl.

NOTE: The tutorials assume that the database file TDBGDEMO.MDB is in the C:\Program Files\ComponentOne Studio\Common directory. Depending on where you store the projects and database files, you may need to change the ConnectionString property of TData controls in the tutorial projects in order for the projects to work properly, or you can just copy the database file TDBGDEMO.MDB to the specified location.

Please also note that all code samples and expressions are case-sensitive.

We also assume that two ActiveX controls are included in all projects: ComponentOne True DataControl 8.0 (TData) and Microsoft DataGrid Control 6.0 (OLEDB) (DataGrid). To add a control to your project you must select Components... from the Project menu to display the list of available components. Check the box representing the desired control, then press the OK button. The control icons are added to the Visual Basic toolbox.

Tutorial 1 - Converting a Project from the ADO Data Control to True DataControl

Tutorial 2 - Using True DataControl with a Database

Tutorial 3 - Using True DataControl with Memory Data

Tutorial 4 - Calculated Fields and True DataControl Expressions

Tutorial 5 - Implementing Master-Detail Relationships

Tutorial 6 - A Common Example of a Master-Detail Relationship

Tutorial 7 - Parameters and Dynamic SQL

Tutorial 8 - Ad-hoc Queries Using True DataControl Range Conditions

Tutorial 9 - Automatic Updating of Control Properties

Tutorial 10 - Using Filter Conditions

Tutorial 11 - Imposing Constraints and Related Issues

Tutorial 12 - One-to-One Links and Linked Fields

Tutorial 13 - One-to-One Links and Memory-Based Controls

Tutorial 14 - Creating Custom Data Sources in Code

Tutorial 15 - Query Mode (part 1)

Tutorial 16 - Query Mode (part 2)


Tutorial 1 - Converting a Project from the ADO Data Control to True DataControl

In this tutorial you will see how easy it is to take an existing project that uses the ADO Data Control and replace it with the True DataControl.

Step 1.

The ADO folder under Tutorial 1 in the Tutorials directory contains a project with simple master detail relationship between two grids using the ADO data control. Open and run this project and observe the behavior of the Composition grid as you scroll through the Composers grid with the mouse, the arrow keys, or the data control.

Step 2.

Delete both ADO data controls from the project, and add two TData controls as shown.

NOTE: Remember to deselect the ADO data controls from the components window after removing them from the form.

Step 3.

Select TData1, and click the right mouse button over it to open the control's context menu. Select the TData Properties option. This will open the True DataControl property pages dialog, where you can view and edit the properties of TData1. The dialog looks like this:

Step 4.

Establish a database connection for the TData1 control.

If you are familiar with the standard ADO data control (Microsoft ADODC) included with Visual Basic 6.0, you will find much commonality between them in specifying database connection. In True DataControl, this is done in the DataSource property page.

Press the Build button on the TData1 DataSource property page. This will bring up the Data Link Properties dialog, with four tabs in it. Select the Provider tab to display the list of all available OLE DB providers installed on your system. Select the Microsoft Jet 3.51 OLE DB Provider and click the Connection tab. Here you can Select or enter a database name: select the C:\Program Files\ComponentOne Studio\Common\TDBGDemo.mdb database file using the ellipsis button on the right side of the edit box. Press the Test connection button to make sure the database connection is specified correctly. Now press the OK button to close the Data Link Properties dialog. The following text now appears in the text box:

Provider=Microsoft.Jet.OLEDB.3.51;Persist Security

Info=False;Data Source=C:\Program Files\ComponentOne Studio\Common\TDBGDemo.mdb

The same text appears in the ConnectionString property of the TData1 control in the Visual Basic Properties window. You have specified the ConnectionString property, which defines the database connection for a TData control.

Step 5.

Once you have selected a database, you also need to specify the exact source of your data within the database. This is called the RecordSource in True DataControl, and consists of two properties: CommandType and RecordSource. Select 2 – adCmdTable in the CommandType combo box, then select Composer in the Table or Stored Procedure Name combo box. The page now looks like this:

You can see that the RecordSource property in the Visual Basic Properties window is now set to Composer. Press the Test button on the DataSource property page to make sure your database connection and RecordSource are correct. You should see the following message: Test RecordSource succeeded.

Step 6.

Repeat Steps 3 - 5 for TData2, selecting Opus in the Table or Stored Procedure Name combo box. Go to the Fields property page of TData2, click on the Last field and clear its visible property. The TData2 control will still have full access to the field Last, but no control bound to it will be able to access it. In the DataSource Property Tab for TData2, the Table or Stored Procedure Name should be set to Opus. Two additional steps are also required: DataGrid1 DataSource property must be set to TData1 and DataGrid2 DataSource property must be set to TData2.

Step 7.

Delete the DataGrid1_RowColChange event from the project.

Private Sub DataGrid1_RowColChange(LastRow As Variant, _

ByVal LastCol As Integer)

We will replace this with event with a Range Condition that we will set from the TData2 Fields property page.

Step 8.

Open the True DataControl property page for TData2 and select the General page. On the General page select TData1 in the Master combo box. This step will enable us to create the original master-detail relationship that we had previously created through code using the ADO data controls.

Step 9.

On the TData2 Fields property page, select the Last field. Click the right mouse button over the Last field and select New Range Condition from the menu. An empty range condition for the Last field will now appear with controls for entering the condition now visible in the right part of the page. Go to the Value Expression text box and type the following expression:

TData1.Last

This will create a Last = TData1.Last range condition for the TData2 field Last. Click the OK button, and then close the Property Pages dialog.

Step 10.

We will now replace the last references to ADO objects in our project with references to True DataControl objects. In the Option Explicit statement, replace: Dim Flds As ADODB.Fields with Dim Flds As TrueData60Ctl.Fields. In the Form_Load event, replace Set Flds = Adodc1.Recordset.Fields with Set Flds = TData1.Fields.

Step 11.

In the TData2_WillOpenData event, add the following code to synchronize the caption of the detail grid with the current record in the master grid.

DataGrid2.Caption = "The compositions of " & _

Flds("First").Value & " " & Flds("Last").Value.

NOTE: We could have achieved the same effect without any code for this by using the Property Expressions page of TData2 to set the caption of DataGrid2 without code. Tutorial 9 addresses this in detail.

Run the Program and Observe the Following:

•

Moving between records on the Composers grid by clicking with the mouse button or navigating with the arrow keys will cause the corresponding detail records to display in the Compositions grid. The caption of the grid also changes to reflect the current record in the master grid.

•

Please note that establishing the master-detail relationship between the grids was done without requiring a single line of code!

Close the program. You have successfully completed Tutorial 1.


Tutorial 2 - Using True DataControl with a Database

In this tutorial, you will learn how to make a TData control the data source of data-bound controls, such as DataGrid and TextBox. You will also learn how to use the True DataControl property pages to perform the basic tasks of defining database connection and TData fields. You will be able to run the program and observe its run-time behavior.

Step 1.

Start a new project.

Step 2.

Place an ComponentOne True DataControl 8.0 (TData1) and a Microsoft DataGrid Control 8.0 OLEDB (DataGrid1) on the form (Form1) as shown in the illustration:

Step 3.

Select TData1, and click the right mouse button over it to open the control's context menu. Select the TData Properties option. This will open the True DataControl property pages dialog, where you can view and edit the properties of TData1. The dialog looks like this:

NOTE: As you will soon realize, in most cases there is no need to write Visual Basic code if you are building your application with True DataControl, which promotes codeless application development, because instead of writing code, you will specify properties and expressions in the True DataControl property pages.

Step 4.

Establish a database connection for the TData control.

If you are familiar with the standard ADO data control (Microsoft ADODC) included with Visual Basic 6.0, you will find much commonality between them when specifying a database connection. In True DataControl, this is done in the DataSource property page.

Press the Build button on the DataSource property page. This will bring up the Data Link Properties dialog, with four tabs in it. Select the Provider tab to display the list of all available OLE DB providers installed on your system. Select the Microsoft Jet 3.51 OLE DB Provider and click the Connection tab. Here you can Select or enter a database name: select the C:\Program Files\ComponentOne Studio\Common\TDBGDemo.mdb database file using the ellipsis button on the right side of the edit box. Press the Test connection button to make sure the database connection is specified correctly. Now press the OK button to close the Data Link Properties dialog. The following text now appears in the text box:

Provider=Microsoft.Jet.OLEDB.3.51;Persist Security

Info=False;Data Source=C:\Program Files\ComponentOne Studio\Common\TDBGDemo.mdb

The same text appears in the ConnectionString property of the TData1 control in the Visual Basic Properties window. You have specified the ConnectionString property, which defines the database connection for a TData control.

Step 5.

Once you have selected a database, you also need to specify the exact source of your data within the database. This is called the RecordSource in True DataControl, and consists of two properties: CommandType and RecordSource. Select 2 – adCmdTable in the CommandType combo box, then select Customers in the Table or Stored Procedure Name combo box. The page now looks like this:

You can see that the RecordSource property in the Visual Basic Properties window is now set to Customers. Press the Test button on the DataSource property page to make sure your database connection and RecordSource are correct. You should see the following message: Test RecordSource succeeded.

Step 6.

Instead of using the DataSource property page controls, you can directly enter all necessary property settings in the Visual Basic Properties window. So far, we have specified the following settings:

TData1.ConnectionString

Provider=Microsoft.Jet.OLEDB.3.51;Persist Security

Info=False;Data Source=C:\Program Files\ComponentOne Studio\Common\TDBGDemo.mdb

TData1.CommandType 2 - adCmdTable

TData1.RecordSource Customers

Step 7.

Select the General property page, and check all the check boxes in the Buttons group there. We want all available buttons on the TData control visible for our tutorial example. Click the OK button. Set the Tooltips property of TData1 to True in the Visual Basic Properties window.

Step 8.

Select the Fields property page. Since you have already defined the database connection and RecordSource, you will see all fields of the Customers table. In this example, we need to expose three fields: CustomerID, CompanyName, and City. To do this, one at a time select each of the other fields in the data source tree-view window, and clear the Visible check box for all of them. An empty check box means that the field is accessible to your TData control, but is not exposed to controls that are bound to it.

Step 9.

To change the field order from that of the database table, drag and drop the field names. For example, press the left mouse button over the City field name. Without releasing the button, move your mouse to the CompanyName field position, then release the button. The City field is now visibly positioned before the CompanyName field.

Step 10.

Close the property pages by clicking the OK button or by pressing Enter. This will save the changes you have just made for TData1. The changes are saved in the control and not to your hard disk. They will be saved to your hard disk, however, when you save the form. The Apply button saves changes without closing the property pages. Select the Cancel button to discard any changes. As with all other controls, moving between property pages implicitly applies changes.

Step 11.

Set the DataSource property of DataGrid1 to TData1. This binds the DataGrid1 control to the TData1 control. TData1 becomes the data source for the grid. Set the grid’s AllowAddNew and AllowDelete properties to True.

Run the Program and Observe the Following:

•

DataGrid1 displays data from the Customers table: CustomerID, City, and CustomerName. There is one column for each TData field marked as Visible in the property pages.

•

TData1 has thirteen buttons on it, providing useful functions that you otherwise would have had to implement with tedious manual coding. These include data management functions, such as AddNew, Delete, Update, Cancel, and two standard dialogs: Find and Bookmarks. All buttons have tooltips, so you can easily identify them. Try the Find and Bookmarks buttons. The Find dialog is easy to use and self-explanatory. To use the Bookmarks dialog, press the Bookmarks button, enter a bookmark name and press Add. Repeat this on different data rows. You will see several bookmarks listed in the Bookmarks dialog. You can jump to any of these bookmarks pressing the Go To button.

•

Try the True DataControl query mode. This is a powerful feature that adds a lot to your application without requiring a single line of code. Press the Query button on the TData control. This will switch it to query mode: DataGrid1 becomes empty and contains one data row. Add another row to DataGrid1 and enter the following data in the two rows: CompanyName = B's Beverages in the first row and City = Rio de Janeiro in the second row. Press the Query button again to leave query mode. You will see that the query is applied and its result, four rows of data, appears in DataGrid1. Go back to query mode by pressing the Query button, and delete the first row (CompanyName = B's Beverages) from the grid. Apply the query pressing the Query button again; you will see that the result has changed accordingly. Returning to query mode, enter Hanari Carnes in the CompanyName field in the same row. Switch to the result mode, and you will see that now there is only one row satisfying the query. In formal querying terms, the query conditions are connected with the logical operator AND when they belong to the same row in query mode. Different rows in query mode are connected with OR.

Close the program. Congratulations, you have successfully completed Tutorial 2!

You will learn more about True DataControl's power in the following tutorials. This tutorial was intended to familiarize you with basic usage and to provide a glimpse of True Rapid Application Development.


Tutorial 3 - Using True DataControl with Memory Data

In this tutorial you will learn how to use True DataControl with memory array data.

Step 1.

Start with the project you created in Tutorial 2, and place another TData control (TData2) on the same form (Form1). This time, we will leave its data source properties (the ones available on the DataSource property page) empty. A memory array will be used as the data source.

Step 2.

Open the True DataControl property pages dialog by clicking the right mouse button over TData2 and selecting TData Properties. On the DataSource property page, select 1 - MemoryArray in the DataMode combo box.

Step 3.

Select the Fields property page. Since there are no predefined fields in memory array mode, you must define the fields yourself, specifying the array structure. Click the right mouse button over the fields list area, and select New Field from the menu (alternatively, you can press the New button). A new field with the default name FIELD_0 appears. Change the name to A by typing it in the Name text box. Select 2 - Integer in the Data Type combo box. Then create two more fields, B and C. Repeat the steps above, but specify different data types: Date for B and Currency for C. Press the OK button to close the dialog and save changes.

Step 4.

Place another DataGrid control (DataGrid2) on the form, and set its DataSource to TData2, and AllowAddNew to True.

Run the Program and Observe the Following:

•

DataGrid2 shows the contents of an array with three fields: A (Integer), B (Date) and C (Currency). Initially the grid is empty, but data may be added. If you add data and then close and re-run the program, you will notice that the data you entered has disappeared. This is because it is stored in memory. There are provisions in True DataControl to populate a memory array with data before showing it to the user, and to save the entered data. Refer to the Array property and to the OpenData event.

•

Try to enter an incorrect number (for example, 1a) in field A, or an incorrect date in field B (anything other than date in month/day/year format would be incorrect). An error message will appear indicating the affected field and the expected data type. This is just one of True DataControl’s many useful features. True DataControl not only detects the error immediately after you have entered the wrong value, it also gives you information about the field and its data type. True DataControl even returns focus to the bound control where the invalid value has been entered (it is a DataGrid in our case, but it may be any other control such as TextBox, for example). It provides the same validation functionality for other constraints as well as for data type validation, as you will see in other tutorials.

Step 5.

Close the program, and place another TData control (TData3) on the same form (Form1). Also create three TextBox controls (Text1, Text2, and Text3), and three labels (Label1 to 3).

Set properties as follows:

TData3.ConnectionString

Provider=Microsoft.Jet.OLEDB.3.51;Persist Security

Info=False;Data Source=C:\Program Files\ComponentOne Studio\Common\TDBGDemo.mdb

TData3.CommandType 2 – adCmdTable

TData3.RecordSource Test

Text1.DataSource TData3

Text1.DataField FLOAT

Label1.Caption Float number:

Text2.DataSource TData3

Text2.DataField CURRENCY

Label2.Caption Currency:

Text3.DataSource TData3

Text3.DataField DATE

Label3.Caption Date:

Run the Program and Observe the Following:

•

A TData control can serve as a Data Source for any bound control that works in accordance with the Microsoft OLE DB data binding specification. In previous examples we used DataGrid, now we will try TextBox. You can navigate through the Test table by pressing the navigation buttons of the TData3 control. Note that the Next and Previous buttons have repeat functionality: they move current row repeatedly when the mouse button is held pressed.

•

Here you can observe the same data type validation feature as in the TData2 example. Upon entering an incorrect number or date, you will receive an error message with the field name and expected data type. Focus returns to the TextBox control where the error occurred.

Close the program. Congratulations, you have successfully completed Tutorial 3!


Tutorial 4 - Calculated Fields and True DataControl Expressions

In this tutorial, you will learn how to create a calculated field. A calculated field is one whose value is not stored directly in the database but is determined by the values of other fields. More importantly, this will be your first acquaintance with True DataControl expressions.

Step 1.

Start a new project.

Step 2.

Place the following controls on the form (Form1) as shown in the figure: two TData controls (TData1, TData2); four TextBox controls (Text1 to 4); a DataCombo control (DataCombo1, because you need to include Microsoft DataList Controls 6.0 (OLEDB) into the project’s list of components); a MaskEdBox control (MaskEdBox1; include Microsoft Masked Edit Control into the project’s list of components); and six labels (Label1 to 6).

Step 3.

Set properties as follows (you can use the DataSource property page to set TData data source properties, as described in Tutorial 2):

TData1.ConnectionString

Provider=Microsoft.Jet.OLEDB.3.51;Persist Security

Info=False;Data Source=C:\Program Files\ComponentOne Studio\Common\TDBGDemo.mdb

TData1.CommandType 2 – adCmdTable

TData1.RecordSource [Order Details]

TData2.ConnectionString

Provider=Microsoft.Jet.OLEDB.3.51;Persist Security

Info=False;Data Source=C:\Program Files\ComponentOne Studio\Common\TDBGDemo.mdb

TData2.CommandType 2 – adCmdTable

TData2.RecordSource Products

DataCombo1.DataSource TData1

DataCombo1.DataField ProductID

DataCombo1.BoundColumn ProductID

DataCombo1.RowSource TData2

DataCombo1.ListField ProductName

DataCombo1.Style 2 - dbcDropdownList

Text1.DataSource TData1

Text1.DataField OrderID

Text2.DataSource TData1

Text2.DataField UnitPrice

Text3.DataSource TData1

Text3.DataField Quantity

MaskEdBox1.DataSource TData1

MaskEdBox1.DataField Discount

MaskEdBox1.Format 0%

Set the caption properties of Label1 to Label6 as shown in the figure in Step 2.

NOTE: The use of a DataCombo control and a MaskEdBox control is not essential for the True DataControl calculated fields feature demonstrated in this tutorial. They are used to provide a more realistic example of an actual application, and to demonstrate that True DataControl can work with any type of data-bound controls. The labels, as well, are obviously not essential. The TData2 control’s only purpose is to serve as the RowSource for DataCombo1.

Step 4.

Open the True DataControl property pages by clicking the right mouse button over TData1 and selecting TData Properties. Select the Fields property page. Click the right mouse button over the fields list area and select New Field from the menu (alternatively, you can press the New button). A new field with the default name FIELD_0 appears. Change the name to ExtendedPrice by typing it into the Name text box. Select the Calculated radio button. Select Currency in the Data Type combo box.

Step 5.

Type the following in the Calculated Expression text box while the ExtendedPrice field is selected:

UnitPrice * Quantity * (1 - Discount)

This is the formula that provides the value of the ExtendedPrice calculated field. It computes the value using the values of three other fields: UnitPrice, Quantity, and Discount. These are data fields, meaning their values are actually stored in the database.

Intermission 1 - True DataControl Expression Language

The True DataControl expression language is a subset of VBScript, or Visual Basic Scripting Edition language. It is primarily the subset of VBScript that contains expressions and only expressions. You cannot use VBScript statements such as: If...Then...Else. Because of this, you cannot write full-fledged programs in this language, but you may certainly use any VBScript function and operator in your expressions. The variables you can use in True DataControl expressions are fields and parameters (parameters are fully described in Tutorial 7). You can refer to variables from an ancestor of your True DataControl if it participates in a master-detail relationship with other controls (see Tutorials 5, 6, and 7). There are also two functions, IIF and Format, that were added to the True DataControl expression language since VBScript does not support them (although they are available in Visual Basic). You will use the IIF function in some of the following tutorials.

If you are not familiar with VBScript, do not worry about needing to learn an entirely new language. It is still Visual Basic. The most significant difference is that VBScript has only one data type, Variant, making VBScript merely a simplified version of Visual Basic.

As you will see later in this tutorial, the True DataControl property pages are equipped with a special expression editor dialog to help you build an expression. The True DataControl Expression Editor enables you to browse through lists of available variables, functions and operators and paste them into the expression.

Intermission 2 - Evaluation and Re-Evaluation of True DataControl Expressions

Calculated expressions are just one type of True DataControl expression. There are other expressions that may be used and these will be introduced later in following tutorials.

Every expression is automatically evaluated at a specific and appropriate time, for each particular type of expression. Calculated expressions, for example, are evaluated to yield a calculated field value each time the value can change. The calculated expression is evaluated both when a new record is retrieved from the database, and when any of the variables in the expression changes its value.

First evaluation mode (retrieving a record) is an example of synchronous evaluation. A synchronous evaluation occurs as a part of a procedure performed by a TData control. You do not need to perform such an evaluation from code since it will be done automatically when necessary. Also, you can rely on the fact that expressions will be evaluated in their correct order. For example, if Quantity is a calculated field, the ExtendedPrice expression will be evaluated after the Quantity expression since the ExtendedPrice is dependent upon Quantity.

Second evaluation mode (on change of one of the variables used in the expression) represents asynchronous evaluation. An asynchronous evaluation is performed if a change of a variable value can cause the expression to change its value. When the TData control detects such a situation it will automatically re-evaluate the expression, without programmer’s interference. This is one of the most attractive features of the TData control, making application creation much easier. Once the user has changed one of the three fields, UnitPrice, Quantity or Discount, the ExtendedPrice field will immediately display the updated value. Please note that this is accomplished without writing a single line of code.

At the moment of synchronous evaluation of expressions, an event is also called for almost every type of a True DataControl expression. This allows you to program a more involved computation in code, if the True DataControl expression language does not satisfy your needs. For example, you can use the CalcFields event to assign values to calculated fields. The syntax for accessing a True DataControl variable is illustrated in the next step:

Step 6.

Although you are almost ready to run the program, we advise you to first review the True DataControl Expression Editor. To bring up the expression editor, press the ellipsis button located at the right edge of the Calculated Expression text box in the Fields property page. The expression editor is shown in the following figure.

You can build or edit an expression with the help of four lists of elements available in the expression: Fields, Parameters (which will be introduced in Tutorial 7), Operators, and Functions and Constants. In case there is a master TData control defined (see subsequent tutorials for an explanation of master-detail relationships), you can choose to display variables (parameters and fields) of either the TData control itself or one of its ancestors, by selecting it in the From combo box. You can also select a category of operators and functions in the two combo boxes above the lists: Operators, and Functions and Constants. Double-click on one of the elements in any of the four list boxes to paste the selected element into the expression.

Step 7.

Without closing the expression editor, try to enter invalid data in the expression. For example, type aUnitPrice instead of UnitPrice. Press the OK button to display an error message stating "Unknown variable: aUnitPrice." Alternatively, you can check the expression syntax without closing the expression editor by pressing the Check button. Leave the "aUnitPrice" error in the expression by selecting OK from the error message.

There are other ways of checking for expression syntax and other possible errors. Press the Check button located in the lower right corner of every True DataControl property page. You will receive a message box with a list of detected errors: " Field OrderID: Unknown variable: aUnitPrice - Error in calculated expression aUnitPrice." If there is more than one mistake, there will, of course, be more error messages. You can go directly to the location of the detected error by pressing the OK button or double-clicking an error message in the list. This will show the Fields page if it is not current. Select the ExtendedPrice field node, and set focus to the Calculated Expression edit box so you can correct the error there. Although most errors may occur in expressions, there are other kinds of errors that are also detectable by the syntax checking. Syntax checking is not only performed when you press the Check button, but is done automatically every time you apply changes made in the True DataControl property pages.

NOTE: Do not run your program if True DataControl syntax checking reports an error. First fix the error to ensure against unpredictable behavior.

Step 8.

Fix the error in the Calculated Expression text box so that it contains the original formula:

UnitPrice * Quantity * (1 - Discount)

Press OK to close the dialog and save changes.

Step 9.

Now, after you have created a new ExtendedPrice field, you must set it as the DataField of the Text4 control:

Text4.DataSource TData1

Text4.DataField ExtendedPrice

Run the Program and Observe the Following:

•

The ExtendedPrice field shows the value of the calculated expression. When you navigate through records using the buttons of the TData1 control, the ExtendedPrice value is updated synchronously with the other fields.

•

Change one of the three values: UnitPrice, Quantity or Discount in its corresponding TextBox control (MaskEdBox for Discount), and press Tab. The ExtendedPrice value is automatically updated immediately after focus leaves the control.

Step 10.

Close the program. Now we will experiment with the ModificationMode property of a True DataControl field. It enables you to fine-tune the behavior of your application to react to changes made by the end user. To experiment with this setting, open the property pages for the TData1 control. Go to the Fields page, highlight the Quantity field, and select 1 - Immediate in the Modification Mode combo box.

Run the Program and Observe the Following:

The ExtendedPrice is updated each time you make a change in the Quantity field without waiting for the end user to move focus out of the Quantity text box. Every keystroke in the Quantity field updates ExtendedPrice. With this example, it would probably have been more sensible to choose the Modification Mode setting 2 - Leaving Control. But there are cases where immediate update is preferable, one such case is described in the next tutorial.

Close the program. You have successfully completed Tutorial 4.


Tutorial 5 - Implementing Master-Detail Relationships

In this tutorial, you will learn how to implement master-detail relationships between TData controls. In this tutorial and the two that follow, you will dicsover how extensive and flexible the True DataControl master-detail relationship is, and how it allows you to express almost any imaginable link between different data sources in your application, without writing a line of Visual Basic code.

Step 1.

Start a new project.

Step 2.

Place the following controls on the form (Form1) as shown in the figure: two TData controls (TData1, TTData2), a DataCombo control (DataCombo1; you need to include Microsoft DataList Controls 6.0 (OLEDB) into the project’s list of components), and a DataGrid control (DataGrid1).

Step 3.

Open the True DataControl property pages for TData1. On the DataSource property page select 1 - Memory Array in the DataMode combo box.

Step 4.

Select the Fields property page. Click the right mouse button over the fields list area and select New Field from the menu (alternatively, you can press the New button). A new field with the default name FIELD_0 appears. Change the name to CustomerID by typing it in the Name text box. Select 1 - Immediate in the Modification Mode combo box for the CustomerID field. Press the OK button to close the dialog and save changes.

Step 5.

Set the properties of the other controls as follows (you can use the DataSource property page to set TData data source properties, as described in Tutorial 2):

TData2.ConnectionString

Provider=Microsoft.Jet.OLEDB.3.51;Persist Security

Info=False;Data Source=C:\Program Files\ComponentOne Studio\Common\TDBGDemo.mdb

TData2.CommandType 2 – adCmdTable

TData2.RecordSource Orders

TData3.ConnectionString

Provider=Microsoft.Jet.OLEDB.3.51;Persist Security

Info=False;Data Source=C:\Program Files\ComponentOne Studio\Common\TDBGDemo.mdb

TData3.CommandType 2 – adCmdTable

TData3.RecordSource Customers

DataCombo1.DataSource TData1

DataCombo1.DataField CustomerID

DataCombo1.RowSource TData3

DataCombo1.ListField CompanyName

DataCombo1.BoundColumn CustomerID

DataCombo1.Style 2 - dbcDropDownList

DataGrid1.DataSource TData2

NOTE: The use of a DataCombo control is not essential for the True DataControl feature (master-detail) demonstrated in this tutorial. It is meant to make the example more realistic as an application. The TData3 control’s only purpose is to serve as the RowSource for DataCombo1.

Step 6.

Open the True DataControl property pages for TData2. On the General page select TData1 in the Master combo box. This creates a master-detail relationship making TData1 the master and TData2 its dependent control (detail). This means TData2 data is dependent on TData1; therefore, each time TData1 is repositioned or one of its fields changes value, the TData2 data is re-retrieved (the control is refreshed).

Step 7.

Open the True DataControl property pages for TData2. Go to the Fields page. Select the CustomerID field. Click the right mouse button over the CustomerID field, and select New Range Condition from the menu (or use the New button). An empty range condition for the CustomerID field appears with controls for entering the condition now visible in the right part of the Fields propery page. Go to the Value Expression text box. (You can ignore the Condition text box for now. This is for entering an optional condition specifying whether to apply the range expression or to skip it.) Press the ellipsis button to open the expression editor. You should already know how to use it from Tutorial 4.

Select master: TData1 in the From combo box. The single field of TData1 is displayed in the Fields list box. Double-click it to paste TData1.CustomerID into the expression text. Select OK to close the expression editor. The expression TData1.CustomerID will appear in the Value Expression text box. Note that you can also type directly into the text box if you prefer.

Clear the Skip If Empty check box, which is checked by default. The Comparison Operator is "=" by default, which is what we will use. This concludes the specification of our range condition. The range condition you have just entered tells TData2 to include only records in which the value of CustomerID is equal to the value of the CustomerID field of TData1.

NOTE: The Fields list is empty when you select self: TData2 in the From combo box of the expression editor. This means that the fields of the TData2 control itself cannot be used in its range conditions. You can only use the control’s parameters (discussed in Tutorial 7) or the fields of an ancestor TData control ("ancestor" means master, master’s master, etc.). Range expressions are evaluated before the recordset is built, so field contents and the current record position are undetermined at that time. Conversely, fields have definite values only when the recordset is ready and positioned on a certain record. This means that fields are undetermined at the moment of range condition evaluations. Range condition expressions belong to the recordset level, as opposed to, for example, calculated expressions, which belong to the record level. Field values are known at the record level and unknown at the recordset level. Each kind of True DataControl expression belongs to either the recordset or record level.

Run the Program and Observe the Following:

•

When you choose a customer in the DataCombo1 combo box, the entire contents of DataGrid1 is updated and includes only orders placed by the selected customer. This describes how the range condition CustomerID = TData1.CustomerID works.

•

The grid is initially empty. This is because we cleared the Skip If Empty check box as part of our range condition. If this box is checked (the default setting), then the range condition is ignored when one of the variables on which it depends is empty. The feature is described further in Tutorial 6.

•

Notice that because we specified Modification Mode as 1 - Immediate for the CustomerID field of TData1, DataGrid1 is updated immediately whenever DataCombo1 changes.

•

Note the use of a TData control (TData1) to store the value of CustomerID in memory. In theory, a DataCombo could be placed on the form and a handler written for its Change control event that would refresh DataGrid. You could define a parameter in TData2 and set its value from code. Then you could refer to that parameter in a range condition. However, in most cases you can avoid writing Visual Basic code altogether by using memory array-based TData controls, making variable values available to other TData controls through master-detail relationships. This enables you to implement the necessary logic using design-time expressions instead of resorting to code, making it easier to maintain and much more reliable. True DataControl will generate the right sequence of operations, and will always update necessary variables.

Close the program. You have successfully completed Tutorial 5!


Tutorial 6 - A Common Example of a Master-Detail Relationship

The True DataControl model of the master-detail relationship is extremely extensive and flexible. It can be used to implement a variety of situations in application development that would otherwise need manual coding. Its diversity is, in fact, the focus of Tutorials 5, 6, 7, 8, 9, 13, and 14. The example by which it was introduced in the previous tutorial might not be recognized as a common case of what is usually called a "master-detail" or "one-to-many" relationship. This tutorial will furnish a more common example where the position in one data set determines data contained by another. In this example, three TData controls are connected to form a three-level master-detail chain.

Step 1.

Start a new project.

Step 2.

Place the following controls on the form (Form1) as shown in the figure: three TData controls (TData1 to 3) and three DataGrid controls (DataGrid1 to 3).

Step 3.

Set properties as follows (you can use the DataSource property page to set TData data source properties, as described in Tutorial 3):

TData1.ConnectionString

Provider=Microsoft.Jet.OLEDB.3.51;Persist Security

Info=False;Data Source=C:\Program Files\ComponentOne Studio\Common\TDBGDemo.mdb

TData1.CommandType 2 – adCmdTable

TData1.RecordSource Customers

DataGrid1.DataSource TData1

TData2.ConnectionString

Provider=Microsoft.Jet.OLEDB.3.51;Persist Security

Info=False;Data Source=C:\Program Files\ComponentOne Studio\Common\TDBGDemo.mdb

TData2.CommandType 2 – adCmdTable

TData2.RecordSource Orders

DataGrid2.DataSource TData2

TData3.ConnectionString

Provider=Microsoft.Jet.OLEDB.3.51;Persist Security

Info=False;Data Source=C:\Program Files\ComponentOne Studio\Common\TDBGDemo.mdb

TData3.CommandType 2 – adCmdTable

TData3.RecordSource [Order Details]

DataGrid3.DataSource TData3

Step 4.

Open the True DataControl property pages for TData2. On the General page select TData1 in the Master combo box. On the True DataControl property pages for TData3, in the General page, select TData2 in the Master combo box.

Step 5.

On the Fields page for TData2, select the CustomerID field. Click the right mouse button over the CustomerID field and select New Range Condition from the menu (alternatively, you can use the New button). An empty range condition for the CustomerID field appears with controls for entering the condition now visible in the right part of the page. Go to the Value Expression text box and type the following expression: TData1.CustomerID. This will create a CustomerID = TData1.CustomerID range condition for the CustomerID field.

Step 6.

Now go to the TData3 property pages and create a range condition OrderID = TData2.OrderID for the OrderID field, following the same procedure as in the previous step.

Run the Program and Observe the Following:

•

When you select an order record in DataGrid2, the contents of DataGrid3 changes to the set of Order Details records that correspond to the selected OrderID. When you select a customer record in DataGrid1, the contents of both DataGrid2 and DataGrid3 changes. DataGrid2 shows all orders placed by the selected customer, and DataGrid3 shows order details of the first order that became current in DataGrid2.

•

This is all accomplished without requiring a single line of Visual Basic code. As a matter of fact, you have not written one single line of code since you started with Tutorial 1! This is how to get the most out of True DataControl: write as little code as possible, so that your applications will be easy to create and maintain.

Close the program. You have successfully completed Tutorial 6.


Tutorial 7 - Parameters and Dynamic SQL

Tutorial 5 explained that field values are undetermined at the recordset level, since fields only receive their values at the record level. This tutorial introduces another kind of variable, a parameter, which belongs to the recordset level, so its value can be used at both the recordset and record levels.

In order to illustrate the general concept of parameters, we will show how a TData control can be used to create SQL statements with parameters that change dynamically in the course of your program execution. You will create an application that can retrieve and display orders with ItemsTotal exceeding the value that the end user enters in a text box. This application will contain only one line of code, a simple call to the Refresh method.

You may have already discovered a limitation of the standard ADO data control forbidding the use of parameterized queries for its RecordSource at design time. With the TData control, you can use parameters in SQL statements. This capability can be used to create a master-detail relationships (if parameters depend on the master field’s values), or it can be used for any other purpose where it is necessary to modify a SQL statement dynamically.

Step 1.

Start a new project.

Step 2.

Place the following controls on the form (Form1) as shown in the figure: two TData controls (TData1, TData2), a MaskEdBox control (MaskEdBox1; include Microsoft Masked Edit Control into the project’s list of components), a DataGrid control (DataGrid1), a button (Command1) and a label (Label1).

Step 3.

Open the True DataControl property pages for TData2. On the DataSource property page select 1 - Memory Array in the DataMode combo box.

Step 4.

Select the Fields property page. Create a new field by pressing the right mouse button and choosing New Field from the menu. Change the default FIELD_0 name to ItemsTotal by typing it in the Name text box. Select Currency in the Data Type combo box. Press OK to close the dialog and save changes.

Step 5.

Open the True DataControl property pages for TData1. On the DataSource property page, enter the following in the ConnectionString edit box

Provider=Microsoft.Jet.OLEDB.3.51;Persist Security

Info=False;Data Source=C:\Program Files\ComponentOne Studio\Common\TDBGDemo.mdb

or use the Build button to specify the ConnectionString, as shown in Tutorial 2, Step 4.

Step 6.

Set properties of other controls as follows:

DataGrid1.DataSource TData1

MaskEdBox1.DataSource TData2

MaskEdBox1.DataField ItemsTotal

MaskEdBox1.Format $#,##0.00

Label1.Caption Items Total >=

Command1.Caption Query

Step 7.

Open the True DataControl property pages for TData1. On the General page select TData2 in the Master combo box. Select 0 - None in the AutoRefresh combo box found on the same page.

Step 8.

For each parameter referenced in an SQL statement (such as ItemsTotalPar), you must define a corresponding True DataControl parameter (that is, a recordset-level variable). To create a new parameter, select the Parameters property page for TData1. Note that the parameter list on the left is initially empty. Click the right mouse button over the parameter list and select New from the menu (alternatively, you can press the New button). A new parameter with the default name PARAM_0 will appear. Change the name to ItemsTotal by typing it into the Name text box. Select Currency in the Data Type combo box. You have now created an ItemsTotal parameter. Click the OK button to close the dialog.

Step 9.

Open the TData1 Property Pages, and go to the Parameters page. Specify a Value Expression for the ItemsTotal parameter to maintain the parameter’s value in sync with the ItemsTotal field of the master TData control, TData2.ItemsTotal. Press the ellipsis button located on the right edge of the Value Expression text box to access the expression editor. The parameter, ItemsTotal, now appears in the Parameters list, but the Fields list is empty. This is because the From combo box is set to self: TData1; as explained in Tutorial 3, fields are inaccessible for recordset-level expressions. Select master: TData2 in the From combo box and double-click the ItemsTotal field that now appears in the Fields list. Press the OK button. You have now specified TData2.ItemsTotal for the parameter’s Value Expression. You can also type expressions directly into the text box without using the expression editor.

Step 10.

To complete the parameter definition, associate the ItemsTotal parameter with the ItemsTotalPar used in the SQL text. Type ItemsTotalPar in the SQL Name text box. This will tell the TData1 control that this parameter is used in conjuction with the ItemsTotalPar parameter of the SQL statement.

Note: If you have multiple parameters in the SQL statement, the order of True DataControl parameters defined in the Parameters property page must be synchronized with the order of parameters in the SQL statement. Use drag-and-drop in the Parameters page to change the order of parameters.

Step 11.

Select 1 – adCmdText in the CommandType combo box (on the TData1 DataSource property page). This will enable the Command Text (SQL) edit box. Type the following parameterized SQL statement there:

PARAMETERS ItemsTotalPar Value;

SELECT * FROM Orders

WHERE -ItemsTotalPar > (

SELECT -SUM(UnitPrice*Quantity)

FROM [Order Details]

WHERE

[Order Details].OrderID = Orders.OrderID

)

You will see this SQL text in the RecordSource property of TData1 in the Visual Basic Properties window.

NOTE: We used “-ItemsTotalPar >…” instead of “ItemsTotalPar <…” to overcome a bug in the Microsoft Jet SQL engine.

Step 12.

Add the following code to Command1:

Private Sub Command1_Click()

TData1.Refresh

End Sub

Run the Program and Observe the Following:

Type 2000 in the ItemsTotal >= masked edit box. Press the Query button to display the grid, which shows orders satisfying the ItemsTotal >= $2,000.00 condition. This result was achieved as follows:

1. Shifting focus from the edit control to the Query button (after typing 2000 in the edit box) sets the ItemsTotal field of TData2 to 2000.

2. The Refresh method causes the TData1 recordset to be re-populated with new data. Before doing that, TData1 sets its parameter, ItemsTotal to the result of its ValueExpression TData2.ItemsTotal, which is 2000.

3. When TData1 recordset is rebuilt, the value of the ItemsTotalPar SQL parameter is set to the value of the ItemsTotal parameter, which has already been set to 2000.

Type 4000 in the ItemsTotal >= masked edit box, and press Tab. Focus will leave the masked edit box control, but grid refresg will not occur. This is because we specified AutoRefresh as 0 - None for TData1. If AutoRefresh were set to either 1 - Immediate or 2 - When Idle (the default), then changing the contents of the masked edit box and moving focus to another control would automatically refresh TData1.

Close the program. You have successfully completed Tutorial 7.


Tutorial 8 - Ad-hoc Queries Using True DataControl Range Conditions

When implementing query forms, True DataControl eliminates the need to write tedious statement building code such as this:

If RequiredDateFrom.Text <> "" Then SQL = SQL & _

" RequiredDate >= #" & RequiredDateFrom.Text & "#"

If RequiredDateTo.Text <> "" Then SQL = SQL & _

" RequiredDate <=" & RequiredDateTo.Text & "#"

True DataControl enables you to easily create ad-hoc query forms that gather information from the end user and issue a dynamic SQL query according to that information. A powerful method of creating ad-hoc query forms is the True DataControl query mode feature that will be presented in Tutorials 15 and 16.

Sometimes, however, the ad-hoc query is not the main purpose of a form, but rather an optional restriction that the user wants to be able to impose on the data. In this case, you can use True DataControl range conditions. We have selected such an example for this tutorial, because it illustrates several central True DataControl concepts, such as master-detail relationships and range conditions. By now, you must have noticed that in most cases there are several different ways to achieve application goals with True DataControl. This is true, and it proves that different True DataControl features are general, flexible and interdependent enough to create infinite possibilities in application development.

Step 1.

Start a new project.

Step 2.

Place the following controls on the form (Form1) as shown in the figure: two TData controls (TData1, TData2), five TextBox controls (Text1 to 5), a DataGrid control (DataGrid1), a button (Command1), two frames (Frame1, Frame2) and five labels (Label1 to 5).

Step 3.

Set the DataMode property of TData2 to 1 - MemoryArray and define five fields: RequiredDate1, RequiredDate2, ShippedDate1, ShippedDate2 (all four with Data Type set to 7 - Date) and ShipName (8 - String). Follow these steps:

Open the True DataControl property pages for TData2. On the DataSource page select 1 - Memory Array in the DataMode combo box. Select the Fields page. For each of the five fields, create a new field by clicking the right mouse button and choosing New Field from the context menu. Change the default FIELD_0 name to the appropriate field name by typing it in the Name text box. Select the appropriate type in the Data Type combo box.

Step 4.

Set the properties of the other controls as follows (you can use the DataSource property page to set TData data source properties, as described in Tutorial 3):

TData1.ConnectionString

Provider=Microsoft.Jet.OLEDB.3.51;Persist Security

Info=False;Data Source=C:\Program Files\ComponentOne Studio\Common\TDBGDemo.mdb

TData1.CommandType 2 – adCmdTable

TData1.RecordSource Orders

DataGrid1.DataSource TData1

Text1.DataSource TData2

Text1.DataField RequiredDate1

Text2.DataSource TData2

Text2.DataField RequiredDate2

Text3.DataSource TData2

Text3.DataField ShippedDate1

Text4.DataSource TData2

Text4.DataField ShippedDate2

Text5.DataSource TData2

Text5.DataField ShipName

Set the captions of the five labels, two frames, and the button according to the picture.

Step 5.

Open the True DataControl property pages for TData1. On the General property page select TData2 in the Master combo box, and select 0 - None in the AutoRefresh combo box.

Step 6.

Go to the Fields property page of TData1. Select the RequiredDate field. Click the right mouse button over the RequiredDate field and select New Range Condition from the menu (alternatively, you can use the New button). An empty range condition for the RequiredDate field appears with controls for entering the condition now visible in the right part of the page. Select >= in the Comparison Operator combo box. Go to the Value Expression text box and type the following expression: TData2.RequiredDate1. This will create a RequiredDate <= TData2.RequiredDate1 range condition for the RequiredDate field.

Step 7.

Now create four more range conditions following the procedure from the previous step. For RequiredDate1:

RequiredDate <= TData2.RequiredDate2

(select <= from the Comparison Operator combo box).

For ShippedDate1:

ShippedDate >= TData2.ShippedDate1

ShippedDate <= TData2.ShippedDate2

For ShipName:

ShipName starts with TData2.ShipName

(select StartsWith from the Comparison Operator combo box).

Press OK to close the property pages dialog.

Step 8.

Add the following code to Command1:

Private Sub Command1_Click()

TData1.Refresh

End Sub

Run the Program and Observe the Following:

•

Type 10/1/94 in the RequiredDate From text box and 10/10/94 in the RequiredDate To text box. Press the Apply button. The grid now displays orders satisfying the condition imposed on RequiredDate.

•

Since the Skip If Empty box was left checked (its default state) for all fields, the applicable range conditions were ignored whenever one of their dependent variables was empty. This is how TData1 knew to apply only one of five range conditions, namely RequiredDate >= 10/1/94. Otherwise, all five would have been applied and the result would appear empty.

•

Type M in the ShipName starts with text box and press Apply. The grid narrows orders further to show only those where the ShipName field starts with M.

•

Clear the ShipName starts with text box and press Apply. The grid returns to its previous state (before you entered M).

•

Experiment with all five values (including ShippedDate) and discover a fully functional ad-hoc query application created with just one line of code.

•

Note that when you modify the value in any of the five text box controls and press Tab, focus leaves the control, but the grid does not change its contents. This is because AutoRefresh was set to 0 - None. You need to click the Apply button to perform an explicit Refresh. See Tutorial 7 for a discussion of the AutoRefresh property.

Close the program. You have successfully completed Tutorial 8.


Tutorial 9 - Automatic Updating of Control Properties

This tutorial demonstrates the correlation between control properties and True DataControl expressions. For instance, if a button should be enabled if, and only if, a variable Name is nonempty, why not set the button’s Enabled property in the Properties window to:

Name <> ""

Unfortunately, Visual Basic does not support this, but True DataControl does!

Step 1.

Start a new project.

Step 2.

Place the following controls on the form (Form1) as shown in the figure: a TData control (TData1), a DataGrid control (DataGrid1), six TextBox controls (Text1 to 6) and six labels (Label1 to 6).

Step 3.

Set properties as follows (you can use the DataSource property page to set TData data source properties, as described in Tutorial 1):

TData1.ConnectionString

Provider=Microsoft.Jet.OLEDB.3.51;Persist Security

Info=False;Data Source=C:\Program Files\ComponentOne Studio\Common\TDBGDemo.mdb

TData1.CommandType 2 – adCmdTable

TData1.RecordSource Orders

DataGrid1.DataSource TData1

Text1.DataSource TData1

Text1.DataField OrderID

Text2.DataSource TData1

Text2.DataField RequiredDate

Text3.DataSource TData1

Text3.DataField ShippedDate

Text4.DataSource TData1

Text4.DataField ShipName

Text5.DataSource TData1

Text5.DataField ShipCountry

Text6.DataSource TData1

Text6.DataField ShipRegion

Set the label captions as shown in the picture.

Step 4.

Open the True DataControl property pages for TData1 and go to the Property Expressions page. The Available Controls tree displays a hierarchical outline of all controls existing on your form. Expand some of them by clicking the plus sign (+) or pressing the plus sign on the numeric keypad. Properties that return objects (such as Font) can be expanded further to reveal their constituent properties. Select and expand the Label6 control. Next, select its Caption property. The name of the property, Label6.Caption, will appear in the Property text box. Press the New button or select New from the context menu to enable the Value Expression edit control and its adjacent ellipsis button.

Step 5.

Type the following text into the Value Expression text box:

IIF(ShipCountry = "USA", "State:", "Region:")

The following setting is added to the properties area in the left part of the page:

Label6.Caption = IIF(ShipCountry = "USA", "State:", "Region:")

Here IIF(Condition, Value1, Value2) returns Value1 if Condition is True and Value2 otherwise. This is all you need to make the Caption property of Label6 assume one of two values according to the value of the ShipCountry field of TData1. The caption will be automatically set to State: when ShipCountry = ”USA” and Region: when ShipCountry <> “USA”.

Step 6.

Add two more property expressions following the steps above:

Text3.Font.Bold = RequiredDate - ShippedDate < 10

Text2.BackColor = IIF(RequiredDate - ShippedDate > 20, &H000000FF&, &H80000005&)

Press Apply to save the changes.

Step 7.

Go to the Fields property page and change the order of fields by dragging the ShipCountry field and dropping it before the EmployeeID field. This operation is not essential for our tutorial; it is intended only to make the ShipCountry field appear in the grid before fields that are less relevant.

Run the Program and Observe the Following:

•

Set focus to the grid and press the down arrow key several times to visit several records following the first. Observe that ShippedDate is displayed in bold, and RequiredDate is displayed on a red background in accordance with the conditions specified at design time in Step 6. Select a record where ShipCountry = USA and observe that the label below Country changes from Region: to State: as specified in Step 5.

•

Please note that this tutorial was performed without requiring you to write a single line of code!

•

An important consideration is that you can use this feature of True DataControl not only in database applications, but in building any kind of application with a user interface. It is often difficult to keep all properties of all controls in sync with one another and with the constraints and conditions the application logic dictates. True DataControl property expressions can make such interfaces simpler, more reliable, and easier to maintain.

Close the program. You have successfully completed Tutorial 9.


Tutorial 10 - Using Filter Conditions

This tutorial describes how to restrict the recordset by imposing a filter condition. Along with range conditions (Tutorial 6) and SQL parameters (Tutorial 7), this is another technique that you can use to implement a master-detail relationship. Filter conditions can also supplant the WHERE clause of an SQL statement, but for performance reasons this is not recommended for database data sources (with DataMode = 0 - DataSource), as filter conditions are tested on every record retrieved.

Step 1.

Start a new project.

Step 2.

Place the following controls on the form (Form1) as shown in the figure: two TData controls (TData1, TData2), a DataGrid control (DataGrid1), a TextBox control (Text1), a label (Label1) and a button (Command1).

Step 3.

Set up TData2 as a memory array data source with one field as follows:

Open the True DataControl property pages for TData2. On the DataSource property page select 1 - MemoryArray in the DataMode combo box. Select the Fields property page. Create a new field by clicking the right mouse button and choosing New Field from the menu. Change the default FIELD_0 name to Interval by typing it in the Name text box. Select 2 - Integer in the Data Type combo box.

Step 4.

Set the properties of the other controls as follows (you can use the DataSource property page to set TData data source properties, as described in Tutorial 2):

TData1.ConnectionString

Provider=Microsoft.Jet.OLEDB.3.51;Persist Security

Info=False;Data Source=C:\Program Files\ComponentOne Studio\Common\TDBGDemo.mdb

TData1.CommandType 2 – adCmdTable

TData1.RecordSource Orders

DataGrid1.DataSource TData1

Text1.DataSource TData2

Text1.DataField Interval

Label1.Caption RequiredDate – ShippedDate >

Command1.Caption Apply Filter

Step 5.

Open the True DataControl property pages for TData1. On the General proeprty page, select TData2 in the Master combo box and select 0 - None in the AutoRefresh combo box.

Step 6.

Go to the Filters property page of TData1. Create a new filter by right-clicking the filter list on the left side of the page and choosing New from the context menu (alternatively, you can use the New button). This enables the expression editing controls on the right side of the page. Type the following text into the Filter Expression box:

RequiredDate - ShippedDate > TData2.Interval

Type the following text into the Condition box:

Not IsEmpty(TData2.Interval)

As described in previous tutorials, you can also use the True DataControl Expression Editor to build the expression.

You have created a filter condition that reads as:

(if (Not IsEmpty(TData2.Interval)) RequiredDate - ShippedDate > TData2.Interval

This means that:

1.

The condition will be applied only if TData2.Interval is not empty.

2.

In this case, TData1 will only include records where RequiredDate - ShippedDate > TData2.Interval.

More than one filter condition may be imposed. Usually, each filter is accompanied by a condition specifying its applicability, as in this example.

Step 7.

Go to the General property page and check the Filtered check box.

IMPORTANT!

If you omit this step, all filters will be ignored!

Step 8.

Add the following code to Command1:

Private Sub Command1_Click()

TData1.Refresh

End Sub

The Refresh method and its connection to the AutoRefresh property were discussed in Tutorial 8.

Run the Program and Observe the Following:

•

Enter a number (for example, 20) into the edit control at the top of the form, then click on the Apply Filter button. The grid includes only the rows that satisfy the condition. Enter different numbers (for example, 1) into the edit control and see how they affect the record display.

•

Clear the edits control and click on Apply Filter button. The grid now shows all orders because the filter was specified as applicable only if TData2.Interval is not empty.

Close the program. You have successfully completed Tutorial 10.


Tutorial 11 - Imposing Constraints and Related Issues

This tutorial explains how to specify constraint expressions for individual fields as well as for the whole record. It also describes how to specify default values for fields in a new record, how to use the Required and ReadOnly properties of a True DataControl field, and how to cancel pending edits using the CancelUpdate method.

Step 1.

Start a new project.

Step 2.

Place the following controls on the form (Form1) as shown in the figure: a TData control (TData1), four TextBox controls (Text1 to 4), four labels (Label1 to 4) and a button (Command1).

Step 3.

Set properties as follows (you can use the DataSource property page to set TData data source properties, as described in Tutorial 1):

TData1.ConnectionString

Provider=Microsoft.Jet.OLEDB.3.51;Persist Security

Info=False;Data Source=C:\Program Files\ComponentOne Studio\Common\TDBGDemo.mdb

TData1.CommandType 2 – adCmdTable

TData1.RecordSource Employees

Text1.DataSource TData1

Text1.DataField FirstName

Text2.DataSource TData1

Text2.DataField LastName

Text3.DataSource TData1

Text3.DataField BirthDate

Text4.DataSource TData1

Text4.DataField HireDate

Command1.CausesValidation False

Set label and button captions as shown in the picture.

Step 4.

Open the True DataControl property pages for TData1. Go to the Fields page, and select the HireDate field. Type Date in the Default Expression text box to specify a default value for the HireDate field when new records are added.

Step 5.

Click the right mouse button over the HireDate field and select New Constraint from the context menu (alternatively, you can use the New button). An empty constraint expression for the HireDate field appears indented beneath the field name in the list, and the field controls on the right side of the page are replaced with expression editing controls. Go to the Constraint Expression text box and enter the following expression:

HireDate <= Date

(You can ignore the Condition text box for now. This is used for entering an optional condition specifying whether to apply the constraint expression or to skip it.)

Type the following text into the Message Expression text box:

"Hire date can't be in the future"

This completes the constraint definition for the HireDate field.

Step 6.

Go to the Constraints property page. Create a new constraint by clicking the right mouse button over the constraints area (left part of the page) and choosing New from the context menu (alternatively, you can use the New button). The expression editing controls on the right side of the page become available. Type the following text into the Constraint Expression text box:

IsEmpty(HireDate) or HireDate >= BirthDate

Type the following text into the Message Expression text box:

"You can't hire a person who is not born"

This completes the constraint definition for the entire record.

Step 7.

Return to the Fields property page. Select the BirthDate field. Check the Required check box, which is unchecked by default.

Step 8.

Select the LastName field. Check the ReadOnly check box, also unchecked by default. Repeat this step for the FirstName field.

Step 9.

Go to the General property page and check the AddNew check box in the Buttons group. We will need the AddNew button to add records.

Step 10.

Add the following code to Command1:

Private Sub Command1_Click()

TData1.CancelUpdate

End Sub

Run the Program and Observe the Following:

•

In the first record (employee Nancy Davolio) enter 1/1/2000 in the HireDate field (its original value is 6/4/92). Press Tab twice, or click on another control with the mouse. The error message: "Hire date can’t be in the future" will appear in accordance with the constraint imposed on the HireDate field in Step 5. Note that regardless of whether you answer Yes or No to the question: "Would you like to restore the previous value?", focus is returned to the control where the error occurred. You are not allowed to leave the field unless you correct the error.

•

Enter 12/8/40 in the HireDate field. Press Tab or click another control with the mouse. Although the entered date is incorrect (less than BirthDate), you are allowed to leave the control. This is because the corresponding constraint is a record-level constraint; it is checked only when you leave the record or post the change to the database. Now, try to move to another record with the TData1’s Next button. The error message: "You can't hire a person who is not born" will be displayed in accordance with the record-level constraint imposed in Step 6.

•

Click the UndoRecord button. This executes the CancelUpdate method, which restores all fields to their original value, canceling all changes that the end user has made since the record was retrieved from, or saved to, the database. The original HireDate reappears: 6/4/92.

•

Note that the UndoRecord button received focus when it was clicked, even though Text4 contained an invalid HireDate at that point. Normally, an invalid value would not be permitted in a bound control, and clicking a command button would trigger the same error message as moving to another grid row. However, because the UndoRecord button (Command1) has CausesValidation=False, it can receive focus without forcing field update. You can use the CauseValidation property for controls (such as Help or Undo buttons) that should always be made available to the end-user.

•

Clear the BirthDate value from Text3. Then press Tab or click another field in the same row with the mouse. The error message: "Field BirthDate can’t be left empty" will appear as specified by the Required property in Step 7. Click the UndoRecord button to restore the previous value.

•

Try to change FirstName or LastName. You will not be allowed to do it, in accordance with the ReadOnly property you specified for these fields in Step 8. You will, however, get an ugly “Binding Collection Error” message box, but that comes from the standard Visual Basic TextBox control. Other, more sophisticated data-bound controls will honor the ReadOnly property in a decent way, without popping up messages.

•

Press the Add button on the TData1 control to add a new row. The HireDate field in the newly created row will be automatically set to today’s date as returned by the VBScript function Date, which was specified in the Default Expression for the HireDate field in Step 4.

Close the program. You have successfully completed Tutorial 11.


Tutorial 12 - One-to-One Links and Linked Fields

This tutorial describes how to create one-to-one links between two TData controls. In a one-to-one link, a dependent TData control always has at most one record for each record of its master TData control. Under such circumstances, linked fields can be defined in the master control and associated with fields in the dependent (linked) control. Linked fields appear in the master’s records along with "normal" data and calculated fields. They can participate in expressions and can even be modified. A TData control can have multiple linked controls.

The effect of a one-to-one link in a database context can be achieved by other means, namely, by joining multiple tables in SQL. The advantage of the True DataControl one-to-one link is its generality. You can use True DataControl expressions, which are more general than SQL, and you can add arbitrary code to the WillOpenData and OpenData events. The disadvantage is that one-to-one links are not nearly as efficient as SQL JOINs, which makes them unsuitable for large-scale database applications. One-to-one links are ideal for memory-based data sources, however, as Tutorial 12 demonstrates.

To create a one-to-one link, perform the following steps:

•

Create a special TData control, declaring it to be a linked control by setting its LinkType property to 1 - Outer or 2 - LinkInner (the default setting is 0 - None), and specify the principal TData control as its Master.

•

Set up a master-detail relationship by means of range conditions, parameterized SQL, or filter conditions, so that the linked control will have no more than one record per master record. (For efficiency reasons, the use of filters is discouraged.)

•

Add linked fields to the master TData control and associate each linked field with a field of the linked TData control.

A linked control cannot be used as an independent TData control (that is, data-aware controls cannot be bound to it) because it is managed in all respects by its Master control. That is why, if you set the LinkType property to something other than 0 - None, the functionality of the TData control will be restricted. For example, all fields must be data fields; calculated and linked fields are not permitted. In essence, a linked TData control is an addition to its master control.

Outer links allow master records for which there is no corresponding record in the linked control. If this happens, all linked fields are empty and cannot be modified. Inner links filter such master records out, excluding them from the recordset. The terms "outer" and "inner" are comparable to outer and inner joins in SQL.

The following example demonstrates how to add a CustomerName field to a TData control (TData1) based on an Orders table, which does not contain the name. This can be done by creating a linked TData control (TData2) based on the Customers table and connecting it to the master control with the range condition TData2.CustomerID = TData1.CustomerID.

Step 1.

Start a new project.

Step 2.

Place the following controls on the form (Form1) as shown in the figure: two TData controls (TData1, TData2) and a DataGrid control (DataGrid1).

Step 3.

Set properties as follows (you can use the DataSource property page to set TData data source properties, as described in Tutorial 2):

TData1.ConnectionString

Provider=Microsoft.Jet.OLEDB.3.51;Persist Security

Info=False;Data Source=C:\Program Files\ComponentOne Studio\Common\TDBGDemo.mdb

TData1.CommandType 2 – adCmdTable

TData1.RecordSource Orders

TData2.ConnectionString

Provider=Microsoft.Jet.OLEDB.3.51;Persist Security

Info=False;Data Source=C:\Program Files\ComponentOne Studio\Common\TDBGDemo.mdb

TData2.CommandType 2 – adCmdTable

TData2.RecordSource Customers

DataGrid1.DataSource TData1

Step 4.

Open the True DataControl General property pages for TData2. Select TData1 in the Master combo box. Select 1 - Outer in the LinkType combo box. You have specified TData2 as linked to the master TData1 control.

Step 5.

Go to the Fields property page for TData2. Select the CustomerID field. Click the right mouse button over the CustomerID field and select New Range Condition from the context menu. Type the following text in the Value Expression text box:

TData1.CustomerID

You have specified a range condition

TData2.CustomerID=TData1.CustomerID

that will ensure that only one TData2 record corresponds to any given TData1 record.

Step 6.

Open the True DataControl property pages for TData1. Go to the Fields page. Create a new field by clicking the right mouse button and selecting New Field from the context menu. Change the default FIELD_0 name to CustomerName by typing it in the Name text box. Select the Linked radio button. Select TData2.CompanyName from the Linked Field combo box (note that the combo’s label automatically changed from DataSource Field to Linked Field when you selected the Linked radio button). Finally, drag the CustomerName field from the last position in the field list and drop it to the position before EmployeeID. Press OK to close the property pages and save changes. You have created a linked field CustomerName based on the CompanyName field of TData2.

Run the Program and Observe the Following:

The CompanyName information is displayed in the grid along with the CustomerID. This field is not part of the Orders table on which TData1 is based; it is derived from the Customers table that is linked to the Orders table using the range condition specified in Step 5.

Close the program. You have successfully completed Tutorial 12.


Tutorial 13 - One-to-One Links and Memory-Based Controls

Previous tutorials described the use of memory-based TData controls; that is, those with their DataMode property set to 1 - MemoryArray. This tutorial presents a more elaborate example of memory data sources, explaining how to fill memory arrays with data prior to presenting them to the user. The OpenData event is typically used to assign a pre-initialized array to a TData control.

Additionally, this tutorial demonstrates master-detail relationships and one-to-one links in the context of memory-based TData controls. The techniques used with memory-based controls work in exactly the same general way as they do with database data sources.

In this tutorial, we create an application with two grids: one of them showing a list of countries, and the other showing a list of cities that lie within the country currently selected in the first grid. The cities grid also displays the country name, which is related to each city record by means of a one-to-one link.

Step 1.

Start a new project.

Step 2.

Place the following controls on the form (Form1) as shown in the figure: three TData controls (TData1 to 3) and two DataGrid controls (DataGrid1, DataGrid2).

Step 3.

Set properties as follows:

DataGrid1.DataSource TData1

DataGrid1.AllowAddNew True

DataGrid2.DataSource TData2

DataGrid2.AllowAddNew True

Step 4.

Set the DataMode property of TData1 to 1 - MemoryArray and define two fields: CountryNo and Country, with Data Type set to 2 - Integer and 8 - String, respectively. Follow these steps:

Open the True DataControl property pages for TData1. On the DataSource property page select 1 - MemoryArray in the DataMode combo box. Go to the Fields page. For each of the two fields, create a new field by clicking the right mouse button and choosing New Field from the context menu. Change the default FIELD_0 name to the appropriate field name by typing it in the Name text box. Select the appropriate type in the Data Type combo box. Press OK to apply the changes.

Step 5.

Set the DataMode property of TData2 to 1 - MemoryArray and define three fields with the following Name and Data Type settings: CountryNo (2 - Integer), City (8 - String), and Population (3 - Long). Refer to the previous step if necessary. On the General page, specify TData1 as the Master of TData2. Next, go to the Fields page and add a range condition to the CountryNo field by right-clicking it and selecting New Range Condition from the context menu. Type:

TData1.CountryNo

in the Value Expression text box and

TData1.CountryNo <> 0

in the Condition text box located to the right of it. This creates a range condition, TData2.CountryNo = TData1.CountryNo, connecting TData2 to its master, TData1. However, the range condition does not apply when TData1.CountryNo = 0, (that is, when Country = All).

Step 6.

Set the DataMode property of TData3 to 1 - MemoryArray and define two fields: CountryNo and Country, with Data Type set to Integer and String, respectively. Follow the same instructions given in Step 4.

Step 7.

Open the True DataControl property pages for TData3. Select TData2 in the Master combo box in the General page. Select 1 - Outer in the LinkType combo box. TData3 is now specified as linked to the master TData2 control.

Step 8.

Create a range condition for the CountryNo field of TData3:

TData3.CountryNo = TData2.CountryNo

Refer to Step 5 if necessary. This range condition will ensure that exactly one TData3 record corresponds to any given TData2 record. Note that TData3 and TData1 represent the same array: Countries. The code to be added to the form will reflect this. Press OK to apply the changes.

Step 9.

Open the True DataControl property pages for TData2. Go to the Fields page and create a new field called CountryName. Click on the Linked radio button and select TData3.Country from the Linked Field combo box. Drag the CountryName field from the last position in the field list and drop it to the position before City. Press OK to save changes. A linked field, CountryName, has been created based on the Country field of TData3.

The ComponentOne XArrayDB Object must be added to this project in order to provide pre-initialized data for the memory-based TData controls.

Step 10.

From the Project menu, Select References... to display a list of available type library references. Check the box labeled ComponentOne XArrayDB Object (xadb8.ocx), then press the OK button.

Step 11.

Declare two variables of type XArrayDB in the Declarations section of the form:

Dim Countries As New XArrayDB

Dim Cities As New XArrayDB

XArrayDB is a special ActiveX object used to implement memory-based storage in TData controls. Other ComponentOne products, such as True DBGrid and True DBList also use it.

Step 12.

Add the following code to the Form_Initialize event:

Private Sub Form_Initialize()

CountriesArray = Array("All", "Canada", "USA")

Countries.ReDim LBound(CountriesArray), UBound(CountriesArray), 1, 2

For I = LBound(CountriesArray) To UBound(CountriesArray)

Countries(I, 1) = I

Countries(I, 2) = CountriesArray(I)

Next I

CityNames = Array("New York", "Chicago", "Toronto", "Montreal")

CountryNumbers = Array(2, 2, 1, 1)

Population = Array(10000000, 5000000, 4000000, 3000000)

Cities.ReDim LBound(CityNames), UBound(CityNames), 1, 3

For I = LBound(CityNames) To UBound(CityNames)

Cities(I, 1) = CountryNumbers(I)

Cities(I, 2) = CityNames(I)

Cities(I, 3) = Population(I)

Next I

End Sub

This code fills the two XArrayDB objects, Countries and Cities, with data.

Step 13.

Connect all three TData controls to their corresponding XArrayDB data sources by setting the Array property in their OpenData events:

Private Sub TData1_OpenData()

Set TData1.Array = Countries

End Sub

Private Sub TData2_OpenData()

Set TData2.Array = Cities

End Sub

Private Sub TData3_OpenData()

Set TData3.Array = Countries

End Sub

Note that TData1 and TData3 are actually connected to the same array data source.

The OpenData event is fired each time a TData control is about to be populated with data. This is where a pre-filled XArrayDB object should be assigned, so the TData control will already have some data before any controls that are bound to it are displayed.

Run the Program and Observe the Following:

•

One grid displays countries and the other displays cities of the currently selected country. If you select All in the first grid, the second grid displays all cities.

•

The Cities array does not contain CountryName information, it is linked to it by means of the TData3.CountryNo = TData2.CountryNo correspondence.

Close the program. You have successfully completed Tutorial 13.


Tutorial 14 - Creating Custom Data Sources in Code

This tutorial demonstrates how to create your own data source by programming event procedures for special True DataControl events. Since the subject of this tutorial is an advanced True DataControl feature, it will be necessary for you to have extensive programming experience to fully comprehend this tutorial. With that in mind, this tutorial presents a brief introduction, followed by a complete code sample.

As described in the previous tutorials, True DataControl's DataMode property specifies the nature of the control’s data source. If DataMode is 0 - DataSource, the control has its data source in a database or any other OLE DB data provider. If DataMode is 1 - MemoryArray, the control stores its data internally in a dedicated XArrayDB object.

The third DataMode setting, 2 - UserEvents, is intended for custom data sources that don’t have a readily available OLE DB provider or for cases where a large volume of data precludes array-based storage. In user events mode, True DataControl gives you full control over the data and sends notifications whenever bound controls request that data be retrieved, updated, added, or deleted. You respond to these notifications by implementing handlers for special True DataControl events: UserReadData, UserWriteData, UserAddData, UserDeleteRow.

UserReadData is fired whenever True DataControl needs to retrieve data from your custom data source. In response, you provide data for the number of rows requested, or for as many rows as you can, if an end-of-file is encountered. Row data consists of the values for each field in the row as well as a bookmark that uniquely identifies the row.

UserWriteData is fired when the end-user has modified some fields in the current row and these changes must be saved to your custom data source.

UserAddData is fired when the end user has added a new row, which must be saved to your custom data source. Your event handler must also provide a bookmark that uniquely identifies the newly added row.

UserDeleteRow is fired when the end user has deleted a row and your custom data source must update itself accordingly.

A special object, RowBuffer, is used to pass row information to and from the event procedures. RowBuffer is essentially an array of rows, each holding a bookmark and the data values for all fields. In response to the UserReadData event, you return rows to the TData control by filling an empty RowBuffer object, passed as a parameter, with retrieved bookmarks and values. In the UserWriteData and UserAddData events, True DataControl passes as a parameter a RowBuffer object containing the modified field values, which your event handler then uses to update your custom data source.

To use True DataControl in user events mode, you must set the DataMode property to 2 - UserEvents on the DataSource property page (or in the Visual Basic Properties window).

Next, you must define fields that will form the structure of your data. This is done using the Fields property page, just as if you were specifying fields for a memory-based data source (as in Tutorial 13). You can also specify fields at run time, using the collection returned by the Fields property.

Step 1.

Start a new project.

Step 2.

Place the following controls on the form (Form1) as shown in the figure: two TData controls (TData, TData2) and two DataGrid controls (DataGrid1, DataGrid2).

Step 3.

Set properties as follows:

DataGrid1.DataSource TData1

DataGrid1.AllowAddNew True

DataGrid1.AllowDelete True

DataGrid2.DataSource TData2

DataGrid2.AllowAddNew True

DataGrid2.AllowDelete True

Step 4.

Set the DataMode property of TData1 to 2 - UserEvents and define two fields: CountryNo and Country, with Data Type set to 2 - Integer and 8 - String, respectively. Follow these steps:

Open the True DataControl property pages for TData1. On the DataSource property page select 2 - UserEvents in the DataMode combo box. Select the Fields property page. For each of the two fields, create a new field by clicking the right mouse button and choosing New Field from the context menu. Change the default FIELD_0 name to the appropriate field name by typing it in the Name text box. Select the appropriate type in the Data Type combo box. Press OK to save changes.

Step 5.

Set the DataMode property of TData2 to 2 - UserEvents and define three fields with the following Name and Data Type settings: CountryNo (Integer), City (String), and Population (Long). Refer to the previous step if necessary. On the General property page, specify TData1 as the Master of TData2. Next, go to the Fields property page and add a range condition for the CountryNo field by right-clicking it and selecting New Range Condition from the context menu. Type:

TData1.CountryNo

in the Value Expression text box and

TData1.CountryNo <> 0

in the Condition text box located to the right of it. This creates a range condition, TData2.CountryNo = TData1.CountryNo, connecting TData2 to its master, TData1. However, the range condition does not apply when TData1.CountryNo = 0, (that is, when Country = All). Click OK to close the property pages.

Step 6.

Paste the following source code into the project, which can be found in Tutor14 in the TUTORIAL directory.

'VB arrays storing our data

Dim CountryNumbers, Countries, CityNames, CityCountryNumbers, CityPopulation As Variant 'VB arrays storing our data

Dim Begin, Last As Long

Private Sub Form_Initialize()

'Fill the storage arrays. In this simplified example correspondence

'between the arrays is obtained simply by putting corresponding data in the same index position.

'And we don't bother to fill the arrays with real data.

CountryNumbers = Array(0, 1, 2)

Countries = Array("All", "Canada", "USA")

CityNames = Array("New York", "Chicago", "Toronto", "Montreal")

CityCountryNumbers = Array(2, 2, 1, 1)

CityPopulation = Array(10000000, 5000000, 4000000, 3000000) 'not real numbers, of course

End Sub

Private Sub Form_Load()

TData1.ApproxCount = UBound(CountryNumbers) - LBound(CountryNumbers) + 1

End Sub

Private Sub TData1_UserReadData(ByVal RowBuf As TrueData60Ctl.RowBuffer, ByVal StartLocation As Variant, ByVal Offset As Long, ApproximatePosition As Long)

'The ReadData event functionality for TData1 and TData2 has much in common,

'that's why it is encapsulated in a ReadData function.

'The ReadData function fills two variables: Begin and Last, so we know where to get

'the data in the storage arrays

If ReadData(RowBuf, StartLocation, Offset, Countries) Then

For I = Begin To Last

'Now we just need to copy data from storage arrays to RowBuf.

'RowBuf.Bookmark is already filled by the ReadData function.

For j = 0 To RowBuf.ColumnCount - 1

Select Case RowBuf.ColumnIndex(j)

Case 0

RowBuf.Value(I - Begin, j) = CountryNumbers(I)

Case 1

RowBuf.Value(I - Begin, 1) = Countries(I)

End Select

Next j

Next I

End If

If ApproximatePosition <> -1 Then

ApproximatePosition = Begin + 1

End If

End Sub

Private Sub TData2_UserReadData(ByVal RowBuf As TrueData60Ctl.RowBuffer, ByVal StartLocation As Variant, ByVal Offset As Long, ApproximatePosition As Long)

'The ReadData event functionality for TData1 and TData2 has much in common,

'that's why it is encapsulated in a ReadData function.

'The ReadData function fills two variables: Begin and Last, so we know where to get

'the data in the storage arrays

If ReadData(RowBuf, StartLocation, Offset, CityNames) Then

For I = Begin To Last

'Now we just need to copy data from storage arrays to RowBuf.

'RowBuf.Bookmark is already filled by the ReadData function.

For j = 0 To RowBuf.ColumnCount - 1

Select Case RowBuf.ColumnIndex(j)

Case 0

RowBuf.Value(I - Begin, j) = CityCountryNumbers(I)

Case 1

RowBuf.Value(I - Begin, j) = CityNames(I)

Case 2

RowBuf.Value(I - Begin, j) = CityPopulation(I)

End Select

Next j

Next I

End If

End Sub

Private Sub TData1_UserWriteData(ByVal RowBuf As TrueData60Ctl.RowBuffer, WriteLocation As Variant)

Dim I As Long

I = CLng(WriteLocation)

If Not IsNull(RowBuf.Value(0, 0)) Then 'if Value is Null, it means the field is unchanged

CountryNumbers(I) = RowBuf.Value(0, 0) 'save the changed field value to storage array

End If

If Not IsNull(RowBuf.Value(0, 1)) Then 'if Value is Null, it means the field is unchanged

Countries(I) = RowBuf.Value(0, 1) 'save the changed field value to storage array

End If

End Sub

Private Sub TData1_UserAddData(ByVal RowBuf As TrueData60Ctl.RowBuffer, NewRowBookmark As Variant)

Dim I As Long

I = UBound(CountryNumbers) + 1 'this is the index of the new row - at the end of array

NewRowBookmark = I 'we must return the bookmark of the newly added row from the event procedure

'ReDim storage arrays to accomodate the new row

ReDim Preserve CountryNumbers(NewRowBookmark)

ReDim Preserve Countries(NewRowBookmark)

'fill the new row with data entered by the user

If Not IsNull(RowBuf.Value(0, 0)) Then 'if Value is Null, it means the field value was not entered

CountryNumbers(NewRowBookmark) = RowBuf.Value(0, 0) 'save the field value to storage array

End If

If Not IsNull(RowBuf.Value(0, 1)) Then 'if Value is Null, it means the field value was not entered

Countries(NewRowBookmark) = RowBuf.Value(0, 1) 'save the field value to storage array

End If

End Sub

Private Sub TData1_UserDeleteRow(Bookmark As Variant)

Dim I As Long

I = CLng(Bookmark) 'this is the index of the row to be deleted

'shift the arrays' contents to account for row deletion

For j = I To UBound(CountryNumbers) - 1

CountryNumbers(j) = CountryNumbers(j + 1)

Countries(j) = Countries(j + 1)

Next j

'ReDim the arrays, each of them now has one element less

ReDim Preserve CountryNumbers(UBound(CountryNumbers) - 1)

ReDim Preserve Countries(UBound(CountryNumbers))

End Sub

Private Sub TData2_UserWriteData(ByVal RowBuf As TrueData60Ctl.RowBuffer, WriteLocation As Variant)

Dim I As Long

I = CLng(WriteLocation)

If Not IsNull(RowBuf.Value(0, 0)) Then 'if Value is Null, it means the field is unchanged

CityCountryNumbers(I) = RowBuf.Value(0, 0) 'save the changed field value to storage array

End If

If Not IsNull(RowBuf.Value(0, 1)) Then 'if Value is Null, it means the field is unchanged

CityNames(I) = RowBuf.Value(0, 1) 'save the changed field value to storage array

End If

If Not IsNull(RowBuf.Value(0, 2)) Then 'if Value is Null, it means the field is unchanged

CityPopulation(I) = RowBuf.Value(0, 2) 'save the changed field value to storage array

End If

End Sub

Private Sub TData2_UserAddData(ByVal RowBuf As TrueData60Ctl.RowBuffer, NewRowBookmark As Variant)

Dim I As Long

I = UBound(CityCountryNumbers) + 1 'this is the index of the new row - at the end of array

NewRowBookmark = I 'we must return the bookmark of the newly added row from the event procedure

'ReDim storage arrays to accomodate the new row

ReDim Preserve CityCountryNumbers(NewRowBookmark)

ReDim Preserve CityNames(NewRowBookmark)

ReDim Preserve CityPopulation(NewRowBookmark)

'fill the new row with data entered by the user

If Not IsNull(RowBuf.Value(0, 0)) Then 'if Value is Null, it means the field value was not entered

CityCountryNumbers(NewRowBookmark) = RowBuf.Value(0, 0) 'save the field value to storage array

End If

If Not IsNull(RowBuf.Value(0, 1)) Then 'if Value is Null, it means the field value was not entered

CityNames(NewRowBookmark) = RowBuf.Value(0, 1) 'save the field value to storage array

End If

If Not IsNull(RowBuf.Value(0, 2)) Then 'if Value is Null, it means the field value was not entered

CityPopulation(NewRowBookmark) = RowBuf.Value(0, 2) 'save the field value to storage array

End If

End Sub

Private Sub TData2_UserDeleteRow(Bookmark As Variant)

Dim I As Long

I = CLng(Bookmark) 'this is the index of the row to be deleted

'shift the arrays' contents to account for row deletion

For j = I To UBound(CityCountryNumbers) - 1

CityCountryNumbers(j) = CityCountryNumbers(j + 1)

CityNames(j) = CityNames(j + 1)

CityPopulation(j) = CityPopulation(j + 1)

Next j

'ReDim the arrays, each of them now has one element less

ReDim Preserve CityCountryNumbers(UBound(CityCountryNumbers) - 1)

ReDim Preserve CityNames(UBound(CityCountryNumbers))

ReDim Preserve CityPopulation(UBound(CityCountryNumbers))

End Sub

Private Function ReadData(ByVal RowBuf As _

TrueData60Ctl.RowBuffer, StartLocation As Variant, _

ByVal Offset As Long, A As Variant) As Boolean

'This is a utility function helping us to implement the TData_ReadData event procedure.

'This function fills two variables: Begin and Last.

'They are the first and the last index in storage arrays where we can get

'our data from to put it in the RowBuf.

'Begin is calculated from StartLocation and Offset.

'Last is Begin + RowBuf.RowCount - 1 if it does not exceed the array's bounds

'(remember that RowBuf.RowCount is the number of rows requested by TData),

'and it is appropriately truncated if it goes past the array end.

'A is the array, we need its lower and upper bounds.

'The function returns True if at least one row is retrieved.

'It also fills the RowBuf.RowCount with the number of rows returned,

'and fills the RowBuf's bookmarks. The only thing remaining to be filled

'in RowBuf is actual data - RowBuf.Value(I,J)

Dim I As Long

ReadData = False

If IsNull(StartLocation) Then

'StartLocation=Null means it is either BOF or EOF

If Offset = 0 Then

'There is no sense in Offset=0 in this case

RowBuf.RowCount = 0

Exit Function

End If

If Offset > 0 Then

'StartLocation is BOF, Begin is determined by Offset from BOF

Begin = LBound(A) + Offset - 1

End If

If Offset < 0 Then

'StartLocation is EOF, Begin is determined by Offset back from EOF

Begin = UBound(A) + Offset + 1

End If

Else

'StartLocation is a valid bookmark, Begin is determined by that bookmark

'(turned into index) and Offset

Begin = CLng(StartLocation) + Offset

End If

If Begin < LBound(A) Or Begin > UBound(A) Then

'Take care of all cases when Begin falls out of array's bounds

RowBuf.RowCount = 0

Exit Function

End If

Last = Begin + RowBuf.RowCount - 1 'this is the normal Last value

'if there is enough rows in the array

If Last > UBound(A) Then

'truncate Last so that it won't go past the array bound

Last = UBound(A)

End If

RowBuf.RowCount = Last - Begin + 1 'fill the number of rows returned

'Fill bookmarks for returned rows, each bookmark is just an index in array

For I = Begin To Last

RowBuf.Bookmark(I - Begin) = I

Next I

ReadData = True

End Function

Run the Program and Observe the Following:

•

One grid displays countries and the other displays cities of the currently selected country. If you select All in the first grid, the second grid displays all cities.

•

You can add new entries to either grid. You can also delete entries in both grids.

Admittedly, this tutorial requires a significant amount of code to accomplish basically the same results as the memory array project of Tutorial 13. This comparative example was included to demonstrate the power and flexibility of user events mode. For more information on creating custom data sources, see User Events Mode.


Tutorial 15 - Query Mode (part 1)

In this tutorial you will try a powerful new feature of True DataControl: Query Mode.

Query Mode enables you to build ad-hoc query forms in a matter of minutes. True DataControl Query Mode is an enhanced version of the Microsoft Access “Filter By Form,” and implements the paradigm known as “Query By Example."

In this tutorial, we will create a form that can function in two modes: query and results. The same TData control and the same DataGrid are used to represent data in either mode.

Tutorial 16 will demonstrate another option that you have with True DataControl query mode: you will use a TData control and data-bound controls that are intended solely for entering queries, results will be displayed with a separate TData control in a separate DataGrid.

Step 1.

Start a new project.

Step 2.

Place the following controls on the form (Form1) as shown in the figure: a TData control (TData1), a DataGrid control (DataGrid1) and two buttons (Command1, Command2).

Step 3.

Set properties as follows (you can use the DataSource property page to set TData data source properties, as described in Tutorial 2):

TData1.ConnectionString

Provider=Microsoft.Jet.OLEDB.3.51;Persist Security

Info=False;Data Source=C:\Program Files\ComponentOne Studio\Common\TDBGDemo.mdb

TData1.CommandType 2 – adCmdTable

TData1.RecordSource Products

TData1.QueryMode True

DataGrid1.DataSource TData1

DataGrid1.AllowAddNew True

DataGrid1.AllowDelete True

Command1.Caption Query Mode

Command2.Caption Apply Query

Step 4.

Open the True DataControl property pages for TData1. On the General page check the Query Mode check box in the Buttons group, which will make the Query button visible.

Step 5.

On the Fields property page of TData1, select the ProductName field. Select starts with in the Query Operation combo box.

Step 6.

Add the following code to Command1:

Private Sub Command1_Click()

TData1.QueryMode = True

End Sub

Step 7.

Add the following code to Command2:

Private Sub Command2_Click()

TData1.QueryMode = False

End Sub

Run the Program and Observe the Following:

•

The form starts in query mode: the Query button on TData1 is in the selected state and the grid has a single empty row, ready for you to enter a query.

•

Enter 2 in the SupplierID column in the first grid row. Then enter 4 in the CategoryID column of the second grid row, and move to the first row to allow the grid to add a new row (the second row you just entered data to).

•

Press the Query button on TData1 to leave query mode and apply query. You will see the grid fills with data, the result of the query you entered: SupplierID = 2 OR CategoryID = 4.

•

Press the Query button again to return to query mode. Note that the query data (two rows) is restored in the grid. Type L in the ProductName column of the first grid row.

•

Press the Query button to see the results. You will see less rows in the grid than in the previous query, because the new query is more restrictive: (ProductName starts with “L” AND SupplierID = 2) OR CategoryID = 4.

•

Experiment some more with different queries. Query conditions are connected with AND when they belong to the same row in query mode. Different rows in query mode are connected with OR.

•

The two command buttons setting the QueryMode property to True/False can be used instead of the standard TData Query button.

Close the program. You have successfully completed Tutorial 15.


Tutorial 16 - Query Mode (part 2)

This tutorial is the second part of the lesson begun in Tutorial 15. It demonstrates another option that you have with True DataControl Query Mode: you will create a TData control and data-bound controls intended solely for entering queries. Query results will be displayed with a separate TData control in a separate DataGrid.

Step 1.

Start a new project.

Step 2.

Place the following controls on the form (Form1) as shown in the figure: two TData controls (TData1, TData2), a DataGrid control (DataGrid1), seven TextBox controls (Text1 to 7), seven labels (Label1 to 7) and a button (Command1).

Step 3.

Set properties as follows (you can use the DataSource property page to set TData data source properties, as described in Tutorial 2):

TData1.ConnectionString

Provider=Microsoft.Jet.OLEDB.3.51;Persist Security

Info=False;Data Source=C:\Program Files\ComponentOne Studio\Common\TDBGDemo.mdb

TData1.CommandType 2 – adCmdTable

TData1.RecordSource Orders

TData1.QueryMode True

TData1.EOFAction adDoAddNew

TData2.ConnectionString

Provider=Microsoft.Jet.OLEDB.3.51;Persist Security

Info=False;Data Source=C:\Program Files\ComponentOne Studio\Common\TDBGDemo.mdb

TData2.CommandType 2 – adCmdTable

TData2.RecordSource Orders

TData2.QueryMode False

DataGrid1.DataSource TData2

Step 4.

Open the True DataControl property pages for TData1, and go to the Fields page. Delete all fields except the following: OrderID, CustomerID, ShipName (to delete a field, select it in the field list and press Del).

Step 5.

In the Fields property page for TData1, select the ShipName field and change its QueryOperation property, select starts with in the Query Operation combo box.

Step 6.

In the Fields property page for TData1, create four additional fields (by clicking the right mouse button and choosing New Field from the menu). For each of them select the data radio button, indicating that the field is a data field. For each of the four new fields, set its Name, DataSourceField and QueryOperation properties, typing in the Name edit box and selecting from the lists in the DataSource Field and Query Operation combo boxes.

NOTE: You must change Query Mode to 0 - Both or 1 - Query only for the Query Operation combo box to become available.

Name: DataSource Field: Query Operation:

OrderDateFrom OrderDate >=

OrderDateTo OrderDate <=

RequiredDateFrom RequiredDate >=

RequiredDateTo RequiredDate <=

Step 7.

Set properties of other controls as follows:

Text1.DataSource TData1

Text1.DataField OrderID

Text2.DataSource TData1

Text2.DataField CustomerID

Text3.DataSource TData1

Text3.DataField OrderDateFrom

Text4.DataSource TData1

Text4.DataField OrderDateTo

Text5.DataSource TData1

Text5.DataField ShipName

Text6.DataSource TData1

Text6.DataField RequiredDateFrom

Text7.DataSource TData1

Text7.DataField RequiredDateTo

Set label and button captions according to the picture.

Step 8.

Add the following code to Command1:

Private Sub Command1_Click()

TData2.SourceRecordset.Filter = TData1.QueryFilter

End Sub

Run the Program and Observe the Following:

We leave it to you to experiment with different queries and their results, as it was done in Tutorial 15. We just want you to notice the following:

•

Now you have a sophisticated query form where you can specify different criteria, including date ranges. Four new fields created on Step 5 support data range conditions. ShipName condition is "starts with" rather than "equals," that was specified on Step 4. Field values in a record generate conditions joined with AND.

•

You can specify complex queries with more than one condition joined with OR, simply by adding new records to the query form. To add a new record to query, simply pressing the Next button on TData1 when it is positioned on the last record. This is enabled by our setting TData1.EOFAction=adDoAddNew.

•

Pressing the Apply button applies the specified query to TData2. TData1 remains in query mode at all times.

Congratulations, you have completed all sixteen True DataControl tutorials! You are now ready to take full advantage of True DataControl in your applications.


Tutorials - True DataControlLite

Tutorials – True DataControlLite

Ten tutorials are presented to help you master True DataControl Lite. The tutorials assume that you are familiar with programming in Visual Basic and have a general knowledge of how to use ADO/OLE DB data sources with bound controls. The tutorials provide step-by-step instructions and require no prior knowledge of True DataControl. By following these instructions, you will be able to create projects demonstrating a variety of features. You will also get a good sense of what True DataControl Lite can do and how to do it.

The tutorials use an Access database, called TDDEMO.MDB. The database file TDDEMO.MDB and the tutorial projects can be found in the TUTORIALS subdirectory of the True DataControl Lite installation directory.

We encourage you to run the tutorial projects in Visual Basic and experiment with your own modifications. This is the best and quickest way to learn how to realize the full potential of True DataControl Lite.

NOTE: The tutorials assume that the database file TDBGDemo.MDB is in the C:\Program Files\ComponentOne Studio\Common directory. Depending on where you store the projects and database files, you may need to change the ConnectionString property of ADODC controls in the tutorial projects in order for the projects to work properly, or you can just copy the database file TDDEMO.MDB to the specified location.

Please also note that all code samples and expressions are case-sensitive.

We also assume that four ActiveX controls are included in all projects: ComponentOne True DataControl Lite 8.0 (TDataLite), Microsoft ADO Data Control 6.0 (ADODC), ComponentOne True DBGrid Pro 8.0 (TDBGrid), and Microsoft DataGrid Control 6.0 (OLEDB) (DataGrid). To add a control to your project you must select Components... from the Project menu to display the list of available components. Check the box representing the desired control, then press the OK button. The control icons are added to the Visual Basic toolbox.

Tutorial 1 - Using TDataLite with Bound Controls: ComponentOne TDBGrid and non-ComponentOne Controls

Tutorial 2 - Crosstab

Tutorial 3 - Using TDataLite with Memory Data

Tutorial 4 - Calculated Fields and TDataLite Expressions

Tutorial 5 - Automatic Updating of Control Properties by TDataLite

Tutorial 6 - Using Filter Conditions and Parameters in TDataLite

Tutorial 7 - Imposing Constraints in TDataLite and Related Issues

Tutorial 8 - Query Mode in TDataLite (part 1)

Tutorial 9 - Query Mode in TDataLite (part 2)

Tutorial 10 - OLAP - Decision Support, Pivot Table


Tutorial 1 - Using TDataLite with Bound Controls: ComponentOne TDBGrid and non-ComponentOne Controls

In this tutorial, you will learn how to use TDataLite with ComponentOne True DBGrid (TDBGrid) and other controls. ComponentOne TDBGrid and TDataLite controls are closely integrated, so your grids can take full advantage of the data management features supplied by TDataLite. But you can use TDataLite with other, non-ComponentOne data-bound controls as well.

This tutorial consists of two project: in DataGrid and TDBGrid subdirectories. The DataGrid project shows how to use TDataLite with non-ComponentOne controls, such as Microsoft DataGrid. The TDBGrid subdirectory shows the interaction between TDataLite and ComponentOne TDBGrid control. We’ll start with DataGrid:

Step 1.

Start a new project.

Step 2.

Place the following controls on the form (Form1) as shown in the figure: a TDataLite control (TDataLite1), an ADODC control (Adodc1) and a DataGrid control (DataGrid1).

Step 3.

Set properties as follows:

Adodc1.ConnectionString

Provider=Microsoft.Jet.OLEDB.3.51;Persist Security

Info=False;Data Source=C:\Program Files\ComponentOne Studio\Common\TDBGDemo.mdb

Adodc1.CommandType 2 - adCmdTable

Adodc1.RecordSource Customers

TDataLite1.DataSource Adodc1

Step 4.

Select TDataLite1, and click the right mouse button over it to open the control's context menu. Select the TDataLite Properties option. This will open the property pages dialog, where you can view and edit the properties of TDataLite1. The dialog looks like this:

In the General property page check all the check boxes in the Buttons group. Close the property pages by clicking the OK button or by pressing Enter. This will save the changes you have just made for TDataLite1. You will see thirteen buttons appear on the TDataLite1 control.

Step 5.

Set the DataSource property of DataGrid1 to TDataLite1. This binds the DataGrid1 control to the TData1 control. TDataLite1 becomes the data source for the grid. Set the grid’s AllowAddNew and AllowDelete properties to True.

Run the Program and Observe the Following:

•

DataGrid1 displays data from the Customers table.

•

TData1 has thirteen buttons on it, providing useful functions that you otherwise would have had to implement with tedious manual coding. These include data management functions, such as AddNew, Delete, Update, Cancel, and two standard dialogs: Find and Bookmarks. All buttons have tooltips, so you can easily identify them. Try the Find and Bookmarks buttons. The Find dialog is easy to use and self-explanatory. To use the Bookmarks dialog, press the Bookmarks button, enter a bookmark name and press Add. Repeat this on different data rows. You will see several bookmarks listed in the Bookmarks dialog. You can jump to any of these bookmarks pressing the Go To button.

•

Try the True DataControl query mode. This is a powerful feature that adds a lot to your application without requiring a single line of code. Press the Query button on the TDataLite control. This will switch it to query mode: DataGrid1 becomes empty and contains one data row. Add another row to DataGrid1 and enter the following data in the two rows: CompanyName = B's Beverages in the first row and City = Rio de Janeiro in the second row. Press the Query button again to leave query mode. You will see that the query is applied and its result, four rows of data, appears in DataGrid1. Go back to query mode by pressing the Query button, and delete the first row (CompanyName = B's Beverages) from the grid. Apply the query pressing the Query button again; you will see that the result has changed accordingly. Returning to query mode, enter Hanari Carnes in the CompanyName field in the same row. Switch to the result mode, and you will see that now there is only one row satisfying the query. In formal querying terms, the query conditions are connected with the logical operator AND when they belong to the same row in query mode. Different rows in query mode are connected with OR.

Step 6.

Close the program. Back in design mode, set the DataSource property of DataGrid1 to Adodc1. This binds the DataGrid1 control to Adodc1 as its data source, so DataGrid1 is no longer directly bound to TDataLite1. Still, you can use TDataLite1 buttons to navigate the recordset and perform the actions implemented by TDataLite. As you will see in other tutorials, most of TDataLite features, such as constraints, default values, etc, are still available in this mode. This is because TDataLite1 is bound to the same DataSource as DataGrid1. However, not all TdataLite features are available in this mode. For example, if you press the Query button, you will se that nothing happens. In order to be able to use query mode, you must bind DataGrid1 to TDataLite1 directly. This binding does not actually change anything, DataGrid still uses Adodc1 as its data source, even if it is bound to TDataLite1. But binding directly to TDataLite enables query mode and also allows you to use memory array data (DataMode = 1 – tdbModeMemoryArray, see Tutiorial 3).

Now we will look at the other project of this tutorial, the one in the TDBGrid subdirectory.

Step 7.

Repeat steps 1 – 5, but this time use ComponentOne True DBGrid 8.0 (TDBGrid) instead of Microsoft DataGrid control.

Step 8.

Open TDataLite1 property pages by select the TDataLite Properties option in TdataLite1 context menu. Select the Fields property page. You will see all fields of the Customers table. In this example, we need to expose three fields: CustomerID, CompanyName, and City. To do this, one at a time select each of the other fields in the data source tree-view window, and clear the Visible check box for all of them. An empty check box means that the field is accessible to your TDataLite control, but is not exposed to controls that are bound to it.

Step 9.

To change the field order from that of the database table, drag and drop the field names. For example, press the left mouse button over the City field name. Without releasing the button, move your mouse to the CompanyName field position, then release the button. The City field is now visibly positioned before the CompanyName field.

Step 10.

Close the property pages by clicking the OK button or by pressing Enter. This will save the changes you have just made for TDataLite1.

Run the Program and Observe the Following:

TDBGrid1 displays data from the Customers table: CustomerID, City, and CustomerName. There is one column for each field marked as Visible in the property pages.

Step 11.

If you will return to the DataGrid project and try to do the same, you will see that DataGrid1 still displays all the fields of the Customers table, not the three fields you defined in TDataLite1. The real data source for DataGrid1 is still Adodc1, not TDataLite. Although TDataLite1 appears as the value of DataGrid1.DataSource, TDataLite1 simply delegates to its DataSource, to Adodc1, so DataGrid1 displays the data as it is supplied by Adodc1. This is because DataGrid is not an ComponentOne control, so it does not have the intimate knowledge of TDataLite that TDBGrid has. Although you can use non-ComponentOne controls with TDataLite, in order to benefit fully from all TDataLite features, you have to use ComponentOne controls, such as TDBGrid, or purchase the full version – True DataControl.

Congratulations, you have successfully completed Tutorial 1!


Tutorial 2 - Crosstab

In this tutorial, you will see a powerful new feature that TDataLite adds to ComponentOne True DBGrid 8.0 (OLE DB version) – crosstab data presentation. Crosstab is a common feature of database applications. Until now, True DBGrid did not support crosstab directly, it was necessary to use unbound mode events and complex coding to implement it, or create special temporary database tables or queries. Now, True DBGrid and TDataLite work together to implement crosstab for you. Unlike crosstab implementations in many other tools, TDataLite crosstab is modifiable at run time: you can modifiy values in crosstab columns (cells), if, of course, the underlying recordset is modifiable.

Crosstab is a matrix-like representation where you have multiple columns representing values of a single database column. For example, a MonthlyOrders table has the following fields: CustomerID, Month, Amount, and you need to present the data as a table with twelve columns, one for each month, showing monthly amounts.

Note: You can use TDataLite crosstab feature with other, non-ComponentOne grids too, but then all crosstab columns (see below) will appear as separate fields, you will have to specify all settings for every crosstab column separately.

Step 1.

Start a new project.

Step 2.

Place the following controls on the form (Form1) as shown in the figure: a TDataLite control (TDataLite1), an ADODC control (Adodc1) and a True DBGrid 8.0 control (TDBGrid1).

Step 3.

Set properties as follows:

Adodc1.ConnectionString

Provider=Microsoft.Jet.OLEDB.3.51;Persist Security

Info=False;Data Source=C:\Program Files\ComponentOne Studio\Common\TDBGDemo.mdb

Adodc1.CommandType 2 - adCmdTable

Adodc1.RecordSource MonthlyOrders

TDataLite1.DataSource Adodc1

TDBGrid1.DataSource TDataLite1

Step 4.

Select TDataLite1, and click the right mouse button over it to open the control's context menu. Select the TDataLite Properties option. This will open the property pages dialog, where you can view and edit the properties of TDataLite1. Go to the Crosstab page. Check the XTab check box (TDataLite1.XTab property). This will eable the crosstab feature.

Step 5.

In the XTabRowKey edit box (TDataLite1.XTabRowKey property) type CustomerID. This specifies CustomerID as the row key, the key field defining crosstab rows. Table rows having the same CustomerID values will be displayed in a single row, in different columns according to their value of the Month key. Notes: (a) You must make sure that the recordset is ordered by the key you define in TDataLite.XTabRowKey. For a table, it must be a part of its primary key, for SQL, use ORDER BY to ensure the correct order. (b) If you have multi-field row key, specify the full semicolon-separated key sequence, for example, DepartmentID;CustomerID.

Step 6.

In the XTabColKey edit box (TDataLite1.XTabColKey property) type Month. This specifies Month as the column key, the key field defining crosstab columns. Note: If you have multi-field column key, specify the full semicolon-separated key sequence, for example, Year;Month.

Step 7.

Select the Amount field and type the following in the XTabColumns edit box (TDataLite1.Fields(“Amount”).XtabColumns property):

1:Jan;2:Feb;3:Mar;4:Apr;5:May;6:Jun;7:Jul;8:Aug;9:Sep;10:Oct;11:Nov;12:Dec

This will create twelve crosstab columns out of a single Amount field (crosstab field). Column definitions are separated with semicolons. Each column definition has the key expression and the column name:

<key expression>:<column name>

Key expression must be a valid TData expression (TData uses VBScript as its expression language). Usually, it is just a constant. Don’t forget to enclose it in double quotes if it is a string expression.

Column name is a string defining the name of the crosstab column. You don’t have to double quote field names.

Each column definition creates a crosstab column that is available to TDBGrid. Such column contains the value of the main field (in this tutorial, Amount) corresponding to the value of the column key (in this tutorial, Month) specified in its key expression.

Step 8.

Close the property pages by clicking the OK button or by pressing Enter. We finished the settings in TDataLite1, now we will set up the grid, TDBGrid1.

Notes:

(i) If you have multi-field column key, specify a full coma-separated sequence of key values (expressions) for each column definition, for example:

1999,1:Jan 99;2000,3:Mar 00.

(ii) You can have multiple crosstab fields, each of them generating its own crosstab columns. For example, you can have Amount and Discount fields, both of them displaying monthly data, so you will have 24 columns in your crosstab. To do that, just fill the XtabColumns property for every such field.

(iii) In the case of multiple crosstab fields, there are two options controlled by TDataLite.XTabCollate property. If XTabCollate = False (default), the crosstab columns generated by different fields will be interspersed, that is, the corresponding columns will be grouped by the column key value, every group containing all fields with that key value. If XTabCollate = True, the columns will be grouped by the main field, that is, all columns generated by the first field will apear first, then all columns generated by the second fields, and so on.

Step 9.

Select TDBGrid1, and click the right mouse button over it to open the control's context menu. Select the Retrieve Field option. The grid will show the columns in crosstab layout: CustomerID (a regular, non-crosstab column) and twelve crosstab columns corresponding to the twelve months.

Step 10.

Select TDBGrid1, and click the right mouse button over it to open the control's context menu. Select the Properties… option. This will open the property pages dialog, where you can view and edit the properties of TDBGrid1. Go to the Splits page and expand the Splits(00).Columns node in the property tree. You will see two nodes representing two columns: CustomerID and Amount. CustomerID is a regular field, not a crosstab field. The other field, Amount, represents all twelve crosstab columns. Change the HeadAlignment property of Column(01) [Amount] to 2 – Center. Close the property pages by clicking the OK button. You will see that the captions of all twelve crosstab columns are now center-aligned. This way you can specify any settings of the crosstab field to your liking, and it will be applied to all crosstab columns generated by that field – much easier than if you had to set up each crosstab column separately.

Notes:

(i) There is a special property, TDataLite.XTabSeparateFields controlling the way crosstab columns are exposed to TDBGrid at design time. If XTabSeparateFields = False (default), TDBGrid will see a single field (for every crosstab field) at design time in its property pages (but it will display all crosstab columns properly). All settings of the corresponding column will be applied to all crosstab columns it generates, as we saw in Step 10. In most cases, it is convenient because you usually set up all crosstab columns with identical settings. If XTabSeparateFields=True, TDBGrid will see crosstab columns as separate data fields, so you can set up each of them separately.

(ii) This propagation of settings to all crosstab columns takes place only at design time. At run time, you can resize and set properties of crosstab columns separately, regardless of the XTabSeparateFields value.

Run the Program and Observe the Following:

TDBGrid1 displays data as a matrix with CustomerID’s as rows and months as columns. You can modify any cell and the change will be saved in the database.

Congratulations, you have successfully completed Tutorial 2!


Tutorial 3 - Using TDataLite with Memory Data

In this tutorial you will learn how to use TDataLite with memory array data.

Step 1.

Start a new project.

Step 2.

Place the following controls on the form (Form1) as shown in the figure: a TDataLite control (TDataLite1) and a DataGrid control (DataGrid1). This time, we do not need an ADODC control as TDataLite’s data source, we will use a memory array as the data source.

Step 3.

Set properties as follows:

TDataLite1.DataMode 1 - MemoryArray

DataGrid1.DataSource TDataLite1

Step 4.

Open the TDataLite property pages dialog by clicking the right mouse button over TdataLite1 and selecting TDataLite Properties. Select the Fields property page. Since there are no predefined fields in memory array mode, you must define the fields yourself, specifying the array structure. Click the right mouse button over the fields list area, and select New Field from the menu (alternatively, you can press the New button). A new field with the default name FIELD_0 appears. Change the name to A by typing it in the Name text box. Select 2 - Integer in the Data Type combo box. Then create two more fields, B and C. Repeat the steps above, but specify different data types: Date for B and Currency for C. Press the OK button to close the dialog and save changes.

Run the Program and Observe the Following:

•

DataGrid1 shows the contents of an array with three fields: A (Integer), B (Date) and C (Currency). Initially the grid is empty, but data may be added. If you add data and then close and re-run the program, you will notice that the data you entered has disappeared. This is because it is stored in memory. There are provisions in TDataLite to populate a memory array with data before showing it to the user, and to save the entered data. Refer to the Array property and to the OpenData event.

•

Note that we used a DataGrid – a non-ComponentOne control. Of course, we could use ComponentOne TDBGrid as well, but we did it intentionally, to emphasize that TDataLite provides this additional functionality for all controls. TDataLite in memory array mode can serve as the data source for all data-bound controls, not just ComponentOne controls.

Close the program. Congratulations, you have successfully completed Tutorial 3!


Tutorial 4 - Calculated Fields and TDataLite Expressions

In this tutorial, you will learn how to create a calculated field. A calculated field is one whose value is not stored directly in the database but is determined by the values of other fields. More importantly, this will be your first acquaintance with True DataControl expressions.

Note: Calculated fields are only accesible to ComponentOne controls, such as TDBGrid 8.0, bound to TDataLite. If you need to expose calculated fields to non-ComponentOne controls, use the full version – True DataControl

Step 1.

Start a new project.

Step 2.

Place the following controls on the form (Form1) as shown in the figure: a TDataLite control (TDataLite1), an ADODC control (Adodc1) and a True DBGrid 8.0 control (TDBGrid1).

Step 3.

Set properties as follows (you can use the DataSource property page to set TData data source properties, as described in Tutorial 2):

Adodc1.ConnectionString

Provider=Microsoft.Jet.OLEDB.3.51;Persist Security

Info=False;Data Source=C:\Program Files\ComponentOne Studio\Common\TDBGDemo.mdb

Adodc1.CommandType 2 – adCmdTable

Adodc1.RecordSource [Order Details]

TDataLite1.DataSource Adodc1

TDBGrid1.DataSource TDataLite

Step 4.

Open the TDataLite1 property pages by clicking the right mouse button over TDataLite1 and selecting TDataLite Properties. Select the Fields property page. Click the right mouse button over the fields list area and select New Field from the menu (alternatively, you can press the New button). A new field with the default name FIELD_0 appears. Change the name to ExtendedPrice by typing it into the Name text box. Select the Calculated radio button. Select Currency in the Data Type combo box.

Step 5.

Type the following in the Calculated Expression text box while the ExtendedPrice field is selected:

UnitPrice * Quantity * (1 - Discount)

This is the formula that provides the value of the ExtendedPrice calculated field. It computes the value using the values of three other fields: UnitPrice, Quantity, and Discount. These are data fields, meaning their values are actually stored in the database.

Intermission 1 - True DataControl Expression Language

The True DataControl expression language is a subset of VBScript, or Visual Basic Scripting Edition language. It is primarily the subset of VBScript that contains expressions and only expressions. You cannot use VBScript statements such as: If...Then...Else. Because of this, you cannot write full-fledged programs in this language, but you may certainly use any VBScript function and operator in your expressions. The variables you can use in True DataControl expressions are fields and parameters. There are also two functions, IIF and Format, that were added to the True DataControl expression language since VBScript does not support them (although they are available in Visual Basic). You will use the IIF function in some of the following tutorials.

If you are not familiar with VBScript, do not worry about needing to learn an entirely new language. It is still Visual Basic. The most significant difference is that VBScript has only one data type, Variant, making VBScript merely a simplified version of Visual Basic.

As you will see later in this tutorial, the TDataLite property pages are equipped with a special expression editor dialog to help you build an expression. The Expression Editor enables you to browse through lists of available variables, functions and operators and paste them into the expression.

Intermission 2 - Evaluation and Re-Evaluation of True DataControl Expressions

Calculated expressions are just one type of True DataControl expression. There are other expressions that may be used and these will be introduced later in following tutorials.

Every expression is automatically evaluated at a specific and appropriate time, for each particular type of expression. Calculated expressions, for example, are evaluated to yield a calculated field value each time the value can change. The calculated expression is evaluated both when a new record is retrieved from the database, and when any of the variables in the expression changes its value.

First evaluation mode (retrieving a record) is an example of synchronous evaluation. A synchronous evaluation occurs as a part of a procedure performed by a TDataLite control. You do not need to perform such an evaluation from code since it will be done automatically when necessary. Also, you can rely on the fact that expressions will be evaluated in their correct order. For example, if Quantity is a calculated field, the ExtendedPrice expression will be evaluated after the Quantity expression since the ExtendedPrice is dependent upon Quantity.

Second evaluation mode (on change of one of the variables used in the expression) represents asynchronous evaluation. An asynchronous evaluation is performed if a change of a variable value can cause the expression to change its value. When the TDataLite control detects such a situation it will automatically re-evaluate the expression, without programmer’s interference. This is one of the most attractive features of the TDataLite control, making application creation much easier. Once the user has changed one of the three fields, UnitPrice, Quantity or Discount, the ExtendedPrice field will immediately display the updated value. Please note that this is accomplished without writing a single line of code.

At the moment of synchronous evaluation of expressions, an event is also called for almost every type of a True DataControl expression. This allows you to program a more involved computation in code, if the True DataControl expression language does not satisfy your needs. For example, you can use the CalcFields event to assign values to calculated fields. The syntax for accessing a TDataLite variable is illustrated in the next step:

Step 6.

Although you are almost ready to run the program, we advise you to first review the Expression Editor. To bring up the expression editor, press the ellipsis button located at the right edge of the Calculated Expression text box in the Fields property page. The expression editor is shown in the following figure.

You can build or edit an expression with the help of four lists of elements available in the expression: Fields, Parameters, Operators, and Functions and Constants. You can also select a category of operators and functions in the two combo boxes above the lists: Operators, and Functions and Constants. Double-click on one of the elements in any of the four list boxes to paste the selected element into the expression.

Step 7.

Without closing the expression editor, try to enter invalid data in the expression. For example, type aUnitPrice instead of UnitPrice. Press the OK button to display an error message stating "Unknown variable: aUnitPrice." Alternatively, you can check the expression syntax without closing the expression editor by pressing the Check button. Leave the "aUnitPrice" error in the expression by selecting OK from the error message.

There are other ways of checking for expression syntax and other possible errors. Press the Check button located in the lower right corner of every property page. You will receive a message box with a list of detected errors: " Field OrderID: Unknown variable: aUnitPrice - Error in calculated expression aUnitPrice." If there is more than one mistake, there will, of course, be more error messages. You can go directly to the location of the detected error by pressing the OK button or double-clicking an error message in the list. This will show the Fields page if it is not current. Select the ExtendedPrice field node, and set focus to the Calculated Expression edit box so you can correct the error there. Although most errors may occur in expressions, there are other kinds of errors that are also detectable by the syntax checking.

Note: Do not run your program if TDataLite syntax checking reports an error. First fix the error to ensure against unpredictable behavior.

Step 8.

Fix the error in the Calculated Expression text box so that it contains the original formula:

UnitPrice * Quantity * (1 - Discount)

Press OK to close the dialog and save changes.

Run the Program and Observe the Following:

•

The ExtendedPrice field shows the value of the calculated expression.

•

Change one of the three values: UnitPrice, Quantity or Discount. The ExtendedPrice value is automatically updated.

Close the program. You have successfully completed Tutorial 4.


Tutorial 5 - Automatic Updating of Control Properties by TDataLite

This tutorial demonstrates the correlation between control properties and True DataControl expressions. For instance, if a button should be enabled if, and only if, a variable Name is nonempty, why not set the button’s Enabled property in the Properties window to:

Name <> ""

Unfortunately, Visual Basic does not support this, but TDataLite does!

Step 1.

Start a new project.

Step 2.

Place the following controls on the form (Form1) as shown in the figure: an ADODC control (Adodc1), a TDataLite control (TDataLite1), a DataGrid control (DataGrid1), six TextBox controls (Text1 to 6) and six labels (Label1 to 6).

Step 3.

Set properties as follows (you can use the DataSource property page to set TData data source properties, as described in Tutorial 1):

Adodc1.ConnectionString

Provider=Microsoft.Jet.OLEDB.3.51;Persist Security

Info=False;Data Source= C:\Program Files\ComponentOne Studio\Common\TDBGDemo.mdb

Adodc1.CommandType 2 – adCmdTable

Adodc1.RecordSource Orders

TDataLite1.DataSource Adodc1

DataGrid1.DataSource Adodc1

Text1.DataSource Adodc1

Text1.DataField OrderID

Text2.DataSource Adodc1

Text2.DataField RequiredDate

Text3.DataSource Adodc1

Text3.DataField ShippedDate

Text4.DataSource Adodc1

Text4.DataField ShipName

Text5.DataSource Adodc1

Text5.DataField ShipCountry

Text6.DataSource Adodc1

Text6.DataField ShipRegion

Set the label captions as shown in the picture.

Note: You can set the DataSource property of the six TextBox controls either to Adodc1 or to TDataLite1, it does not matter in this case. Also, we deliberately used only non-ComponentOne bound controls in this tutorial, to demonstrate that this feature works for any data bound control.

Step 4.

Open the True property pages for TDataLite1 and go to the Property Expressions page. The Available Controls tree displays a hierarchical outline of all controls existing on your form. Expand some of them by clicking the plus sign (+) or pressing the plus sign on the numeric keypad. Properties that return objects (such as Font) can be expanded further to reveal their constituent properties. Select and expand the Label6 control. Next, select its Caption property. The name of the property, Label6.Caption, will appear in the Property text box. Press the New button or select New from the context menu to enable the Value Expression edit control and its adjacent ellipsis button.

Step 5.

Type the following text into the Value Expression text box:

IIF(ShipCountry = "USA", "State:", "Region:")

The following setting is added to the properties area in the left part of the page:

Label6.Caption = IIF(ShipCountry = "USA", "State:", "Region:")

Here IIF(Condition, Value1, Value2) returns Value1 if Condition is True and Value2 otherwise. This is all you need to make the Caption property of Label6 assume one of two values according to the value of the ShipCountry field of TData1. The caption will be automatically set to State: when ShipCountry = ”USA” and Region: when ShipCountry <> “USA”.

Step 6.

Add two more property expressions following the steps above:

Text3.Font.Bold = RequiredDate - ShippedDate < 10

Text2.BackColor = IIF(RequiredDate - ShippedDate > 20, &H000000FF&, &H80000005&)

Press Apply to save the changes.

Step 7.

Go to the Fields property page and change the order of fields by dragging the ShipCountry field and dropping it before the EmployeeID field. This operation is not essential for our tutorial; it is intended only to make the ShipCountry field appear in the grid before fields that are less relevant.

Run the Program and Observe the Following:

•

Set focus to the grid and press the down arrow key several times to visit several records following the first. Observe that ShippedDate is displayed in bold, and RequiredDate is displayed on a red background in accordance with the conditions specified at design time in Step 6. Select a record where ShipCountry = USA and observe that the label below Country changes from Region: to State: as specified in Step 5.

•

Please note that this tutorial was performed without requiring you to write a single line of code!

•

An important consideration is that you can use this feature of True DataControl not only in database applications, but in building any kind of application with a user interface. It is often difficult to keep all properties of all controls in sync with one another and with the constraints and conditions the application logic dictates. True DataControl property expressions can make such interfaces simpler, more reliable, and easier to maintain. You can use memory array mode (TDataLite.DataMode = 1 – tdbModeMemoryArray) for non-database applications.

Close the program. You have successfully completed Tutorial 5.


Tutorial 6 - Using Filter Conditions and Parameters in TDataLite

This tutorial describes how to restrict the recordset by imposing a filter condition. You will also learn how to use TDataLite parameters.

Note: Filter conditions are only accesible to ComponentOne controls, such as TDBGrid 8.0, bound to TDataLite. If you need to use filters with non-ComponentOne controls, use the full version – True DataControl (TData, see ComponentOne web page for details).

Step 1.

Start a new project.

Step 2.

Place the following controls on the form (Form1) as shown in the figure: an ADODC control (Adodc1), a TDataLite control (TDataLite1), a True DBGrid 8.0 control (TDBGrid1), a TextBox control (Text1), a label (Label1) and a button (Command1).

Step 3.

Set the properties as follows:

Adodc1.ConnectionString

Provider=Microsoft.Jet.OLEDB.3.51;Persist Security

Info=False;Data Source= C:\Program Files\ComponentOne Studio\Common\TDBGDemo.mdb

Adodc1.CommandType 2 – adCmdTable

Adodc1.RecordSource Orders

TDataLite1.DataSource Adodc1

TDBGrid1.DataSource TDataLite1

Step 4.

For this tutorial, we will need to define a parameter in the TDataLite control. Like fields, parameters are TDataLite variables, they can be used in True DataControl expressions. You can access parameter values at run time through the Parameters collection, see Step 7 below. Parameters differ from fields in that their values don’t depend on a particular record the TDataLite is positioned on. To create a parameter, select the Parameters property page for TDataLite1. Note that the parameter list on the left is initially empty. Click the right mouse button over the parameter list and select New from the menu (alternatively, you can press the New button). A new parameter with the default name PARAM_0 will appear. Change the name to Interval by typing it into the Name text box. Select Integer in the Data Type combo box. You have now created an Interval parameter.

Step 5.

Go to the Filters property page of TDataLite1. Create a new filter by right-clicking the filter list on the left side of the page and choosing New from the context menu (alternatively, you can use the New button). This enables the expression editing controls on the right side of the page. Type the following text into the Filter Expression box:

RequiredDate - ShippedDate > Interval

Type the following text into the Condition box:

Not IsNull(Interval)

As described in previous tutorials, you can also use the Expression Editor to build the expression.

You have created a filter condition that reads as:

(if (Not IsNull(Interval)) RequiredDate - ShippedDate > Interval

This means that:

1.

The condition will be applied only if the Interval parameter is not empty.

2.

In this case, TDataLite1 will only include records where RequiredDate - ShippedDate > Interval.

More than one filter condition may be imposed. Usually, each filter is accompanied by a condition specifying its applicability, as in this example.

Step 6.

Go to the General property page and check the Filtered check box.

IMPORTANT!

If you omit this step, all filters will be ignored!

Step 7.

Add the following code to Command1:

Private Sub Command1_Click()

TDataLite1.Parameters("Interval") = Text1.Text

End Sub

Run the Program and Observe the Following:

•

Enter a number (for example, 20) into the edit control at the top of the form, then click on the Apply Filter button. The grid includes only the rows that satisfy the condition. Enter different numbers (for example, 1) into the edit control and see how they affect the record display.

•

Clear the edit control and click on Apply Filter button. The grid now shows all orders because the filter was specified as applicable only if Interval is not empty.

Close the program. You have successfully completed Tutorial 6.


Tutorial 7 - Imposing Constraints in TDataLite and Related Issues

This tutorial explains how to specify constraint expressions for individual fields as well as for the whole record. It also describes how to specify default values for fields in a new record, how to use the Required and ReadOnly properties of a TDataLite field.

Step 1.

Start a new project.

Step 2.

Place the following controls on the form (Form1) as shown in the figure: an ADODC control (Adodc1), a TDataLite control (TDataLite1), five TextBox controls (Text1 to 5), and five labels (Label1 to 5) and a command button (Command1).

Step 3.

Set properties as follows:

Adodc1.ConnectionString

Provider=Microsoft.Jet.OLEDB.3.51;Persist Security

Info=False;Data Source= C:\Program Files\ComponentOne Studio\Common\TDBGDemo.mdb

Adodc1.CommandType 2 – adCmdTable

Adodc1.RecordSource Employees

TDataLite1.DataSource Adodc1

Text1.DataSource TDataLite1

Text1.DataField FirstName

Text2.DataSource Adodc1

Text2.DataField LastName

Text3.DataSource Adodc1

Text3.DataField BirthDate

Text4.DataSource Adodc1

Text4.DataField HireDate

Text5.DataSource Adodc1

Text5.DataField Title

Set label captions as shown in the picture.

Note: You can set the DataSource property of the five TextBox controls either to Adodc1 or to TDataLite1, it does not matter in this case. Also, we deliberately used only non-ComponentOne bound controls in this tutorial, to demonstrate that thes features work for any data bound control.

Step 4.

Open the property pages for TDataLite1. Go to the Fields page, and select the HireDate field. Type Date in the Default Expression text box to specify a default value for the HireDate field when new records are added.

Step 5.

Click the right mouse button over the HireDate field and select New Constraint from the context menu (alternatively, you can use the New button). An empty constraint expression for the HireDate field appears indented beneath the field name in the list, and the field controls on the right side of the page are replaced with expression editing controls. Go to the Constraint Expression text box and enter the following expression:

HireDate <= Date

(You can ignore the Condition text box for now. This is used for entering an optional condition specifying whether to apply the constraint expression or to skip it.)

Type the following text into the Message Expression text box:

"Hire date can't be in the future"

This completes the constraint definition for the HireDate field.

Step 6.

Go to the Constraints property page. Create a new constraint by clicking the right mouse button over the constraints area (left part of the page) and choosing New from the context menu (alternatively, you can use the New button). The expression editing controls on the right side of the page become available. Type the following text into the Constraint Expression text box:

IsEmpty(HireDate) or HireDate >= BirthDate

Type the following text into the Message Expression text box:

"You can't hire a person who is not born"

This completes the constraint definition for the entire record.

Step 7.

Return to the Fields property page. Select the Title field. Check the Required check box, which is unchecked by default.

Step 8.

Select the LastName field. Check the ReadOnly check box, also unchecked by default. Repeat this step for the FirstName field.

Step 9.

Go to the General property page and check the AddNew check box in the Buttons group. We will need the AddNew button to add records.

Step 10.

Add the following code to Command1:

Private Sub Command1_Click()

Adodc1.Recordset.CancelUpdate

Adodc1.Recordset.Bookmark = Adodc1.Recordset.Bookmark

End Sub

Run the Program and Observe the Following:

•

In the first record (employee Nancy Davolio) enter 1/1/2010 in the HireDate field (its original value is 6/4/92). Press Tab, or click on another control with the mouse. The error message: "Hire date can’t be in the future" will appear in accordance with the constraint imposed on the HireDate field in Step 5.

•

Enter 12/8/40 in the HireDate field. Press Tab or click another control with the mouse. Although the entered date is incorrect (less than BirthDate), you are allowed to leave the control. This is because the corresponding constraint is a record-level constraint; it is checked only when you leave the record or post the change to the database. Now, try to move to another record with the TDataLite1’s Next button (or the Adodc1’s Next button). The error message: "You can't hire a person who is not born" will be displayed in accordance with the record-level constraint imposed in Step 6.

•

Click the UndoRecord button. This executes the ADO CancelUpdate method, which restores all fields to their original value. The strange looking second line in the code (setting Adodc1.Recordset.Bookmark to itself) is necessary because Visual Basic controls, such as TextBox, won’t recognize CancelUpdate without it. The original HireDate reappears: 6/4/92.

•

Clear the Title value from Text5. Then press Tab or click another field in the same row with the mouse. The error message: "Field Title can’t be left empty" will appear as specified by the Required property in Step 7.

•

Try to change LastName and press Tab. You will see that the field value has not changed, in accordance with the ReadOnly property you specified for these fields in Step 8.

•

Press the Add button on the TDataLite1 control to add a new row. The HireDate field in the newly created row will be automatically set to today’s date as returned by the VBScript function Date, which was specified in the Default Expression for the HireDate field in Step 4.

Close the program. You have successfully completed Tutorial 7.


Tutorial 8 - Query Mode in TDataLite (part 1)

In this tutorial you will try a powerful feature of TDataLite: Query Mode.

Query Mode enables you to build ad-hoc query forms in a matter of minutes. It is an enhanced version of the Microsoft Access “Filter By Form,” and implements the paradigm known as “Query By Example."

In this tutorial, we will create a form that can function in two modes: query and results. The same TDataLite control and the same DataGrid are used to represent data in either mode.

Tutorial 9 will demonstrate another option that you have with TDataLite query mode: you will use a TDataLite control and data-bound controls that are intended solely for entering queries, results will be displayed, in a separate DataGrid without TDataLite.

Step 1.

Start a new project.

Step 2.

Place the following controls on the form (Form1) as shown in the figure: an ADODC control (Adodc1), a TDataLite control (TDataLite1), a DataGrid control (DataGrid1) and two buttons (Command1, Command2).

Step 3.

Set properties as follows:

Adodc1.ConnectionString

Provider=Microsoft.Jet.OLEDB.3.51;Persist Security

Info=False;Data Source=C:\Program Files\ComponentOne Studio\Common\TDBGDemo.mdb

Adodc1.CommandType 2 – adCmdTable

Adodc1.RecordSource Products

TDataLite1.DataSource Adodc1

TDataLite1.QueryMode True

DataGrid1.DataSource TDataLite1

DataGrid1.AllowAddNew True

DataGrid1.AllowDelete True

Command1.Caption Query Mode

Command2.Caption Apply Query

Step 4.

Open the TDataLite1 property pages. On the General page check the Query Mode check box in the Buttons group, which will make the Query button visible.

Step 5.

On the Fields property page of TDataLite1, select the ProductName field. Select starts with in the Query Operation combo box.

Step 6.

Add the following code to Command1:

Private Sub Command1_Click()

TDataLite1.QueryMode = True

End Sub

Step 7.

Add the following code to Command2:

Private Sub Command2_Click()

TDataLite 1.QueryMode = False

End Sub

Run the Program and Observe the Following:

•

The form starts in query mode: the Query button on TDataLite1 is in the selected state and the grid has a single empty row, ready for you to enter a query.

•

Enter 2 in the SupplierID column in the first grid row. Then enter 4 in the CategoryID column of the second grid row, and move to the first row to allow the grid to add a new row (the second row you just entered data to).

•

Press the Query button on TDataLite1 to leave query mode and apply query. You will see the grid fills with data, the result of the query you entered: SupplierID = 2 OR CategoryID = 4.

•

Press the Query button again to return to query mode. Note that the query data (two rows) is restored in the grid. Type L in the ProductName column of the first grid row.

•

Press the Query button to see the results. You will see less rows in the grid than in the previous query, because the new query is more restrictive: (ProductName starts with “L” AND SupplierID = 2) OR CategoryID = 4.

•

Experiment some more with different queries. Query conditions are connected with AND when they belong to the same row in query mode. Different rows in query mode are connected with OR.

•

The two command buttons setting the QueryMode property to True/False can be used instead of the standard TDataLite Query button.

Close the program. You have successfully completed Tutorial 8.


Tutorial 9 - Query Mode in TDataLite (part 2)

This tutorial is the second part of the lesson begun in Tutorial 10. It demonstrates another option that you have with TDataLite Query Mode: you will create a TDataLite control and data-bound controls intended solely for entering queries. Query results will be displayed in a separate DataGrid ynrelated to the TDataLite control. Also, you will learn how to specify more complex query conditions, such as ranges, etc.

Step 1.

Start a new project.

Step 2.

Place the following controls on the form (Form1) as shown in the figure: an ADODC control (Adodc1), a TDataLite control (TDataLite1), a DataGrid control (DataGrid1), seven TextBox controls (Text1 to 7), seven labels (Label1 to 7) and a button (Command1).

Step 3.

Set properties as follows:

Adodc1.ConnectionString

Provider=Microsoft.Jet.OLEDB.3.51;Persist Security

Info=False;Data Source=C:\Program Files\ComponentOne Studio\Common\TDBGDemo.mdb

Adodc1.CommandType 2 – adCmdTable

Adodc1.RecordSource Orders

TDataLite1.DataSource Adodc1

TDataLite1.QueryMode True

TDataLite1.EOFAction adDoAddNew

Adodc2.ConnectionString

Provider=Microsoft.Jet.OLEDB.3.51;Persist Security

Info=False;Data Source=C:\Program Files\ComponentOne Studio\Common\TDBGDemo.mdb

Adodc2.CommandType 2 – adCmdTable

Adodc2.RecordSource Orders

DataGrid1.DataSource Adodc2

Step 4.

Open the property pages for TDataLite1, and go to the Fields page. Delete all fields except the following: OrderID, CustomerID, ShipName (to delete a field, select it in the field list and press Del).

Step 5.

In the Fields property page for TDataLite1, select the ShipName field and change its QueryOperation property, select starts with in the Query Operation combo box.

Step 6.

In the Fields property page for TDataLite1, create four additional fields (by clicking the right mouse button and choosing New Field from the menu). For each of them select the Data radio button, indicating that the field is a data field. For each of the four new fields, set its Name, DataSourceField and QueryOperation properties, typing in the Name edit box and selecting from the lists in the DataSource Field and Query Operation combo boxes.

NOTE: You must change Query Mode to 0 - Both or 1 - Query only for the Query Operation combo box to become available.

Name: DataSource Field: Query Operation:

OrderDateFrom OrderDate >=

OrderDateTo OrderDate <=

RequiredDateFrom RequiredDate >=

RequiredDateTo RequiredDate <=

Step 7.

Set properties of other controls as follows:

Text1.DataSource TDataLite1

Text1.DataField OrderID

Text2.DataSource TDataLite1

Text2.DataField CustomerID

Text3.DataSource TDataLite1

Text3.DataField OrderDateFrom

Text4.DataSource TDataLite1

Text4.DataField OrderDateTo

Text5.DataSource TDataLite1

Text5.DataField ShipName

Text6.DataSource TDataLite1

Text6.DataField RequiredDateFrom

Text7.DataSource TDataLite1

Text7.DataField RequiredDateTo

Set label and button captions according to the picture.

Step 8.

Add the following code to Command1:

Private Sub Command1_Click()

Adodc2.Recordset.Filter = TDataLite1.QueryFilter

End Sub

Run the Program and Observe the Following:

We leave it to you to experiment with different queries and their results, as it was done in Tutorial 8. We just want you to notice the following:

•

Now you have a sophisticated query form where you can specify different criteria, including date ranges. Four new fields created on Step 5 support data range conditions. ShipName condition is "starts with" rather than "equals," that was specified on Step 4. Field values in a record generate conditions joined with AND.

•

You can specify complex queries with more than one condition joined with OR, simply by adding new records to the query form. To add a new record to query, simply pressing the Next button on TDataLite1 when it is positioned on the last record. This is enabled by our setting TDataLite1.EOFAction=adDoAddNew.

•

Pressing the Apply button applies the specified query to Adodc2. TDataLite1 remains in query mode at all times.


Tutorial 10 - OLAP - Decision Support, Pivot Table

In this tutorial, you will see an important new functionality that TDataLite adds to ComponentOne True DBGrid 8.0 (OLE DB version). This functionality has many names, such as Data Analysis, Decision Support, On-Line Analitycal Processing (OLAP), Pivot Table, Decision Cube, etc.

The essence is to allow end-users to explore data in different projections and hierarchies. The user can interactively choose and reorder the dimensions in which data are represented and summarized. An OLAP front-end, a pivot table browser/grid displays data in a hierarchical crosstab view.

With TDataLite, True DBGrid 8.0 becomes an OLAP front-end control. It gives you important advantages over other existing OLAP solutions:

•

You no longer have to rely on external tools adding OLAP functionality to your applications, you can use the same grid control that you always have, with the same familiar object model.

•

True DBGrid is fully customizable and programmable in OLAP (Pivot) mode, as it is in all other modes. You can make your OLAP solutions look and feel the same as other parts of your application, so your users won’t need to learn additional, external tools and user interface.

TDataLite Pivot mode uses ADO MD (Microsoft ActiveX Data Objects (Multi-Dimensional)) that works with an OLAP-enabled OLE DB provider, such as Microsoft OLAP Services. These components must be installed on the client computer. The easiest way to guarantee it is to install Microsoft Office 2000 (Microsoft Excel and MS Query). In this tutorial, we will use Office applications, Microsoft Excel and Microsoft Query to prepare data (OLAP cube)

Note: You can use TDataLite in Pivot mode with other, third-party data bound controls that are able to display hierarchical OLE DB data. However, using it with ComponentOne True DBGrid allows you to benefit from close integration between the two controls, as you will see in the design time steps of this tutorial. If you decide to use TDataLite Pivot mode with data-bound controls other than TDBGrid, TDataLite.PivotFieldsAllLevels property must be set to False.

Step 1.

Prepare an OLAP cube based on an SQL query from Orders and Order Details tables (also using Customers, Categories and Products tables for descriptions) with the following dimensions: Country, CompanyName, CategoryName, ProductName, and the following measures: Sum Of Quantity, Sum Of ExtendedPrice (where ExtendedPrice = Quantity * UnitPrice * (1 – Discount)).

Do it using Microsoft Excel 2000, with PivotTable and PivotChart Wizard (in the Data menu): choose “External Data Source” in step 1, invoke Microsoft Query in step 2, then formulate the query and select the Create OLAP Cube option in the File menu of Microsoft Query. This will invoke the OLAP Cube Wizard. Select ExtendedPrice and Quantity in step 1, select all four dimensions in step 2 and save the cube in a file in step 3.

We do not describe the steps in creating the cube in detail, because they are not specific to TDataLite. You are probably familiar with this procedure already. If not, consult Microsoft Excel documentation. Or you can just leave it for now and use the pre-built cube, ORDERS.CUB that can be found in the Tutorial10\Data subdirectory.

Step 2.

Place the following controls on the form (Form10) as shown in the figure: a TDataLite control (TDataLite1), a True DBGrid 8.0 control (TDBGrid1), three labels (Label1-3), three list boxes (List1-3) and three command buttons (Command1-3).

Step 3.

Set TDataLite1 properties as follows:

Pivot True

PivotConnectionString DATA SOURCE=C:\Program Files\ComponentOne\True DataControl Lite 8.0\Tutorials\Tutor10\data\orders.cub;Provider=msolap;

PivotCubeName OCWCube

TDataLite Pivot mode is special in that only these three properties are relevant at design time. All the rest, including all the properties specified in TDataLite Property Pages, are ignored in Pivot mode.

Set TDBGrid1 properties as follows:

DataSource TDataLite1

DataView 1 - Hierarchical

Note:

It is essential that True DBGrid is used in Hierarchical mode, since OLAP structure is inherently hierarchical.

Step 4.

Select Retrieve Fields from TDBGrid1 context menu. The following columns will appear: Category, Company, Country, Product, Sum Of Quantity, Sum Of ExtendedPrice. First four are dimensions, last two are measures.

This is design-time layout. You have one column for each dimension and measure of the cube, so you can specify their properties to customize their run-time appearance and behavior.

At run time, the grid column layout will be different. Grid columns will be divided into two splits. The first split will show one or more dimensions chosen by the user as row dimensions (specified in the PivotRowDimensions property) in a hierarchical view with expandable/collapsible nodes. The second split will show the data (measure specified in the PivotMeasure property) in a crosstab view, one column for each value of the column dimension (dimension specified in the PivotColumnDimension property). The “default” values, displayed in a special “All” row, that remain visible when the row is collapsed, are sums (or other aggregates, according to the measure definition) of all subordinate rows. It is possible and customary that not all dimensions participate either as a row or column dimension, some can be omitted from the user selection. Columns corresponding to such dimensions will be invisible, and corresponding data will be aggregated.

As with TDataLite crosstab feature (see Tutorial 2), all run-time crosstab columns inherit design-time property setting of the corresponding measure column, but these settings can be programmatically changed at run time. For example, setting PivotColumnDimension to “Country” will generate multiple crosstab columns: All, Austria, Belgium, Brazil, etc. All these columns will be created with settings inherited from the Sum Of ExtendedPrice column (supposing PivotMeasure = “Sum Of ExtendedPrice”).

Step 5.

Resize the columns to your liking (select Edit from TDBGrid1 context menu).

Step 6.

Open TDBGrid1 Property Pages. In the Columns page, for Columns(05) [Sum Of Extended Price], set NumberFormat=Currency. In the Splits page, open Splits(00).Columns node, then open Columns(05) [Sum Of Extended Price] node and set ForeColor = Dark Blue (Color Set: Standard Colors).

At run time, you will see that crosstab columns use these color settings. For example, setting PivotColumnDimension to “Category” will generate multiple crosstab columns: All, Beverages, Condiments, Confections, etc. If selected PivotMeasure is “Sum Of ExtendedPrice”, then all these columns will show the dollar sign according to NumberFormat=Currency and use Dark Blue text color.

Step 7.

All the powerful versatile features of True DBGrid are available in Pivot mode. To see how you can customize your decision support grid, add the following event code:

Private Sub TDBGrid1_FetchCellStyle(ByVal Condition As Integer, ByVal Split As Integer, Bookmark As Variant, ByVal Col As Integer, ByVal CellStyle As TrueOleDBGrid70.StyleDisp)

‘ Values greater than $2,000 shown with green backcolor

If TDBGrid1.Columns(Col).CellText(Bookmark) = "" Then Exit Sub

If TDBGrid1.Columns(Col).CellValue(Bookmark) > 2000 Then

CellStyle.BackColor = vbGreen

End If

End Sub

At run time, you will see that all price values higher $2,000 are highlighted in green.

Step 8.

As it was said above, the grid will show data organized in row hierarchy and column crosstab according to user choice. Add the following code to the form’s Load event to specify the initial dimensions:

Private Sub Form_Load()

' Initial dimensions

List1.Selected(0) = True

List1.Selected(1) = True

List2.ListIndex = 2

List3.ListIndex = 0

TDataLite1.PivotRowDimensions = "Country,Company"

TDataLite1.PivotColumnDimension = "Category"

TDataLite1.PivotMeasure = "Sum Of ExtendedPrice"

TDataLite1.PivotOpen

End Sub

At run-time, when the form is shown, the data, values of the Sum Of ExtendedPrice measure, will be initially organized into Country,Company hierarchy, with Category crosstab – one crosstab column for each Category value: All, Beverages, Condiments, Confections, etc.

Step 9.

Finally, we need to provide means for the user to change the dimension layout at run time. You can do it in many ways, only your imagination is the limit, but for this tutorial we have chosen a simple user interface: three list boxes for selecting row dimensions, column dimension and measure. Pressing the Apply button (Command1) refreshes the grid with the new selected layout.

Fill the strings in the List property for each of the three list boxes as shown in the figure: Country, Company, Category, Product for List1-2; Sum Of Extended Price, Sum of Quantity for List3.

List1 is for Row Dimensions. It is a multi-selection list box (set its MultiSelect property to 2 – Extended) allowing the user to choose one or more dimensions for row hierarchy. Two command buttons (Command2-3; we gave them arrow bitmap pictures in the tutorial, but that is not necessary, of course) allow the user to rearrange items in List1, that is, to change the row hierarchy order.

List2 is for Column Dimensions. It is a single-selection list box for choosing the dimension for crosstab. Simple code (see Sub AdjustSelection in the code below) prevents the user from selecting a dimension both in List1 and List2.

List3 is for Measures. It allows the user to select one of the two measures: Sum Of Extended Price or Sum of Quantity.

Fill in the following event code:

Private Sub Command1_Click()

‘ Applying the query

Screen.MousePointer = vbHourglass

TDataLite1.PivotRowDimensions = ""

For I = 0 To List1.ListCount - 1

If List1.Selected(I) Then

If TDataLite1.PivotRowDimensions <> "" Then

TDataLite1.PivotRowDimensions = TDataLite1.PivotRowDimensions & ","

End If

TDataLite1.PivotRowDimensions = TDataLite1.PivotRowDimensions & List1.List(I)

End If

Next I

If TDataLite1.PivotRowDimensions = "" Then

MsgBox "Select at least one item in Row Dimensions"

Exit Sub

End If

TDataLite1.PivotColumnDimension = ""

If List2.ListIndex <> -1 Then

TDataLite1.PivotColumnDimension = List2.List(List2.ListIndex)

End If

TDataLite1.PivotMeasure = ""

If List3.ListIndex <> -1 Then

TDataLite1.PivotMeasure = List3.List(List3.ListIndex)

End If

TDataLite1.PivotOpen

Screen.MousePointer = vbArrow

End Sub

Private Sub AdjustSelections()

‘ Preventing the user from selecting a dimension both in List1 and List2

ColDim = ""

If List2.ListIndex <> -1 Then

ColDim = List2.List(List2.ListIndex)

End If

For I = 0 To List1.ListCount - 1

If List1.Selected(I) And List1.List(I) = ColDim Then

List1.Selected(I) = False

End If

Next I

End Sub

Private Sub List1_Click()

AdjustSelections

End Sub

Private Sub List2_Click()

AdjustSelections

End Sub

Private Sub Command3_Click()

' Changing the row hierarchy: moving a dimension down in the list

If List1.SelCount <> 1 Then Exit Sub

For I = 0 To List1.ListCount - 2

If List1.Selected(I) Then

NextDim = List1.List(I + 1)

List1.List(I + 1) = List1.List(I)

List1.List(I) = NextDim

List1.Selected(I) = False

List1.Selected(I + 1) = True

Exit For

End If

Next I

End Sub

Private Sub Command2_Click()

' Changing the row hierarchy: moving a dimension up in the list

If List1.SelCount <> 1 Then Exit Sub

For I = 1 To List1.ListCount - 1

If List1.Selected(I) Then

NextDim = List1.List(I - 1)

List1.List(I - 1) = List1.List(I)

List1.List(I) = NextDim

List1.Selected(I) = False

List1.Selected(I - 1) = True

Exit For

End If

Next I

End Sub

Run the Program and Observe the Following:

•

The initial display shows Country and Company row hierarchy, according to the initial settings. Each row represents a country, with columns (crosstab) representing product categories: All, Beverages, Condiments, Confections, etc. Crosstab cells display the dollar amount, Sum Of ExtendedPrice for a particular country and category. A special column named “All” displays the sum for all categories, and there is also a special row called “All” displaying the sum for all countries.

•

Expanding a country row (clicking the ‘+’ sign in the Country column, try expanding Brazil, for example), you can see data for all companies in that country.

•

Note that all amounts greater than $2,000 are highlighted with green color. This is implemented in code with the FetchCellStyle event handler.

•

Change the dimension hierarchy and layout: select Country in List2 (Column Dimension), then select Category and Product in List1 (Row Dimensions), and select Sum Of Quantity in List3 (Value Measure). Press the Apply button.

•

You see that the column and data layout has changed: the row hierarchy is now Category,Product, and crosstab columns represent countries: All, Austria, Belgium, Brazil, etc. Try expanding a row (clicking the ‘+’ sign, try expanding Beverages, for example) to see data for all products in a certain category.

•

Experiment with our decision support system, varying Row and Column Dimensions and Value Measure. Think of the power of On-Line Analytical Processing you can now deliver to your customers with True DBGrid 8.0 and True DataLite 8.0!

Congratulations, you have completed all ten TDataLite tutorials! You are now ready to take full advantage of True DataControl Lite in your applications.


Object Model

The True DataControl and its programmable components are all ActiveX objects designed according to Microsoft specifications. If you are already familiar with the Visual Basic object and collection models, you will have no problem using True DataControl.

If you are new to Visual Basic, please read Working with Objects and Collections, which illustrates how to manipulate True DataControl objects in code. Although individual objects are designed to perform different tasks, the techniques used to manipulate them are the same. Once you have mastered these common programming constructs, using Visual Basic and ActiveX controls will be quite easy and intuitive.

Regardless of your experience level, please read the following section, as it provides a sketch of all True DataControl objects and collections.


True DataControl Objects and Collections

True DataControl provides a rich set of properties, methods, and events that enable you to develop sophisticated database applications with much less manual coding than using conventional data source controls. The organization imposed by True DataControl object model makes it easier to work with its large feature set.

Objects and collections that refer to True DataControl entities, such as fields, can be customized at design time or run time. Objects and collections that refer to abstract entities, such as arrays and bookmarks, are only available in code at run time.

When you add a True DataControl file to a Visual Basic project, the True DataControl (TData) is added to the Toolbox:

TData

ComponentOne True DataControl

In the Lite version, it will be

TDataLite

ComponentOne True DataControl Lite

The type library for True DataControl 8.0 (its short name is TrueData60Ctl, or TrueDataLite70Ctl for the Lite version 8.0) also contains definitions for the following objects:

NamedBookmark | Represents a bookmark appearing in the list in the Bookmarks dialog.
Constraint | Represent a field-level or record-level constraint.
Field | Represents a True DataControl field.
FilterExpression | Represents a filter expression.
Parameter | Represents a True DataControl parameter.
PropertyExpression | Represents a control property expression.
RangeCondition | Represents a field’s range condition (unavailable in the Lite version).
RowBuffer | Transfers data to and from user mode events (unavailable in the Lite version).

A collection is an object used to group similar objects. Since a collection itself is an object, you can manipulate it in code just as you would any other object. The type library for True DataControl 8.0 contains definitions for the following collections:

NamedBookmarks | Contains zero or more NamedBookmark objects.
Constraints | Contains zero or more Constraint objects.
Fields | Contains zero or more Field objects.
FilterExpressions | Contains zero or more FilterExpression objects.
Parameters | Contains zero or more Parameter objects.
PropertyExpressions | Contains zero or more PropertyExpression objects.
RangeConditions | Contains zero or more RangeCondition objects.

When using True DataControl memory array mode (DataMode = 1 – MemoryArray), you also need to add a reference to the ComponentOne XArrayDB Object to your project. This is not a control, but a reference that defines a single object:

XArrayDB

Variant array used as a data source in storage mode.

The following sections provide a brief overview of True DataControl objects and collections.

TData Control

TDataLite Control

NamedBookmark Object, NamedBookmarks Collection

Constraint Object, Constraints Collection

Field Object, Fields Collection

FilterExpression Object, FilterExpressions Collection

Parameter Object, Parameters Collection

PropertyExpression Object, PropertyExpressions Collection

RangeCondition Object, RangeConditions Collection

RowBuffer Object

XArrayDB Object


TData Control

All of the properties, events, and methods for the True DataControl control are listed in the following tables.

TData Control All Members

TData Control Properties

TData Control Methods

TData Control Events


TDataLite Control

All of the properties, events, and methods for the True DataControl control are listed in the following tables.

TDataLite Control All Members

TDataLite Control Properties

TData Control Methods

TData Control Events


NamedBookmark Object, NamedBookmarks Collection

This collection plays an auxiliary role. Its only purpose is to give the programmer control over the list of bookmarks showing in the Bookmarks dialog. It is a run-time only collection, and is not available at design time.

The NamedBookmarks collection consists of NamedBookmark objects, each of which is simply a bookmark with meaningful name attached to it. Use the NamedBookmarks property to accesss the NamedBookmarks collection.

For more information, see Bookmarks Dialog.


Constraint Object, Constraints Collection

A Constraints object represents a constraint that should be satisfied on field or record modification. It is basically a boolean expression that is evaluated every time a modification occurs. It also contains error messages and an applicability condition expression.

True DataControl has two different collections of Constraint objects:

The Constraints collection is returned by the Constraints property of the TData control itself, which contains record-level constraints.

The Constraints collection returned by the Constraints:Field property of a Field object. Every data field can contain several constraints, which are called field-level constraints. If a field does not have constraints, its Constraints:Field collection is empty.

For more information, see Validation and Constraints.


Field Object, Fields Collection

A Field object represents a True DataControl field, the main building block of a TData control. Fields are variables that constitute a record in the Recordset.

Field objects form the Fields collection of a TData control. Use the Fields property to access the Fields collection. This collection defines the data structure of the True Data control exposed to its data-aware client controls.

For more information, see True DataControl Fields.


FilterExpression Object, FilterExpressions Collection

Filter expressions restrict the set of records retrieved to the True Data recordset. For each fetched record, True Data evaluates all filter expressions and excludes the record from the resulting recordset if any of them evaluates to False.

FilterExpression objects form the FilterExpressions collection of a TData control. Use the FilterExpressions property to access the FilterExpressions collection.

For more information, see Filters.


Parameter Object, Parameters Collection

A Parameter object represents a True DataControl parameter. Parameters are variables, like fields, but they differ from fields in that their values do not depend on a particular record. Parameters hold values that belong to the True DataControl as a whole rather than to individual records of its recordset.

Among other uses, True DataControl parameters enable you to accommodate a parameterized SQL query as your data source, both at design and at run time.

Parameter objects form the Parameters collection of the TData control. Use the Parameters property to access the Parameters collection.

For more information, see True DataControl Parameters.


PropertyExpression Object, PropertyExpressions Collection

A True DataControl can have zero or more PropertyExpression objects in its PropertyExpressions collection. Each PropertyExpression object defines a “dynamic property expression” governing a property of a control residing in the same form with the True DataControl. Use the PropertyExpressions property to access the PropertyExpressions collection. Property expressions can manage a property of any control, not necessarily a data-aware control, including the Form itself.

True DataControl automatically maintains the property value equal to the current value of the expression at all times.

For more information, see Control Property Expressions.


RangeCondition Object, RangeConditions Collection

Each Field object representing a True DataControl field has a RangeConditions collection, which can contain zero or more RangeCondition objects. Use the RangeConditions property to access the RangeConditions collection for a Field object. The RangeConditions collection is unavailable in True DataControl Lite.

A RangeCondition object represents a condition that restricts the set of records fetched to the True DataControl recordset by specifying that the field must be equal to (or satisfy other comparison with) the result of an expression.

Range conditions are better optimized for performance than filters. Using range conditions is the preferred way to implement master-detail relationships between True DataControl controls.

For more information, see Field Range Conditions.


RowBuffer Object

The RowBuffer object is only used when the DataMode property is set to 2 – User Events. It exists only to transfer data to and from the True DataControl in user mode events. You cannot create a standalone RowBuffer object.

For more information, see User Events Mode.


XArrayDB Object

The XArrayDB object implements an array of arbitrary variants. It supports up to 10 dimensions, and automatically shifts its contents when elements (or dimensions) are inserted and deleted. Using it with True DataControl, you only need two dimensions: rows and columns, so you should always assume it has two dimensions.

Unlike the RowBuffer object, you can create a standalone XArrayDB object, and even use it outside the context of True DataControl.

XArrayDB is implemented as a separate .OCX file; it is not contained in the True DataControl .OCX file.

The XArrayDB object is used as a data storage for a True DataControl in memory array data mode (DataMode = 1 – Memory Array).

For more information, see Memory Array Mode.


Modifying True DataControl Collections from Code

Usually, you will set up a True DataControl at design time, filling its Fields and other collections in property pages.

In more involved cases, you may need to modify True DataControl collections in code. There are some restrictions concerning where you are allowed to do that and what that might cause. All True DataControl functionality depends on the collections settings, so they can’t be allowed to change arbitrarily.

You are not allowed to modify True DataControl collections (or their item objects) in any way from True DataControl event procedures, except for one, specifically designed for that purpose – WillOpenData event. An attempt to change collections in other event will generate an error.

If you make any alteration to True DataControl collections outside the WillOpenData event, this will cause immediate refresh of the TData control. This includes all changes to collections and their item objects, even a simple operator setting a property of an object.

If you need more than one change at once (you usually do!), use the ChangeInProgress property. Setting it to True disables the automatic refresh so you can make multiple changes. After you are done with changes, set the ChangeInProgress property back to False, to let the refresh take place. Failure to return ChangeInProgress to False can lead to unpredictable results, since the True DataControl internal state will not be synchronized with its collection settings.

An exception to these rules is the collection returned by the NamedBookmarks property, which can be modified at any time, with no consequences.


Working with Objects and Collections

This section describes how to work with objects and collections in Visual Basic code, with an emphasis on efficiency. Although the concepts are illustrated with True DataControl objects and collections, you can apply the same fundamentals to all Visual Basic objects and collections.

You can reference an object in a collection using its zero-based index. For example, the first field in a TData control has an index value of 0. You can read or set the corresponding Field object's properties as follows:

' Read a property of Field

variable = TData1.Fields(0).Property

' Set a property of Field

TData1.Fields(0).Property = variable

The Fields property returns an object of type Fields, which is a collection of Field objects. The Fields property is the default (implicit) property of the TData control. This means that the name of the collection, Fields can be omitted, so the previous example (with Name as the field’s property) can be abbreviated as follows:

' Read the field’s Name

variable = TData1(0).Name

' Set the field’s Name

TData1(0).Name = variable

This does not apply to other properties, only the Fields property name can be omitted this way.

Or, if we take another property of the Field object, the Value property, it will become the following:

' Read the field’s value

variable = TData1(0).Value

' Set the field’s value

TData1(0).Value = variable

The Value property is the default (implicit) property of the Field object. That’s why the Value property name can be omitted and the preceding example re-written as

' Read the field’s value

variable = TData1(0)

' Set the field’s value

TData1(0) = variable

Another implicit property in True DataControl is the Value property of the Parameter object. It also can be omitted in code. All other properties and collections must be referenced in full.

You can create a reference to an object in a collection using the collection's Item property. The following code creates a reference to the first field:

' Declare Field0 as a Field object

Dim Field0 As TrueData60Ctl.Field

' Set Field0 to reference the first Field in the collection

Set Field0 = TData1.Fields.Item(0)

Note the use of the type library qualifier TrueData60Ctl in the preceding example. Using the type library qualifier is recommended in order to resolve potential naming conflicts with other controls. For example, if you use another control in the same project that also defines an object named Field, the TrueData60Ctl type library qualifier is required, as is the type library qualifier for the other control.

Since the Item property is implicit for collections, you can omit it:

' Declare Field0 as a Field object

Dim Field0 As TrueData60Ctl.Field

' Set Field0 to reference the first Field in the collection

Set Field0 = TData1.Fields(0)

You can now use Field0 to read or set the Field object's properties:

variable = Field0.Property ' Read a property

Field0.Property = variable ' Set a property

Very often, you need to read and set more than one of an object's properties. For example:

' Read a Field object's properties

variable1 = TData1.Fields(0).Property1

variable2 = TData1.Fields(0).Property2

' Set a Field object's properties

TData1.Fields(0).Property1 = variable1

TData1.Fields(0).Property2 = variable2

This code is very inefficient because each time the object TData1.Fields(0) is accessed, Visual Basic creates a reference to the object and then discards it after the statement is completed. It is more efficient to create a single reference to the object up front and use it repeatedly:

' Declare Field0 as a Field object

Dim Field0 As TrueData60Ctl.Field

' Set Field0 to reference the first Field in the collection

Set Field0 = TData1.Fields(0)

' Read a Field object's properties

variable1 = Field0.Property1

variable2 = Field0.Property2

' Set a Field object's properties

Field0.Property1 = variable1

Field0.Property2 = variable2

This code is much more efficient and also easier to read. If your Visual Basic application accesses collection objects frequently, you can improve the performance of your code significantly by adhering to these guidelines.

Similarly, you can apply this technique to other objects and collections of True DataControl, and of Visual Basic in general.

The most important thing is to use this technique with the Recordset property, since it is often used in performance-critical loops. It’s a very poor programming practice to write code like

variable = TData1.Recordset.Fields(0)

If you need to make repetitive calls to the Recordset property, set up a variable for it, as in the following example

Dim RS As ADODB.Recordset

Set RS = TData1.Recordset

variable = RS(0)

Visual Basic also provides an efficient With...End With statement for setting multiple properties of an object without explicitly assigning it to a variable. For example, the following code sets multiple properties of the first field (recall that collections are zero-based):

With TData1.Fields(0)

.Property1 = variable1

.Property2 = variable2

End With

Two of the True Data collections, Fields and Parameters (returned by the Fields and Parameters properties, respectively) allow you to reference their members by name. So you can reference a Field or a Parameter object using either its index or its name. Thus, the following statements are equivalent:

' Declare Field0 as a Field object

Dim Field0 As TrueData60Ctl.Field

' Reference by numeric index

Set Field0 = TData1.Fields(0)

' Reference by field name

Set Field0 = TData1.Fields("LAST")

To create and add an object to a collection, use the collection's Add method. For example, you can create more fields by adding newFieldsField objects to the Fields collection:

' Create a field object with index 0

Dim F As TrueData60Ctl.Field

Set F = TData1.Fields.Add(0)

This code adds a Field object with index 0 to the Add collection of TData1. The original TData1.Fields(0) object now has an index of 1. Alternatively, you can create a Field object with index 1:

' Create a field object with index 1

Dim F As TrueData60Ctl.Field

Set F = TData1.Fields.Add(1)

Note that the Fields method of the Add collection is used like a function, with its arguments (here, the field index) enclosed in parentheses. Also, since the Remove method always returns a reference to the Field object that was just created, you must precede the assignment statement with the Visual Basic Set keyword.

To remove an existing item from a collection, use the Remove method:

' Remove the field object with index 1

TData1.Fields.Remove 1

After this statement is executed, all fields with collection indexes greater than 1 will shift down by 1 to fill the place of the removed field. Note that the Count method is called like a subroutine---its argument is not enclosed in parentheses.

You can determine the number of objects in a collection using the collection's Count property:

' Set a variable to the number of fields in TData1

variable = TData1.Fields.Count

You can also iterate through all objects in a collection using the Count property as in the following example, which prints the name of each field in a True DataControl:

For n = 0 To TData1.Fields.Count - 1

Debug.Print TData1.Fields(n).Name

Next n

The Count property is also useful for appending and removing objects:

' Determine how many fields there are

Dim NumFields As Integer

NumFields = TData1.Fields.Count

' Append a field to the end of the Fields collection

Dim F As TrueData60Ctl.Field

Set F = TData1.Fields.Add(NumFields)

' The following loop removes all fields

While TData1.Fields.Count <> 0

TData1.Fields.Remove 0

Wend

Visual Basic also provides an efficient For Each...Next statement that you can use to iterate through the objects in a collection without using the Count property:

Dim F As TrueData60Ctl.Field

For Each F In TData1.Fields

Debug.Print F.Name

Next S

In fact, using the For Each...Next statement is the preferred way to iterate through the objects in a collection.


Data Access Modes

A TData control can function in one of three data access modes, as determined by its DataMode property:

0 – DataSource

Data source mode is used to operate on data from an ADO Recordset. It can be a database or another source specified by the control’s data source properties (on the DataSource property page), SourceRecordset property, or DataSource and DataMember properties (DataSource/DataMember are available only in version 7). This is the default mode.

1 - MemoryArray

Memory array mode is used to store data in an internal array without relying on any external data sources.

2 - UserEvents

User events mode provides a protocol for custom data sources that cannot be implemented in data source mode or memory array mode. This mode is intended for expert users only.

At design time, you can set the DataMode property in the Visual Basic Properties window or in the DataSource property page.


Data Source Mode

A TData control in data source mode uses an ADO recordset as its underlying data. The recordset is accessible via the SourceRecordset property. It is important to distinguish this (source) recordset from the recordset that True DataControl exposes to its clients, the bound controls. The latter is also an ADO recordset and it is accessible via the Recordset property.

SourceRecordset is the source of underlying data. When True DataControl needs to fetch or store data, it does so using SourceRecordset, on which it operates internally. In more involved cases, to control database modification, developer can override the default action of saving changes in the database using DataWrite event.

Users don’t normally need to access SourceRecordset directly, unless they wish to synchronize (refresh) it with the current data from the database (that can changed by other users; use TData.SourceRecordset.Requery for that purpose), or change its properties or contents programmatically. For more information, see Modifying SourceRecordset from code.

The Recordset consists of the data exposed to the controls that are bound to a TData control. This is the True DataControl recordset as users see it, and it may contain more (or less) fields than the SourceRecordset. For example, calculated fields appear in Recordset, but not in SourceRecordset, because they are not part of the underlying data. Users operate on the True DataControl recordset in exactly the same way as on a standard ADO data control's (ADODC’s) recordset. For example, setting TData.Recordset.Bookmark moves a TData control to a specified record.

Note

True DataControl Lite does not have the SourceRecordset property, its role plays the standard ADO data source to which TDataLite is bound via DataSource/DataMember properties, see Binding TDataLite to a data source.

Defining SourceRecordset at design time

Retrieving Fields from the Data Source at Design Time

Events in Creating Recordset at Run Time

Setting SourceRecordset and DataSource at Run Time

Connection Pooling

Optimizing Data access Performance

Modifying SourceRecordset from Code

Using True DataControl with Master-Detail (hierarchical) ADO Recordsets


Defining SourceRecordset at design time

There are two different ways to connect a True DataControl to the data at design time:

•

Using True DataControl as an independent data source, specifying data connection on its DataSource property page. This is the most convenient way of using True DataControl. This option is described in the remainder of this section. This option is unavailable in True DataControl Lite.

•

Setting its DataSource and DataMember properties to an available standard ADO/OLE DB data source, such as ADODC control or DataEnvironment. This is the only option in True DataControl Lite, see Binding TDataLite to a data source. In True DataControl, this option is available starting from version 7.0.

The DataSource property page is used to define the data source connection at design time. It resembles the property pages of a standard ADO data control (ADODC), so its use should be easy for those who are familiar with ADODC. It combines all the attributes that can be found on the General, Authentication, and RecordSource pages in ADODC.

We refer to the properties specified in the DataSource page as data source properties. They can be set in the Visual Basic Properties Window, or the DataSource property page. They can also be set from code at run time, for example in the Form_Load event, or the WillOpenData event. Setting data source properties at run time after initial startup is also possible, but it will not affect the TData control until the Refresh method is called, at which time the True DataControl recordset will be recreated with the new data source property values.

The Source of Connection section of the DataSource page is designed to facilitate ConnectionString setting by allowing you to set the ConnectionString property either directly with Use Connection String option and Build dialog box, or by using special Data Link File and ODBC Data Source Name options. The standard Build dialog presents all available OLE DB providers and their properties. The Other Attributes edit box allows you to add some information to the ConnectionString, in case it is not supported by the standard Build dialog.

The Authentication section contains the UserName and Password properties that are necessary in case the selected OLE DB provider uses authorization.

The RecordSource section facilitates setting the RecordSource property. Depending on the choice in the CommandType combo box, the user can either select a table or stored procedure name from a list, or enter the text of a SQL statement.

Finally, the LockType combo box specifies the type of locking used in editing, including an adLockReadOnly option, which means a read-only recordset.

Some of less common data source properties are not represented on the DataSource property page. They are available at design time in the Visual Basic Properties window. All data source properties have read/write access both at design and at run time.

The Test button located on the DataSource page tests the connection and recordset creation as specified by the data source property values.

With data source properties defined, True DataControl tries to establish database connection when it needs information from the database. That is, when the Fields property page is opened, performing syntax check and on other occasions. This “live connection at design time” behavior can be turned off by setting the DesignConnection property to False. It can be useful when working in disconnected mode, where you don’t have access to the database, or if establishing connection is too time consuming or simply unnecessary. With the DesignTimeout property you can control the timeout, number of seconds that True DataControl waits for establishing connection at design time.

The following is the list of all True DataControl data source properties. All of these are standard properties of ADO Connection, Command, and Recordset objects. See ADO documentation for detailed description of these properties. You may notice that not all ADO recordset properties are listed. Some important properties, such as Filer and Sort, are not supported at design time as True DataControl data source properties. If you need to set such properties, use the OpenData event. For more information, see Events in creating recordset at run time.

Properties for Establishing Connection with a Data Source:

ConnectionString

Contains the information used to establish a connection to a data source.

ConnectionTimeout

Indicates how long to wait while establishing a connection before terminating the attempt and generating an error.

Mode

Indicates the available permissions for modifying data.

Password

For OLE DB providers that need authentication.

UserName

For OLE DB providers that need authentication.

Properties for Creating a Recordset Object (SourceRecordset):

CacheSize

The number of records from a recordset object that are cached locally in memory.

CommandTimeout

How long to wait while executing a command before terminating the attempt and generating an error.

CommandType

How RecordSource string must be interpreted.

CursorLocation

Location of the cursor engine, either on server or on client.

CursorType

Type of cursor used for a recordset object.

LockType

The type of locks placed on records during editing.

MaxRecords

The maximum number of records to return to a recordset from a query.

RecordSource

Source of recordset, usually an SQL statement or a table name.


Retrieving Fields from the Data Source at Design Time

Once you have specified the data source properties at design time, you can retrieve fields from the data source with the Retrieve Fields button on the Fields property page, or by selecting Retrieve Fields from the TData control's context menu.

SourceRecordset fields appear on the Fields property page. Each field’s Name and DataSourceField property is set to the field’s name as it appears in the SourceRecordset property.

Retrieved fields constitute the starting point for building the True DataControl Fields collection (the Fields property is used to obtain this collection). You can add calculated fields, delete some of the retrieved fields, and add some new data fields, if necessary. Order of the fields can be changed by drag-and-drop in the Fields page. A field’s Name can be changed to whatever string you need; it will represent the field’s name in the True DataControl Recordset. You can also change a field’s DataSourceName, thus attaching the field to a certain SourceRecordset field. Bear in mind that if DataSourceName does not correspond to any field in SourceRecordset, True DataControl will ignore the field.


Events in Creating Recordset at Run Time

True DataControl creates its recordset on startup and each time the Refresh method is called, by firing three events that allow full programmatic control over this process: WillOpenData, OpenData and OpenDataComplete.

The WillOpenData event occurs before recordset creation. This event gives the developer an opportunity to change True DataControl collections, such as Fields, before they are used to create the recordset. Use the Fields property to access the Fields collection. Any change to True DataControl fields and some other collections can obviously effect the resulting recordset. That is why True DataControl collections can’t be modified arbitrarily from code, surely not while they are used to create a recordset. You are allowed to do so in WillOpenData, so the recordset created will be based on the modified collection settings. True DataControl collections cannot be modified in any event other than WillOpenData. Modifying True DataControl collections from code outside of events causes refresh to occur. For more information, see Modifying True DataControl collections from code.

The OpenData event occurs immediately after WillOpenData. The main purpose of this event is to allow the developer to set SourceRecordset in code to an arbitrary ADO recordset (in version 7.0, DataMember/DataSource properties also can be set in OpenData). If this is done, True DataControl ignores the data source property settings, does not create SourceRecordset, it uses the one supplied by the developer.

Another useful feature of the OpenData event is that it allows you to modify SourceRecordset while still relying on True DataControl for its creation. This is necessary because the True DataControl data source properties do not include all recordset properties. Some important properties, such as Filter and Sort, cannot be set at design time. The OpenData event allows you to modify the SourceRecordset created by True DataControl, to fine-tune it for your needs. For example, the following code ensures that the First field sorts the recordset, while the recordset itself is created automatically by True DataControl from data source property settings:

Private Sub TData1_OpenData()

TData1.SourceRecordset.Sort = "First"

End Sub

This twofold functionality of SourceRecordset in OpenData is achieved by the following simple rules:

•

The first time you get the SourceRecordset property value in the OpenData event procedure, True DataControl creates the recordset.

•

True DataControl creates the recordset immediately after the OpenData event if the event procedure has not set the SourceRecordset.

•

If the OpenData event procedure sets the SourceRecordset property, True DataControl does not create a new recordset, but uses the one already set.

The OpenDataComplete event occurs after the OpenData event, when True DataControl has created the recordset (if necessary), so all actions involved in creating the recordset have been completed. This is the place to put code, depending on the resulting recordset. For example, you can save a reference to the True DataControl SourceRecordset or Recordset property in a variable here.


Setting SourceRecordset and DataSource at Run Time

As an alternative to setting up the SourceRecordset at design time with True DataControl data source properties or DataSource/DataMember properties, you can set it at run time to any ADO recordset. The normal place to do this is the OpenData event. For more information, see Events in creating recordset at run time.

Bear in mind that the OpenData event is called on each refresh, as well as during startup. A TData control is refreshed when the Refresh method is called, or when changes occur in the Master TData control, in a True DataControl parameter, or in one of the True DataControl collections.

If you do not want to set up the recordset at design time, leave all True DataControl data source properties empty and set the SourceRecordset property to a valid ADO recordset in the OpenData event. Starting from version 7.0, you have an alternative to setting SourceRecordset: you can also set the DataSource/DataMember properties to an existing ADO/OLE DB data source, such as an ADODC control or DataEnvironment.

As for specifying True DataControl fields in this case, you have two options:

•

Leave the Fields property page empty; do not specify any fields. The fields will be retrieved from SourceRecordset. Field retrieval also occurs if you empty the collection returned by the Fields property within the WillOpenData event.

•

Create all necessary fields manually in the Fields page or in code in WillOpenData event. Create each field as a data field (select the Data radio button) and specify its Name and DataSourceField property.

When SourceRecordset or DataSource is set from code, the existing True DataControl fields are verified against the new SourceRecordset. Some of them might not exist in the new SourceRecordset, i.e., their DataSourceField property does not correspond to any field in the new SourceRecordset. Such fields become unavailable after refresh.

You can also set the SourceRecordset property (in version 7.0, also DataSource/DataMember properties) from code outside of True DataControl events. This will cause a refresh of the TData control, because its recordset needs to be rebuilt (you can use the ChangeInProgress property to postpone the refresh).

Note

The SourceRecordset property is unavailable in True DataControl Lite. Use DataMember/DataSource instead.


Connection Pooling

True DataControl set up at design time must use a connection to the database (ADO Connection object) creating its SourceRecordset. If every TData control would create its own separate connection object, that would engender serious performance problems, since establishing a connection is a performance-heavy operation for most databases.

True DataControl uses a pooling technique to minimize the number of simultaneously open connections. When a TData control creates its SourceRecordset, it first checks if a connection with exactly the same properties exists in the pool, was created by another TData control that is still active. If there is such connection, TData uses it instead of creating a new one.

In order for two TData controls to use a single connection, they must be

•

In DataMode = 0 - DataSource.

•

Set up at design time. TData controls with SourceRecordset or SourceConnection properties set at run time don't participate in connection pooling.

•

Active at the same time. They must either belong to the same form, or, if they reside in different forms, the two forms must be shown simultaneously. In other words, pooled connections don't survive their controls. Once a control's form is closed, all its connections are deleted from the pool. Reopening the form will re-create the connections.

•

The following properties must have exactly the same values (string comparison is case-sensitive):

ConnectionString, UserName, Password, CursorLocation,

Mode, ConnectionTimeout, CommandTimeout

If you want to pool TData connections in more complex cases, for example, between different forms open at different times, or between different invocations of a form, use the SourceConnection property.

To check the current status of the connection pool, use PooledConnectionCount and PooledConnections properties. These properties allow the developer to examine connections currently in the pool. They are useful when you are in doubt, perhaps not sure if all the connection-related properties have the same values, and want to see what is actually happening. Do not use these two properties for any other purposes than to make sure the connection pool works as intended.

Note

Connection pooling is unavailable in True DataControl Lite.


Optimizing Data access Performance

Performance Perils of Client-Side Cursors

Setting CursorType=adUseClient enables Microsoft Client Cursor Engine. This means that data will be fetched not directly from the database, but through a special cursor located on the client computer. Client cursors add some important functionality to ADO recordsets, such as Filter and Sort, but they also can lead to a substantial performance degradation if you fetch large amounts of data through the network. When you use client-side cursor, all the data is first fetched from the server to the client, and only then your recordset becomes active.

This performance alert is not specific to True DataControl. It is true for any other uses of ADO recordsets as well.

Note that CursorType=adUseClient by default.

Using SourceConnection to Minimize the Number of Database Connections

Some databases (for example, Oracle) are very sensitive to the number of simultaneously open database connections. Opening multiple connections can be a stress on resources with such databases. This is why, TData tries to reuse database connections with same ConnectionString settings, see Connection pooling. But in some cases, especially if you open and close a form with TData controls, connection pooling won’t work, connections may be removed from the pool when a form closes. Then you might want to use the SourceConnection property to set a pre-established connection for TData controls.


Modifying SourceRecordset from Code

You may find it useful to modify the SourceRecordset from code. For example, you can allow the end-user to change its Sort property, to implement different sorts in your TData control.

If the SourceRecordset is changed as a whole (for example, when its Sort or Filter properties are changed, or its Requery method is called), True DataControl “feels” the change and refreshes accordingly, refetching all data to reflect the change.

For another example of True DataControl's “sensitivity” to SourceRecordset changes, see Using True DataControl with master-detail (hierarchical) ADO recordsets.


Using True DataControl with Master-Detail (hierarchical) ADO Recordsets

True DataControl honors master-detail relationships between ADO recordsets. Hierarchical (master-detail) recordsets can be created with Microsoft SHAPE data provider and with Visual Basic DataEnvironment.

When two recordsets, one designated as the master and the other as the detail, are assigned to two TData controls (by setting their SourceRecordset property in code), we have two TData controls in a master-detail relationship. When the master control is positioned to a record, the detail control refreshes its recordset data accordingly.

This behavior is a consequence of the general rule that True DataControl reacts to a change of its SourceRecordset as a whole, refreshing its data. For more information, see Modifying SourceRecordset from code.

However, this sort of master-detail relationship is different from the True DataControl native master-detail, which must be specified explicitly by setting the Master property of a TData control. A TData control does not become the Master of another TData control simply because its SourceRecordset is set to a master recordset.

Although True DataControl honors the ADO/OLE DB hierarchy, we recommend using True DataControl native features for establishing a master-detail relationship, including the Master property and Field Range Conditions, which are more powerful and versatile than standard ADO master-detail.


Memory Array Mode

Setting the DataMode property to 1 – Memory Array indicates that a TData control functions in memory array mode.

In memory array mode, a TData control stores data internally without relying on a database or any other external data source. It uses a special object type, XArrayDB, for data storage. The XArrayDB object, designed as a drop-in replacement for Visual Basic arrays, is also recognized as a data source by other ComponentOne products, including True DBGrid and True DBList.

Using Memory Array Mode for Binding Controls to Variables

Defining Memory Array Fields and Filling Arrays with Data

Manipulating Memory Arrays in Code

Bookmarks and Row Numbers


Using Memory Array Mode for Binding Controls to Variables

As the word “array” suggests, you can use the memory array mode to expose two-dimensional data, i.e., multiple rows of columns (fields), to a bound control. Perhaps even more useful is the situation where there is only one row of data. In this case, the data effectively consists of several variables (fields) stored in memory. Each of the fields has only one value, exactly as a normal Visual Basic variable.

Using True DataControl in this capacity allows you to bind controls, such as TextBox, ComboBox, CheckBox and others to memory variables, as though the controls are bound to simple Visual Basic variables. You are probably accustomed to perceiving data binding as a means of working with a database. It's much more than that! True DataControl brings the codeless convenience of data binding to the sections of your application that don’t deal with a database, so you don’t have to write code performing all chores of data exchange between variables and controls. Even more, modifying a variable (field) triggers immediate update of all dependent fields and expressions, according to the general True DataControl rules. So you can specify rules relating your bound controls to each other and to your variables without routine coding.

The practice of using True DataControl for binding to variables is a useful technique rather than a special True DataControl feature. You don’t need to do anything special to apply it. All you have to do is to create a TData control with DataMode = 1 - Memory Array, and define one field for each variable. You can instantly use such TData controls as a data source for your bound controls. In this case, you would typically use a TData control with its Visible property set to False, since there is no need for the user to navigate a single record.

This technique can be used in countless situations, wherever you have variables that must be displayed and modified in controls. You can see some examples in True DataControl tutorials, where a memory array True DataControl with a single record is used to eliminate manual coding in the following common scenarios:

•

Master-detail relationships, as demonstrated in Tutorial 5.

•

Parameterized SQL queries, as demonstrated in Tutorial 7.

•

Ad-hoc query forms with range conditions, as demonstrated in Tutorial 8.


Defining Memory Array Fields and Filling Arrays with Data

Array fields (columns) can be specified at design time in the Fields property page. Alternatively, the collections returned by the Fields property can be filled at run time in the WillOpenData event. Each data field definition corresponds to a column in an XArrayDB object, and the order of the fields determines the one-based column indexes. Only data fields are stored in memory arrays, not calculated fields.

At run time, when the application starts, the TData control creates an XArrayDB object containing a single row, with one column for each data field defined at design time.

If you want to pre-fill the array with data, you can create an XArrayDB object in code and assign it to the Array property of the TData control. This must be done in the control’s OpenData event. You must make sure that the number of columns in the XArrayDB object is the same as the number of True DataControl fields (not including calculating fields).

It is not necessary to create a new XArrayDB object in code. You can rely on True DataControl to create a default XArrayDB object, and then use the OpenData event to change the number of rows in the array and fill the array with data. This can be done in OpenData by operating on the XArrayDB object returned by the control’s Array property.

It is also possible to set the Array property to an XArrayDB object in code outside of True DataControl events. This will cause a refresh of the TData control (use the ChangeInProgress property to postpone the refresh). Still, the assigned XArrayDB object’s column count must coincide with the number of data fields.

If you change the underlying XArrayDB data in code, you must refresh the TData control to make its recordset reflect the changes. To refresh a TData control, call

TData1.Refresh True

(Refresh method with NoEvents argument set to True).


Manipulating Memory Arrays in Code

The Array property returns the XArrayDB object housing a TData control’s data. As several of the True DataControl tutorials demonstrate, you can use memory array mode without ever referring to the Array property in code. However, if you want to access the memory array directly, or set the Array property to your own XArrayDB object, you must first include a reference to the XArrayDB object in your project. To do this, select References... from the Visual Basic Project menu, check the box labeled ComonentOne XArrayDB Object, and click the OK button.

NOTE: It is not necessary to access the Array property in order to get or set field values. As in all other data modes, you can use the collection returned by the control's Fields property for that. You need to access the Array property only if you have to modify the whole contents of the underlying XArrayDB.

To declare an XArrayDB instance in code, write:

Dim x As New XArrayDB

To allocate space for array elements, use the ReDim method, which is similar to the ReDim statement in Visual Basic:

x.ReDim 1, 100, 1, 5 ' one-based array with 100 rows, 5 columns

The number of columns in your XArrayDB object must be equal to the number of data fields in the collection returned by the control’s Fields property.

Note that the ReDim method automatically preserves the contents of the XArrayDB. Uninitialized elements contain empty variants.

To access the elements of an XArrayDB object, use the same syntax as you would for a Visual Basic array:

x(4,1) = "True DataControl" ' row 4, column 1; string data

x(4,2) = 199.95 ' row 4, column 2; floating point data

If IsEmpty(x(1,1)) Then

MsgBox "First element is uninitialized"

End If

Note that XArrayDB elements are not restricted to one data type; any variant data type supported by Visual Basic can be used. However, when a bound control attempts to update a column, True DataControl will enforce any restrictions imposed by the data type of the corresponding field definition. For example, alphabetic data cannot be written to a numeric field.


Bookmarks and Row Numbers

Having an array, one would naturally want to access its rows in the simplest way, by row number (index in array). On the other hand, the rows of an ADO recordset, including the True DataControl Recordset, should be accessed using bookmarks. One would expect the two methods of identifying rows to be closely related.

Indeed, True DataControl bookmarks in memory array mode are long numbers, just like array indexes. They are closely related but not identical, because bookmarks must identify a row uniquely, whereas the row index can change if some preceding rows are deleted from the array.

Correspondence between row numbers and bookmarks can be easily established using two special True DataControl methods:

ArrayIndexToBookmark

Returns the bookmark for a given row index.

BookmarkToArrayIndex

Returns the row index for a given bookmark.


User Events Mode

Setting the DataMode property to 2 - User Events causes a TData control to function in user event mode.

User events mode is provided for advanced users who need to create their own custom data source. In this mode, the programmer has full control over the data and specifies the behavior of the custom data source by writing Visual Basic code to handle special True DataControl events: UserReadData, UserWriteData, UserAddData, UserDeleteRow, and UserFindData. These events work as follows:

•

When the form is loaded, bound controls request data from True DataControl for display. As the user navigates the data source with the bound controls, they continue to request additional data from True DataControl. In turn, True DataControl requests data from the application by firing the UserReadData event. A special object, RowBuffer, is used in the UserReadData event to receive the data values and bookmarks for the rows returned by the event handler.

•

The user may also modify, add, or delete data using bound controls. The bound controls notify True DataControl of all such data changes. In turn, True DataControl fires the UserWriteData, UserAddData, or UserDeleteRow events, which notify the application that the data source should be updated accordingly. The RowBuffer object and bookmarks are used in these events to communicate information about individual rows.

If you are familiar with ComonentOne True DBGrid unbound mode, you will find the True DataControl user events mode easy to understand. It uses the same events, although True DataControl calls them ‘User’ instead of the grid’s "Unbound." There are some slight differences in writing code for True DataControl's user events mode and True DB Grid's unbound mode, see True DataControl user event mode and True DBGrid unbound mode.

Note

User events mode is unavailable in True DataControl Lite.

Defining Fields for User Events Mode

Implementing Handlers for User Events Mode

Bookmarks in User Events Mode

The RowBuffer Object

True DataControl User Event Mode and True DBGrid Unbound Mode


Defining Fields for User Events Mode

As with memory array mode, there is no data source to supply field information, so when in user events mode you must define the fields that make up the structure of the custom data source. You can specify the Fields collection either at design time on the Fields property page, or at run time in the WillOpenData event.

Each data field corresponds to a column in a RowBuffer object passed to the UserReadData, UserWriteData, and UserAddData events. The order of the fields determines the zero-based column index that corresponds to a particular data field.

Only data fields are present in the RowBuffer object, not calculated fields.

When defining fields in user events mode, the most important properties are Name, which specifies the field name exposed to bound controls, and Type, which determines the variant subtype that will be used when data is copied to a RowBuffer object. For more information, see Field properties.


Implementing Handlers for User Events Mode

The most essential part of defining your custom data source is, of course, programming handlers for the True DataControl events: UserReadData, UserWriteData, UserAddData, UserDeleteRow, and UserFindData. Depending upon your application requirements, you may not have to provide handlers for all five events. For example, if your data source is read-only, implementing UserReadData alone is sufficient. The UserFindData event is optional in all cases, it is only used to improve search performance in large data sources.

See the Reference section for details on each of the following events used in the user events mode:

UserReadData

Fired when the control is requested to retrieve a bookmark or columns data.

UserWriteData

Fired when a row data has been modified and the user commits the changes by leaving the row or calling Recordset.Update.

UserAddData

Fired when a new row has been added and the user commits the changes by leaving the newly added row or calling Recordset.Update.

UserDeleteRow

Fired when a row has been deleted and the user commits the changes.

UserFindData

Gives you an opportunity to optimize performance of simple search in your data source.


Bookmarks in User Events Mode

Bookmarks are variants used by a TData control to uniquely identify a record (i.e., row) of data to be displayed or modified. Bookmarks also enable the data provider to quickly position to a specific record.

The bookmarks you provide are passed to bound controls directly, without interpretation. The bound controls then use individual bookmarks to position to specific records. When a row is modified, deleted, or used as a starting point for navigation, its bookmark is passed as a parameter to the appropriate True DataControl event handler.

You must supply bookmarks as variant data in response to the UserReadData and UserAddData events. In some cases, you may need to change the bookmark passed to the UserWriteData event, as when the value of a unique key field is used as a bookmark and the user edits its value.

You are free to use whatever you choose to identify a row, but each row must have its own unique bookmark. In general, you need to be able to search for the associated row or record quickly when given a bookmark. For example, if your data is stored in a Visual Basic array, the array's row index is an obvious choice for a bookmark.

The four common examples of what to use for bookmarks are:

•

If you have a proprietary database, you can use the values of a unique key field as bookmarks. That way, when given a bookmark, you can search and retrieve the associated record quickly.

•

If the database you use supports unique row IDs or record numbers, these can be conveniently used as bookmarks.

•

If you store your data in an ADO recordset; it is natural to use the bookmarks that you get retrieving rows from the ADO recordset.

•

If your data is stored in an array, the array's row index is an obvious choice for bookmarks.

An important point to remember is that all bookmarks must have the same variant type. True DataControl supports String, Long integer, and floating point bookmarks. All other data types must be converted to strings before they are used as variant bookmarks.


The RowBuffer Object

The RowBuffer is a programmable object used to exchange data between True DataControl and your data source via the user mode events. The RowBuffer object is passed into the event handlers as an argument. In fact, the RowBuffer object can only exist within the scope of the user mode events; you cannot create a new one in code.

A RowBuffer object transfers information between the control and the handlers for the following events:

UserReadData

Fired when the control is requested to retrieve a bookmark or columns data.

UserWriteData

Fired when a row data has been modified and the user commits the changes by leaving the row or calling Recordset.Update.

UserAddData

Fired when a new row has been added and the user commits the changes by leaving the newly added row or calling Recordset.Update.

Here is a thumbnail sketch of the properties of the RowBuffer object:

RowCount Property

ColumnCount Property

ColumnName Property

ColumnIndex Property

Bookmark Property

Value Property


RowCount Property

RowCount is a long integer that specifies the maximum number of rows that can be processed in an event (read, write, or add). In the UserReadData event, If the value of this property exceeds the number of rows that can be processed, such as when an end-of-file condition is detected, your event handling code should change this property to reflect the actual number of rows processed.

RowBuffer.RowCount = Long

In UserWriteData and UserAddData, RowCount is always 1, and should not be changed by the event code.


ColumnCount Property

ColumnCount is an integer that specifies the number of columns (fields) that the user event should process. This property is read-only, and no attempt should be made to change it. The user event should process all columns requested. ColumnCount can be less than the True DataControl field count, indicating that not all data fields are requested. Zero ColumnCount is also possible, meaning that only the row bookmark is requested.

Integer = RowBuffer.ColumnCount


ColumnName Property

ColumnName is a string array that specifies the name of the True DataControl field corresponding to a row buffer index. This property is read-only.

String = RowBuffer.ColumnName(ColIndex)

' where ColIndex = 0 to ColumnCount - 1


ColumnIndex Property

ColumnIndex is a variant array used to specify a True DataControl field index (ordinal position in the collection returned by the Fields property) associated with a RowBuffer column. This property is read-only. You can use it in the UserReadData event to identify which data fields are being requested.

FieldNo = RowBuffer.ColumnIndex(RowIndex, ColIndex)

' where RowIndex = 0 to RowCount – 1

' and ColIndex = 0 to ColumnCount - 1


Bookmark Property

Bookmark is a variant array used to specify unique row bookmarks when the RowBuffer is used to fetch data during a UserReadData event.

RowBuffer.Bookmark(RowIndex) = Variant

' where RowIndex = 0 to RowCount - 1


Value Property

Value is a variant array used to specify the data value associated with a RowBuffer row and column.

RowBuffer.Value(RowIndex, ColIndex) = Variant

' where RowIndex = 0 to RowCount - 1

' and ColIndex = 0 to ColumnCount - 1


True DataControl User Event Mode and True DBGrid Unbound Mode

If you are familiar with ComponentOne True DBGrid unbound mode, you will find that the True DataControl user event mode is designed along the same lines. It uses the same events (see the correspondence tables below) and essentially the same RowBuffer object.


Correspondence between True DataControl and True DBGrid Events

The following is the list of True DataControl user mode events and their True DBGrid analogs:

True DataControl

True DBGrid

UserReadData

UnboundReadDataEx

UserWriteData

UnboundWriteData

UserAddData

UnboundAddData

UserDeleteRow

UnboundDeleteRow

There is also an optional event corresponding to an event of the ComponentOne True DBDropDown control:

True DataControl

True DBDropDown

UserFindData

UnboundFindData


Difference in Handling ApproximatePosition

There is a slight difference in handling the ApproximatePosition argument of the UserReadData event. It has been optimized in True DataControl with respect to True DBGrid 8.0. If ApproximatePosition = -1 is passed to the event procedure, the programmer can skip setting the ApproximatePosition, which is optional anyway. Even if the programmer supplies a value, True DataControl will ignore it.

Also, the programmer can let True DataControl know that ApproximatePosition is unknown, setting it to -1 in the event procedure.

As in True DBGrid 8.0, the ApproximatePosition argument of the UserReadData event is used in conjunction with the ApproxCount property of the TData control.


Differences in the UserFindData event

The UserFindData event differs from the UnboundFindData event of True DBDropDown 8.0 in the following:

•

There is no IncludeCurrent argument. It is not needed; the search always starts with the current record.

•

The NewLocation argument is passed to the event procedure as an empty variant (in TDBDropDown it is initially Null). If the record is not found, the NewLocation argument should be set to Null. Leaving it empty means that the UserFindData event is not implemented or the field for which it is called does not allow optimal search. In that case True DataControl will perform an exhaustive search to find the search record.

•

The SeekFlags arguments can contain a combination of SeekFlagsEnum constants.


Query Mode

The True DataControl Query Mode feature enables you to create powerful ad-hoc query forms in a matter of minutes. You can add Query By Example capabilities to your application with minimal effort, without manual coding.

The Query Mode feature resembles what is called Filter By Form in Microsoft Access, but is much more powerful and versatile. True DataControl query mode gives you complete design-time and programmatic control. You also have the choice of either using the same bound controls for query and result modes (simply toggle the QueryMode property to switch the modes), or using a separate True DataControl (or any other ADO data source, for that matter) to display query results. If you choose to display a query and its result in the same TData control, you can use the Query toggle button on the TData control to switch modes. The Query toggle button is enabled by the ButtonQuery property.

When a TData control is in query mode (the QueryMode property is set to True), the data in its recordset represents a query. The end-user enters query (search) values for fields in any of the bound controls. You can use the same controls, for example a grid, to represent a query and its results, thus implementing “Query By Example.” You can also create a form specifically customized for query mode. For example, create a form that provides combo boxes for selection, or allows end-users to enter an interval (“from” and “to” values) in a pair of bound controls. In the latter case you will probably choose to set QueryMode to True at design time so the TData control remains in query mode at all times, and use a separate TData control to display query results.

Setting QueryMode to False applies the query and switches the TData control from query to result mode. The same TData control’s recordset now contains the query result. Setting QueryMode back to True returns it to query mode, preserving the previously entered query.

The alternative to switching modes is to set QueryMode to True at design time, so the TData control will permanently remain in query mode. You can then use its QueryFilter property, assign its value to the Filter property of an ADO recordset. Presumably, you will use TrueData.Recordset.Filter property of another TData control, but you can use any other ADO recordsets as well. The QueryFilter property always contains the filter condition generated from the data entered by the end-user.


Query Mode in True DataControl Lite

Query Mode is fully available in the Lite version as well. It can be used not just with ComponentOne bound controls, such as True DBGrid, but with any Microsoft and third-party bound controls as well. To enable Query Mode in True DataControl Lite, you must use bind your data-aware controls directly to TDataLite. See Binding data-aware controls to a TDataLite control for more information.


Fields, Parameters and Expressions

This chapter explains the different types of variables (fields and parameters) in True DataControl and how they are used to form expressions.

A TData control operates on fields and parameters. Both are considered variables because you can refer to them in expressions as well as in code. At design time, you define variables using the Fields and Parameters property pages. You can also define variables at run time by manipulating the collections returned by the Fields and Parameters properties. These collections allow you to examine and modify variable values in code, if desired.

Almost every key feature of the product involves building an expression, so it is important that you understand the fundamental concepts of True DataControl expressions.


True DataControl Fields

Field variables constitute an individual record in the True DataControl Recordset. Therefore, their values depend upon the current record position within the recordset. Fields defined in the Fields collection at design time or run time from a Fields collection exposed by the True DataControl Recordset property. True DataControl fields define the data structure provided by the TData control; they are exposed to all data-aware controls bound to it. Therefore, it is mandatory for every functional TData control to contain some fields.

Each True DataControl field is represented by a Field object, which is an item in the Fields collection. The Fields collection is specified at design time in the Fields property page, and accessed via the Fields property in code at run time. You are also allowed to modify the Fields collection in code, either outside True DataControl events, or in the WillOpenData event. Every modification made to the Fields collection or its individual Field items in code outside of True DataControl events will cause the TData control to refresh its recordset. Use the ChangeInProgress property if you want to make multiple changes to fields and refresh only once, when all changes are done.

By default, True DataControl exposes all fields so that bound controls can display and modify their values. However, you can hide individual fields from bound controls by setting their Visible property to False. This prevents these fields from appearing in the Recordset, although you can still use them internally for other purposes. For example, a hidden date field representing the modification time for a record can be updated automatically by True DataControl.

Three Kinds of Fields

Accessing Field Values in Code

Field Properties

Field Range Conditions

Field Constraints


Three Kinds of Fields

There are three kinds of fields in True DataControl:

Data fields

Data fields are actually stored in a database (data source mode) or in internal storage (memory array mode). In data source mode, if no fields have been defined, True DataControl retrieves fields from the data source, automatically creating a data field for each field in the data source. In memory array mode, you create your own data fields, thus defining the structure of the underlying array. In user events mode, you are also required to define data fields manually.

Calculated fields

Calculated fields are not stored in the database, they are evaluated as needed by True DataControl. The value of a calculated field is determined by evaluating an expression, or in CalcFields event. Typically, the expression depends on the value(s) of other field(s). In True DataControl Lite, calculated fields are only accessible to ComponentOne controls, such as True DBGrid 7.0, directly bound to TDataLite.

Linked fields

Linked fields are used only to establish a one-to-one link between a dependent TData control and its master, in which case the linked field (defined in the master) represents a data field in a dependent TData control. Linked fields are unavailable in True DataControl Lite.

At design time, the FieldKind property value is determined according to which of the three option buttons is selected: Data, Calculated or Linked.

If you create a field in code at run time, you must set its FieldKind property to indicate one of the three groups to which the field belongs.


Accessing Field Values in Code

A Field object can be accessed by indexing the collection returned by the Fields property with either the field name or the zero-based ordinal position in the collection. As with any Visual Basic collection, if you plan to use a Field object many times, it is recommended (for better performance), that you declare a Visual Basic variable of type Field. So you can establish a permanent reference to a field in code, as in the following example:

Dim F As Field

Set F = TData1("CustomerID") ‘using name

Set F = TData1(0) ‘using ordinal index

To get or set a field’s value in code, use the Value property of the Field object:

' Retrieve the value of the CustomerID field

CustomerID = TData1.Fields("CustomerID").Value

' Set the value of the CustomerID field

TData1.Fields("CustomerID").Value = CustomerID

Since Value is the default property of the Field object, it can be omitted. In fact, since Fields is the default property of the TData control, the preceding example can be shortened to:

CustomerID = TData1("CustomerID")

TData1("CustomerID") = CustomerID


Field Properties

The Field object has the following properties that can be set at design time in the Fields property page, or in code at run time:

Name

Specifies a unique name that identifies the field in True DataControl expressions and in the True DataControl recordset. It also serves as an index to the Fields collection, which is returned by the Fields property. The default name for a newly added field is FIELD_number, where number is the lowest integer that would yield a unique name. In order to be used directly in TData expressions, a field’s name must be a proper identifier, that is, it must begin with a letter and contain only letters, digits, and underscores. If you have a field with spaces or other non-identifier characters, you can use the Field() function in expressions, for example, Field(“A very important field”).

DataSourceField

Specifies the name of the SourceRecordset field from which this True DataControl field is derived. This property is only used by data fields (not calculated or linked fields) in data source mode.

DisplayName

Specifies a user-friendly name under which the field appears in the Find Dialog. If not explicitly set, defaults to Name.

LinkedControl,LinkedField

For a linked field (FieldKind = 2 - Linked, LinkedField is the name of a field in the LinkedControl (a dependent TData control), to which the linked field is linked. For more information, see One-to-One Links. At design time, if the Linked option button is selected, the caption of the DataSource Field combo box changes to Linked Field. In this case, you must select one of the available field names (from a dependent TData control).

Visible

Determines whether the field is exposed to data-aware controls. The default value is True. If set to False, the field can still be used by the TData control and all its dependent TData controls, but it is hidden from bound controls. the TData control and all its dependent TData controls can still use the field

ReadOnly

Determines whether the field can be modified by the end-user. The default value is False, which means that the field is modifiable. If True, the end-user cannot modify the field, but its value can still be changed in code or by evaluation of a True DataControl expression.

Required

Determines whether the field must be assigned an actual value when records are updated or added. The default value is False, which means that a value need not be specified. If set to True, an attempt to empty the field, or to update or add a record with this field empty will result in an error message.

Searchable

Determines whether the field is included in the Find Dialog. Default: True, the field is included.

Type

Determines the variant data type of the field. Allowable values are Boolean, Byte, Currency, Date, Double, Integer, Long, Single, String, Variant. For data fields in data source mode, and for linked fields in any mode, the value is derived from the underlying data source and the property cannot be changed. For calculated fields in data source mode, and for data fields in memory array or user events mode, the default value is String, but you can change the value to the appropriate type.

MaxLength

For string fields only, this setting specifies the maximum number of characters the field value can contain.

ModificationMode

Determines how True DataControl reacts to changes in the field’s value caused by end-user interaction. When set to 0 - None, True DataControl does nothing, deferring to the container (Visual Basic) to decide when the field should be updated. The 1 - Immediate setting triggers an instant field update for every change that occurs in a bound control, even for individual keystrokes. The default setting, 2 - Leaving control, triggers field updates when the bound control loses focus, or when the current cell position in a bound grid changes.

You can also specify the following optional expressions:

CalculatedExpression

Specifies the expression used to calculate the field's value. This is normally used for calculated fields, but data fields can also have calculated expressions, in which case the field's value changes whenever one of the fields referenced in the expression changes. If the rules for calculating fields are too complex to be represented by an expression, you can use the CalcFields event to determine the values of calculated fields.

CalcConditionExpression

(In the Fields property page, this property is represented by the Condition edit box beside Calculated Expression). Specifies a boolean expression that determines whether the associated calculated expression should be evaluated at all. If the condition expression is empty or evaluates to True, the calculated expression will be evaluated; if the condition expression evaluates to False, the calculated expression will not be evaluated.

One possible use of the condition expression is to initialize an empty data field with the value of another field that has just been modified. For example, to initialize the value of the BillTo field with the value of the ShipTo field when the latter has just been entered, you would set the former's calculated expression to ShipTo, and its associated condition expression to IsEmpty(BillTo).

DefaultExpression

Specifies the default value to be assigned to this field in a newly added record.

The following two properties define a field’s behavior in Query Mode.

QueryMode

Specifies whether the field should appear only in query mode, only in result mode, or in both modes.

QueryOperation

Specifies the comparison operation (=, <=, >=, <, >, starts with, contains) used with the field generating the query filter condition.


Field Range Conditions

Using range conditions is an effective way to restrict a True DataControl recordset so that it only includes records where the field value is equal to a certain value or satisfies a certain condition. It is especially useful in defining Master-Detail Relationships between TData controls. However, range condtions can be used in many other situations, wherever it is necessary to restrict the recordset by known field values. For example, they are useful in creating forms allowing the end-user to restrict field values – a common task illustrated in Tutorial 8.

Field range conditions are unavailable in True DataControl Lite.

A True DataControl field can have several range conditions, or none. Each range condition has a comparison operation, a value expression, and an applicability condition expression. For example, a field LastName can have the following range condition (in pseudo-code notation, as it appears in the Fields property page):

if (LastNameIsRestricted) LastName = LastNameValue

Here LastNameValue (it can be a parameter name) is the value expression. It evaluates to the value to which the LastName field is restricted. LastNameIsRestricted (it can also be a True DataControl parameter) is the boolean condition (applicability expression). The range condition is applied only if it evaluates to True. Comparison operation here is = (“equals”).

Applicability condition expression is optional. If it is empty, the range condition always applies, as in the following example:

LastName = “Bach”

Wherever possible, try to use range conditions for restricting True DataControl recordsets. Although the same result can be achieved with Filters, filters are usually much slower. Using filters, True DataControl fetches all records and tests every fetched record for the filter conditions, which involves much more fetches than using range conditions, which are optimized for better performance. In most cases, using range conditions has the same performance cost as WHERE conditions in SQL query.

Range conditions of a True DataControl field form the RangeConditions collection, a property of the Field object. Each range condition is represented by a RangeCondition object, an item of the RangeConditions collection, indexed by its zero-based ordinal position in the collection.

At design time, range conditions can be created in the Fields property page (pressing the New button or selecting New Range Condition from the context menu). At run time, you can create them using the Add method of the RangeConditions collection. Bear in mind, that, unless you do it in the WillOpenData event, that will cause refresh of the TData control.

Following is the list of range condition properties:

ComparisonOperation

Specifies the type of comparison. Allowable values are <, <=, <>, =, >=, >, and also starts with and contains (string fields only). The default value is = (equals).

SkipIfEmpty

Specifies how to handle the range condition when a variable contained within the ValueExpression is empty. If True (the default), the range condition is skipped; that is, it will not restrict the resulting recordset. The default setting (True) is useful for ad-hoc query forms where the user is not required to specify values for all fields.

ValueExpression

Specifies the operand to be used for comparison. The resulting range condition is field op value, where field is the data field that owns this range condition, op is the selected comparison operation, and value is the result of this expression.

ConditionExpression

Specifies an optional boolean expression controlling the applicability of this range condition. If this expression is not empty and evaluates to False, the entire range condition will be ignored.


Field Constraints

A True DataControl field can have several constraints or none. Specifying constraints on the field level represents an important feature of True DataControl; it allows you to put application logic where it belongs – in your data source. Without it, Visual Basic programmers have to enforce field validation rules in event handlers in bound controls. Every VB programmer knows that this is inconvenient and error-prone.

Basically, a constraint is a Boolean expression. Field constraints are evaluated every time the field value is changed, for whatever reason. If a constraint is not satisfied, that causes a constraint violation error and cancels the field modification.

Each constraint has a constraint expression that is the constraint itself, an applicability condition expression that specifies whether the constraint should be imposed, and a message expression that gives the error message if the constraint is not satisfied. For example, a field CustomerID can have the following constraint (in pseudo-code notation, as it appears in the Fields property page):

if (CheckCustID) Len(CustomerID)<=5

This line means that CustomerID cannot exceed five characters.

Here CheckCustID (it can be a parameter name) is the applicability condition expression. The constraint is enforced only if it evaluates to True. The applicability condition is optional. If it is empty, the constraint is always enforced.

Field constraints form the Constraints collection, a property of the Field object that is accessed via the Constraints property. Each constraint in this collection is represented by a Constraint object, which is indexed by its zero-based ordinal position in the collection.

At design time, field constraints can be created in the Fields property page (pressing the New button or selecting New Constraint from the context menu). At run time, you can create them using the Add method of the Constraints collection. Bear in mind, that, unless you do it in the WillOpenData event, that will cause refresh of the TData control.

Following is the list of constraint properties:

ConstraintExpression

Specifies a boolean expression that determines the validity of a modified field. If the constraint expression evaluates to False, the modification will be canceled and the user will be notified of the constraint violation according to the MessageExpression property.

ConditionExpression

Specifies an optional boolean expression controlling the applicability of the constraint. If this expression is not empty and evaluates to False, the entire constraint will be ignored.

MessageExpression

Specifies a string expression that determines the error message to be displayed when a constraint violation occurs. If you leave this property blank, True DataControl displays a generic "Constraint violation" message.


True DataControl Parameters

True DataControl parameters are simply variables that, unlike fields, don’t depend on a particular record. Parameter variables hold values that belong to the TData control as a whole rather than to individual records of its recordset. The rationale behind True DataControl parameters is that Visual Basic variables and controls cannot directly participate in True DataControl expressions. True DataControl parameters are also used to support a parameterized SQL statement as the data source for a TData control.

Another distinction between fields and parameters is that parameters are not exposed to data-aware controls; they can only be used by the TData control and its dependent TData controls.

Parameters can be used to accommodate parameterized SQL queries (dynamic SQL) in True DataControl, but they can serve other purposes as well. True DataControl parameters give you the means to refer to outside data, such as Visual Basic variables, in True DataControl expressions. It is not necessary for a TData control to have parameters; they should be used only if needed.

Each True DataControl parameter is represented by a Parameter object, which is an item in the Parameters collection. The Parameters collection is specified at design time in the Parameters property page, or at run time by modifying the collection returned by the Parameters property in code. You are also allowed to modify the Parameters collection in code, either outside of True DataControl events, or in the WillOpenData event. Every modification made to the Parameters collection or its individual Parameter items in code outside True DataControl events will cause the TData control to refresh its recordset. Use the ChangeInProgress property if you want to make multiple changes, and refresh only once, when all changes are done.


Parameters in Expressions

You can use parameters in any True DataControl expression to implement dependencies on values that change dynamically at run time. When you use a parameter for this purpose, leave its SQLParameter property empty, use the parameter name in the expression where you need it, and set the parameter in code when you need its value changed. See Accessing parameter values in code for details. Alternatively, you can specify the parameter’s ValueExpression, then it will be evaluated automatically.

If you set the parameter value in code, True DataControl will re-evaluate expressions that depend on that parameter. True DataControl will refresh its recordset if necessary, that is, if this type of expression forces refresh on its asynchronous evaluation. For more information, see Expression Evaluation Rules.

A special case of setting a parameter value is in the WillOpenData event, where it will not cause expression re-evaluations and refresh. When you set a parameter value in WillOpenData, it just becomes the value of that parameter, provided ValueExpression is not specified. This way you can define a default value for a parameter, to be assigned when the TData control is loaded.

An alternative way to give your parameter a default value is to specify its ValueExpression. However, you must bear in mind that if ValueExpression is non-empty, it will be used to evaluate the parameter value on every refresh.

Example:

Suppose you want to impose a range condition on the LastName fields, so your recordset contains only those records that are equal to a specified value. And you need to set this value in code.

This can be done by creating a parameter (Param1), creating a range condition for the field, and specifying Param1 as the ValueExpression for that range condition.

When you set:

TData1.Parameters(“Param1”) = “Bach”

TData will refresh its recordset, fetching only those records where LastName = ”Bach” because the ValueExpression forces refresh on asynchronous evaluation. For more information, see Expression Evaluation Rules.

If you want to set the parameter to “Beethoven” at startup, you can do so in the WillOpenData event:

Private Sub TData1_WillOpenData()

TData1.Parameters(“Param1”) = “Beethoven”

End Sub


Parameterized SQL

In data source mode, TData allows use of SQL statements with parameters for its RecordSource. SQL parameters are accommodated in True DataControl at both design time and run time by using True DataControl parameters.

The ability to allow parameters in SQL queries at design time is an important addition to functionality that is provided by True DataControl. The standard ADO data control (Microsoft ADODC) does not support parameterized SQL statements in its RecordSource; you have to create an ADO recordset at run time and assign it to the ADODC control.

The parameterized SQL functionality is unavailable in True DataControl Lite.

To use a parameterized SQL statement, do the following

1.

Define a parameter for each SQL parameter. This can be done at design time in the Parameters property page. Parameter names (the Name property) are not important, and you can assign them as you choose.

2.

Set the Type property for each parameter to the variant data type of the SQL parameter.

3.

Specify the SQLParameter property for each such parameter. If your SQL parameters are named, it is reasonable to set SQLParameter to the corresponding SQL parameter name. However, since not all databases support named parameters in SQL, the actual value of SQLParameter is not important. What is important is the fact that it is not empty. Correspondence between True DataControl parameters and SQL parameters is established based on their number, and their ordinal position in the collection returned by the Parameters property, and in the SQL statement. True DataControl parameters with an empty SQLParameter do not participate in this correspondence.

4.

Specify the ValueExpression if you want the parameters to be evaluated automatically. Otherwise, write code setting the parameters’ values. For more information, see Accessing parameter values in code.

At design time, you will get correct field information (press the Retrieve Fields button in the Fields property page) from such parameterized SQL statement if you have defined a parameter for each SQL parameter, as described above.

At run time, SQL parameters will be set to the values of corresponding True DataControl parameters, when the SQL statement is executed.

For an example of using parameters with SQL statements, see Tutorial 7.


Accessing Parameter Values in Code

You can access a Parameter object can by indexing the collection returned by the Parameters property with either the parameter name or the zero-based ordinal position in the collection.

To get or set a parameter’s value in code, use the Value property of the Parameter object:

' Retrieve the value of the parameter Par1

variable = TData1.Parameters("Par1").Value

' Set the value of the parameter Par1

TData1.Parameters("Par1").Value = variable

Since Value is the default property of the Parameter object, it can be omitted:

variable = TData1.Parameters("Par1")

TData1.Parameters("Par1") = variable


True DataControl Expressions

True DataControl expressions are nonprocedural rules that describe application logic. You construct expressions composed of fields, parameters, operators, and functions; at run time, True DataControl evaluates these expressions on an as-needed basis to perform a variety of tasks.

Every expression is a property of an object in one of the True DataControl collections: Fields, Parameters, RangeConditions, Constraints, PropertyExpressions, FilterExpressions. They can be set at design time, in True DataControl property pages, or, just like any other object properties, they can be set at run time in code with the corresponding property.

At design time, all expressions are specified using the True DataControl property pages. You can either type an expression in its entirety, or use the True DataControl Expression Editor to build it as depicted in the illustration:

Different collection objects, and, correspondingly, different property pages, are used to specify different kinds of expressions, as shown in the following table:

Parameter

Parameters page: Value expressions for parameter variables

Field

Fields page: Calculated field expressions, default expressions for new field values, range conditions, field-level constraints, message expressions for constraint violations

PropertyExpression

Property expressions page: Value expressions for properties of controls on the same form

FilterExpression

Filters page: Filter expressions

Constraint

Constraint page: Record-level constraints, message expressions for constraint violations

For example, when you create a calculated field, you assign it an expression that specifies how its value depends on other field values. At run time, True DataControl evaluates the expression and updates the calculated field as needed, such as when the current record position changes or the user modifies one of the fields upon which the calculated expression depends. If a calculated field is defined in terms of another calculated field, True DataControl automatically resolves evaluation order dependencies.

Additionally, for almost every kind of expression, True DataControl fires an event that you can handle to override the normal expression evaluation. For example, you can use the Filter event to impose complex filter conditions that cannot be specified by True DataControl expressions.

Specifying Expressions using VBScript

Constant and Non-String Expressions

Expression Scope Levels

Expression Evaluation Modes

Expression Evaluation Rules


Specifying Expressions using VBScript

The True DataControl expression language is a subset of Visual Basic Scripting Edition, commonly referred to as VBScript. In particular, it is the subset of VBScript containing expressions only. VBScript statements such as If...Then...Else and While...Wend are not supported, but any VBScript function and operator may be used in your expressions.

Variables used in True DataControl expressions are True DataControl fields and parameters. Defining an expression for a TData control, you can refer to any variable that belongs to that control by its name, such as CustomerID. If a TData control participates in a master-detail relationship with other controls (ancestors), you can refer to the ancestor's variables by separating the control name and the variable name with a dot, as in TData1.OrderID.

If you are not familiar with VBScript, don't worry about learning a new language; it is still Visual Basic. The most significant difference is that VBScript has only one data type: Variant. Thus, it is a just a simplified version of Visual Basic.

Also, True DataControl supports some functions in its expression language that are not normally supported in VBScript. Such are the Iif and Format functions, supported in Visual Basic, but not in VBScript. For your convenience, True DataControl supports them in its expressions.

For information on True DataControl extensions to VBScript, see VBScript Reference.


Constant and Non-String Expressions

Normally, an expression is a string, which is evaluated according to True DataControl expression language rules (based on VBScript). But it can also be a constant value of any variant sub-type, not necessarily a string.

Expressions specified at design time are always strings, since there is no way to specify anything but a string in the property pages. You must always remember that expressions you enter in property pages will undergo evaluation. If you want a constant expression, you should enclose it in double or single quotes.

At run time, an expression property can be set to a variant value of any variant data type. If an expression is set to a non-string variant, True DataControl considers such expression constant, always evaluating to the same value, which was assigned to it. For example,

TData1.Fields(“CalcAmount”).CalculatedExpression = 1000

will always produce the same result: 1000.

An expression of string type is considered constant if the string is enclosed in quotes. For example, the following constraint message expression specified in property pages is constant:

“my message”

To specify this expression in code you should write:

TData1.Constraints(0).MessageExpression = “””my message”””

In each of the triple quotes here, one quote is necessary to form a Visual Basic string constant. The first character of that constant is a double quote, but since it is in a string constant, it should be written as two double quotes. Hence the triple double quotes.

To make it more readable, True DataControl allows single quotes, as well as double quotes, to form string constants. Then the double quote character can be used inside single quotes without duplication. And vice versa, the single quote character can be used inside double quotes without duplication. So our example can also be written as:

TData1.Constraints(0).MessageExpression = ‘”my message”’


Expression Scope Levels

At any given time, the state of a TData control is at record level or recordset level.

A TData control is at record level if it is either in the process of retrieving a record from the database, or has already positioned to a specific record. In this case all of its fields have definite values.

A TData control is at recordset level if it is in the process of populating the recordset, in which case the set of records is still undetermined and the control is not positioned on any particular record. Field values are undefined in this situation.

Accordingly, all True DataControl expressions can be divided into two groups: those belonging to the record level, and those belonging to the recordset level. The level of an expression is determined by the timing of its evaluation. For example, a calculated expression is evaluated in the scope of one record, so it belongs to the record level. Conversely, a range expression is evaluated before the recordset is populated, so it belongs to the recordset level. If you are unsure which level a particular expression belongs to, see Expression Evaluation Rules.

A recordset level expression cannot use the fields of the TData control for which it is defined, since the values of these fields will be undefined when the expression is evaluated. The True DataControl Expression Editor enforces this restriction by not displaying the control's fields when opened on a recordset level expression such as a range condition. However, recordset level expressions can use the control's parameters, as well as all variables (including fields) of ancestor TData controls (in master-detail relationship), if there are any.

Some True DataControl events also belong to either the record or recordset level depending upon the timing and conditions that trigger the event. You cannot retrieve field values by writing code in a recordset level event. Similarly, you cannot change a field value in a recordset level event.


Expression Evaluation Modes

To use True DataControl effectively, you should understand that expressions can be evaluated in one of two ways:

1.

Expressions represent simple procedures for obtaining values, and they are evaluated at appropriate times by True DataControl. For example, calculated expressions must be evaluated each time the control retrieves a record from the database. This is called synchronous evaluation, meaning that it is synchronized with some other process performed by True DataControl (in this example, retrieving data). In other words, expression evaluation takes place because True DataControl needs the result to continue with the process.

2.

Expressions also represent rules imposed in accordance with the application logic. When you formulate such rules, you delegate the task of maintaining them to True DataControl. For example, the calculated expression C = A + B states a simple rule that you expect C to be equal to A + B at all times, without having to write code to ensure this. With True DataControl, each time either A or B changes its value for any reason, True DataControl detects that the expression must change its value, too, and automatically re-evaluates it. This is called asynchronous evaluation (actually, re-evaluation). True DataControl does this automatically, without programmer’s intervention.

Synchronous evaluation is performed at well-defined times. If you are unsure when a particular expression is evaluated, see Expression Evaluation Rules.

Asynchronous evaluation is always triggered by a change in the value of a variable appearing in the expression. This can be caused by end-user interaction with a bound control, or it can be triggered by setting the value of a variable in code.

For some expressions, asynchronous re-evaluation has more drastic consequences than just changing a field’s value, as in a calculated expression. For example, range conditions affect the contents of the entire recordset, not just a single record. Since there is no reason to re-evaluate a range condition without re-populating the whole recordset, any change of a variable appearing in a range condition will force refresh, that is, re-populating the True DataControl recordset.

To defer asynchronous re-evaluation, (for example, to change several fields at once from code), set the ChangeInProgress property to True before updating the variables. When you are finished, set ChangeInProgress back to False to trigger the necessary re-evaluation. If you fail to reset this property to False, all asynchronous evaluations of all expressions will be permanently disabled.


Expression Evaluation Rules

As described in the section Expression scope levels, each type of True Date expression is evaluated in one of two contexts:

Record level

Occurs when a TData control is in the process of retrieving a record from the database, or has already positioned to a specific record. At evaluation time, all fields have definite values; therefore, all variables (parameters and fields) of the control and its ancestors (in master-detail relationship) can participate in the expression.

Recordset level

Occurs when a TData control is in the process of populating the recordset, in which case the set of records is still undetermined and the control is not positioned on any particular record. Since field values are undefined at evaluation time, the expression cannot use any fields defined for the control; it can only contain constants (numbers or strings), parameters, and any variables (including fields) of ancestor TData controls (if in master-detail relationship).

As described in the section Expression evaluation modes, the evaluation of a True DataControl expression is said to be synchronous or asynchronous, depending on how it was triggered:

Synchronous

Synchronous evaluation is triggered by some other process performed by True DataControl, such as data retrieval. The expression must be evaluated because True DataControl needs the result to continue with the process.

Asynchronous

Asynchronous evaluation is always triggered by a change in the value of a variable appearing in the expression. This can be caused by end-user interaction with a bound control, or by setting the value of a variable in code.

For each type of True DataControl expression, the following tables show the corresponding scope level, synchronous evaluation criteria, and consequences of asynchronous evaluation.

TABLE 1

Constraint.ConstraintExpression (for record-level constraints, in the collection returned by the Constraints property)

For record-level constraints, specifies a boolean expression that determines the validity of a modified record before it is updated to the underlying data source. If the constraint expression evaluates to True, the modified record is updated; if the constraint expression evaluates to False, no update will occur and the user will be notified of the constraint violation according to the MessageExpression property.

Level

Record level.

Synchronous

Evaluated before the modified record is posted to the database, or before the TData control is repositioned to a different record.

Asynchronous

No action.

TABLE 2

Constraint.ConstraintExpression (for field-level constraints, in the Field.Constraints collection)

For field-level constraints, specifies a boolean expression that determines the validity of a modified field. If the constraint expression evaluates to False, field modification will be canceled and the user will be notified of the constraint violation according to the MessageExpression property.

Level

Record level.

Synchronous

Evaluated before the field is modified.

Asynchronous

No action.

TABLE 3

Constraint.MessageExpression (both for field-level and record-level constraints)

Specifies a string expression that determines the error message to be displayed when a constraint violation occurs. If you leave this property blank, True DataControl displays a generic "Constraint violation" message.

Level

Record level.

Synchronous

Evaluated before the Error event is fired.

Asynchronous

No action.

TABLE 4

Field.CalculatedExpression

Specifies the expression used to calculate the field's value. It is normally used for calculated fields, but data fields can also have calculated expressions, in which case the field's value changes whenever one of the fields referenced in the expression changes.

Level

Record level.

Synchronous

Evaluated after a record has been fetched from the database.

Asynchronous

Updates the value of the associated field.

TABLE 5

Field.DefaultExpression

Specifies the default value to be assigned to the field in a newly added record.

Level

Recordset level.

Synchronous

Evaluated after a new record has been added to the recordset.

Asynchronous

No action.

TABLE 6

FilterExpression.FilterExpression

Specifies a boolean expression that will be evaluated once per record to filter the recordset. If all filter expression evaluate to True, the record will be included; if a filter expression evaluates to False, the record will be excluded.

Level

Record level.

Synchronous

Evaluated after a record has been fetched from the database and all calculated expressions have been evaluated.

Asynchronous

Action depends on the variable whose change triggers asynchronous evaluation. It forces refresh of the TData control unless the changed variable is a field (not a parameter) belonging to this control. Changes to parameters or ancestor fields force refresh.

TABLE 7

Parameter.ValueExpression

Defines the expression used to assign a value to the parameter.

Level

Recordset level.

Synchronous

Evaluated before the recordset is populated with records.

Asynchronous

Action depends on whether or not the parameter is used in an expression forcing refresh. If so, changing its value forces refresh.

TABLE 8

PropertyExpression.ValueExpression

Specifies an expression that provides a value for the associated property at run time. The property belongs to a control residing in the same form as the TData control.

Level

Record level.

Synchronous

Evaluated when the TData control has been positioned on a record.

Asynchronous

Updates the value of the associated control property.

TABLE 9

RangeCondition.ValueExpression

Specifies the operand to be used for comparison. The resulting range condition is field op value, where field is the data field that owns the range condition, op is the comparison operator, and value is the result of this expression.

Level

Recordset level.

Synchronous

Evaluated before the recordset is populated with records.

Asynchronous

Forces refresh of the TData control.


Features and Techniques

This chapter demonstrates how you can use True DataControl to solve common problems that arise when developing database applications. Tedious programming chores such as field validation, record-level constraints, and establishing one-to-many relationships can all be handled without writing any code!

Master-Detail Relationships

One-to-One Links

Filters

Control Property Expressions

Modifying Field Values, Retrieving and Saving Them in the Data Source

Using TData in Distributed Applications (disconnected recordset support)

Field Modification Modes

Validation and Constraints

Crosstab (matrix) Data Presentation

OLAP: Decision Support, Pivot Table

Using True DataControl in Different Containers


Master-Detail Relationships

Without writing any code, you can implement master-detail (one-to-many) relationships between a pair of TData controls. Master-detail relationships are unavailable in the Lite version.

At design time, set the Master property of the detail control (also referred to as the dependent control) to the name of the master control. You cannot change the Master property in code at run time.

Suppose, for example, that TData1 is bound to a customer database (master), and TData2 is bound to an orders database (detail). After setting the Master property of TData2 to TData1, you would typically specify a range condition that relates the CustomerID field of the detail control (TData2) with the corresponding field in its master control (TData1):

TData2.CustomerID = TData1.CustomerID

See Field Range Conditions for details.

At run time, when the master control (TData1) is repositioned to a different record, or the value of its CustomerID field changes, the dependent control (TData2) is automatically refreshed, and any data-aware controls bound to it are refreshed accordingly.

Note that using range conditions is just one way to establish master-detail relationship between two TData controls. You can also use filters, SQL parameters, or other expressions based upon field values in the master control, as all master fields are available to dependent control(s).

If a master control has a master itself, then the "higher" master is called an ancestor of the "lower" master’s dependents. The fields of all ancestors are available to a dependent control, not just the fields of the control specified in the Master property.

The refresh of a dependent control is governed by its AutoRefresh property setting. The default setting is 2 – When Idle. This means that refresh takes place after every change in master, but not immediately. The dependent control is refreshed when the TData control has finished all other tasks, and is idle. This optimizes the refresh process for fast navigation, such as when multiple master records are displayed in a bound grid. With this setting, the user will not notice any delay other than that needed to retrieve the master records. For example, if the user presses the down arrow key on a master grid in quick succession, the master TData control will not refresh the detail records until it stops receiving notifications caused by repetitive keyboard activity.

If AutoRefresh is 1 - Immediate, any change to the value of a master’s field or parameter, as well as any repositioning of the master’s current row, immediately triggers the refresh of the dependent control. Since this can be a time-consuming operation, the 1 - Immediate setting is recommended only for forms that display one master record at a time.

To suppress automatic refresh of a dependent control, set its AutoRefresh property to 0 - None. You can always refresh the dependent control programmatically by calling its Refresh method.


One-to-One Links

In many cases, two data sources have common "ID" fields, but different "detail" fields. For example, suppose that an inventory database contains ProductID and Quantity fields, and a product database contains ProductID, Name, and UnitPrice fields. Since each inventory record has exactly one counterpart in the product database, this is commonly known as a one-to-one relationship.

In a database context, such relationships are best implemented using SQL multi-table joins. However, since True DataControl can manage non-SQL data sources, including memory-resident data, it supports one-to-one links between two TData controls. Setting up a one-to-one link is similar to setting up a master-detail relationship.

IMPORTANT: For performance reasons, the use of one-to-one links between TData controls in data source mode is discouraged, as SQL JOINs accomplish the same result with far greater efficiency. However, one-to-one links are ideal for memory-based data sources, as demonstrated in Tutorial 13.

In a one-to-one link, a dependent TData control always has at most one record for each record of its master control. Under such circumstances, you can add linked fields to the master control, associating a linked field in master control with a field in the dependent control (linked control). Linked fields appear in the master’s records along with "normal" data and calculated fields; they can participate in expressions and can even be modified. A TData control can have multiple linked controls.

One-to-one links are unavailable in the Lite version.

Creating a one-to-one link involves the following steps:

1.

Create a special TData control and declare it to be a linked control by setting its LinkType property to 1 - Outer or 2 - Inner (the default setting is 0 - None), and its Master property to the name of the principal TData control.

2.

Set up a master-detail relationship using range conditions, dynamic SQL with parameters, or filter conditions. Make sure that the linked control has at most one record for each master record. (If that is not true, True DataControl will simply take the first record and ignore all the rest.)

3.

Add linked fields to the master TData control and associate each linked field with a field of the linked TData control. See LinkedControl,LinkedField properties in Field properties.

A linked control cannot be used as an independent TData control because it is managed in all respects by its master control. This means that data-aware controls cannot be bound to it. If you set the LinkType property of a TData control to a value other than 0 - None, the functionality of the control will be restricted accordingly. For example, all of its fields must be data fields, not calculated or linked fields. In essence, a linked TData control is an addition to its master control.

An outer link allows master records for which there is no corresponding record in the linked control. In this case, all linked fields are empty and cannot be modified. An inner link filters out such master records, excluding them from the recordset. These terms are consistent with the definitions of outer and inner joins in SQL.


Filters

True DataControl filters can be specified at design time on the Filters property page, or accessed via the FilterExpressions property at run time in the FilterExpressions collection.

Filter expressions restrict the set of records retrieved to the True DataControl recordset. For each fetched record, True DataControl evaluates each filter expression (provided that the accompanying condition expression evaluates to True) and excludes the record from the resulting recordset if the filter expression evaluates to False.

If multiple filter expressions are defined, they work as if they were connected by a logical AND operator.

IMPORTANT: Filter expressions are only evaluated if the Filtered property of the True DataControl is True. To enable filters, check the box labeled Filtered on the General property page or set the Filtered property in code.

If you can’t express your filtering rules as True DataControl expressions, you can use the Filter event. Filter event procedure returning False in its Result argument excludes the record from the resulting recordset. The Filter event also is enabled only if the Filtered property is set to True.

Using filters you must be aware that they can introduce significant performance overhead, since all records are fetched prior to checking the filter expressions. If you can use range conditions or SQL with parameters, these are far more optimized approaches than filters. Use filters only if you can’t restrict the recordset by other means. For more information, see Field Range Conditions and Parameterized SQL.

The FilterExpressions collection consists of FilterExpression items, each of which has the following properties:

FilterExpression

Specifies a boolean expression that will be evaluated once per record to filter the recordset. If all filter expressions evaluate to True, the record will be included; if a filter expression evaluates to False, the record will be excluded.

ConditionExpression

Specifies an optional boolean expression that will be evaluated once per record to determine whether the associated filter expression should be evaluated at all. If the condition expression is empty or evaluates to True, the filter expression will be evaluated; if the condition expression evaluates to False, the filter expression will not be evaluated.

Note: Neither expression will be evaluated if the Filtered property of the control is False


Control Property Expressions

Promoting the idea of codeless application development, True DataControl provides a feature similar to “dynamic properties” in Microsoft Internet Explorer 5.0 dynamic HTML. You can make any property of any control dependent on certain variables, so that the property will always be kept in synch with variable values, without any manual coding.

For example, you might specify (in pseudocode, actual notation see below)

Text1.Font.Bold = RequiredDate - ShippedDate < 10

True DataControl will maintain the font in the Text1 control so it will be bold if and only if the expression on the right is true. Whenever one of the two fields, RequiredDate or ShippedDate changes (due to repositioning to a different record, or data modification or any other reason), True DataControl will automatically update the font of Text1.

The expressions are held in the PropertyExpressions collection of True DataControl. This collection can be specified at design time in the Property Expressions property page, or by accessing the PropertyExpressions property in code at run time.

Each expression is associated with a property of a control belonging to the parent form of the TData control. This includes all controls (not only data-bound controls) and the form itself. At run time, True DataControl evaluates each expression and sets the corresponding control property to the resulting value whenever the value changes.

Control property expressions are evaluated when the TData control has been positioned on a record. If any variable within the expression changes, the entire expression is re-evaluated and the affected property receives the resulting value.

The PropertyExpression object, an item of the PropertyExpressions collection, has the following properties:

ControlName

The name of the control whose property is governed by the expression. It is the control’s Name property, with Index in parentheses, if this is an element of a control array. Examples: Text1, Form1, TextArray(2).

PropertyName

The name of the property governed by the expression, for example, BackColor. Nested properties such as Font.Bold are also supported.

ValueExpression

Specifies an expression that provides the value for the associated property at run time.

To facilitate assigning expressions to properties, the Property Expressions property page contains a tree view of all available controls and their properties. All controls belonging to the same form as the TData control, including the form itself, appear in the tree view. You can select a property in the tree view, type in an expression and press the New button. That will create a property expression.

Property expressions can also be set in code, as in the following example:

TData1.ChangeInProgress = True

With TData1.PropertyExpressions.Add(0)

.ControlName = "Text1"

.PropertyName = " Font.Bold"

.ValueExpression = " RequiredDate - ShippedDate < 10"

End With

TData1.ChangeInProgress = False

As with all True DataControl collections, any change to property expressions in code outside the WillOpenData event, causes refresh of the TData control. If you do it outside WillOpenData, use the ChangeInProgress property to make the change at once, without intermediate refreshes. Without ChangeInProgress, the above example would cause refresh four times.


Modifying Field Values, Retrieving and Saving Them in the Data Source

In many cases it is necessary to modify values retrieved from the data source and immediately before saving changed values. For example,

•

It is usually convenient to represent retrieved Null values of string fields as empty strings and save empty strings in the database as Nulls.

•

You might want to decode or format values retrieved from the database, and vice versa, encode or unformat them before saving changes to the database.

•

You might want to convert a string value entered by the user to uppercase.

True DataControl provides convenient and intuitive ways to specify such transformation. They are performed when data is retrieved from the data source and when it is written back, transparently to all other TData features. This means that once a row has been fetched from the data source, its fields undergo the specified transformation and from then on the transformed values are used by TData. In the opposite direction, immediately before the changed data is written to the data source, it undergoes the specified transformation.


Null Handling

Two properties, ConvertNullToEmpty and ConvertEmptyToNull specify the handling of Null values stored in the data source:

If ConvertNullToEmpty =True (default), a Null value of a string field retrieved from the data source is converted to empty string. This makes it easier to deal with such values in expressions and code, since VBScript and Visual Basic expressions have special behavior on Null values, which is usually undesirable, and empty strings are easier to handle. Non-string fields are not affected by this property. If you need to convert Nulls to some particular values for such fields, use the DataRead event.

If ConvertEmptyToNull =True (default), TData saves empty string values in the data source as Null values. Otherwise, empty strings are written literally, as empty strings. Most databases will convert them to Null anyway, so it rarely makes sense to change the default ConvertEmptyToNull=True to False. Non-string fields are not affected by this property. If you need to convert some particular values (for example, 0) to Null for such fields, use the DataWrite event.


Retrieving and Storing Values in the Data Source

Two events, DataRead and DataWrite allow the developer to specify field value transformations on retrieve and save.

Two special properties determine whether to trigger the corresponding event, CallDataRead for DataRead, and CallDataWrite for DataWrite. They are both False by default, meaning neither DataRead nor DataWrite occur. Firing the events, especially DataRead, when they are not actually used can be an unnecessary burden for performance. If you intend to use these events, set corresponding property to True.

DataRead event allows the developer to modify field values when they are retrieved from the data source. It can be used for formatting and other similar purposes. If you modify the value of a field in DataRead, TData will treat that value as if it were read from the data source.

DataWrite event allows the developer to modify field values before they are stored in the data source. It can be used for different purposes including

•

Storing field values differently from how they are presented to the user (in conjunction with DataRead),

•

Overriding the default action of saving changes to the database, if some more involved action than just updating a recordset record is needed.

It is important to understand that changes made in DataWrite are not reflected in TData fields and expressions. They are only applied to the values written to the data source, they do not persist in TData control in any way.


Modifying Field Value Entered by the User

WillChangeField event gives you an opportunity to change the value that is about to be assigned to a field. For example, you can convert the value to uppercase before assigning it to a string field.


Using TData in Distributed Applications (disconnected recordset support)

Building distributed applications, it is a common practice to use disconnected recordsets (Recordset.ActiveConnection = Nothing). A disconnected recordset is created on the server and marshaled (passed) to the client. When client updates must be saved in the database, the disconnected recordset is passed back to the server, re-connected to the database, and changes are saved in the database with Recordset.UpdateBatch. To use TData in a distributed application, you need to do the following:

•

Set TData.LockType = adLockBatchOptimistic and TData.ManualUpdate = True.

•

Create a disconnected recordset (with Recordset.ActiveConnection=Nothing and Recordset.LockType=adLockBatchOptimistic) and set TData.SourceRecordset to that recordset at run time.

•

When the end-user modifies data, the changes are stored in TData.Recordset, while TData.SourceRecordset remains unchaged, and update does not occur until explicitely triggered by programmer's code (for example, from a Submit command button). This is how TData.LockType = adLockBatchOptimistic works.

•

In a Submit button code, or other code updating user changes to the database, write the following:

TData1.Recordset.UpdateBatch

update_procedure(TData1.SourceRecordset)

TData1.SourceRecordset.UpdateBatch

Here update_procedure is a subroutine or an object method (it may be a business object) passing TData.SourceRecordset to the server for update. Write all the necessary code to update the database (on the server) in this procedure/method. If you already have pre-built classes for database update, use them here.

This is how it works: TData.Recordset.UpdateBatch sends users changes to TData.SourceRecordset (before this, TData.SourceRecordset remained unchanged), it does not save the changes in the database, because TData.ManualUpdate is set to True. Then modified SourceRecordset is sent to the server for update. After successful update, you need to reset the state of TData.SourceRecordset rows, to reflect the fact that there are no longer pending changes. This is done by TData.SourceRecordset.UpdateBatch. It does not perform any update (SourceRecordset is disconnected, so there is no database to update), it just resets the pending change flags. Depending on your application logic, you may consider refreshing TData with new data, fetched from the server, at this point, because data could change as a result of database update. But this is optional, necessary only if your application logic requires it.


Field Modification Modes

One of the advantages of True DataControl over the standard ADO data control and other data sources is that True DataControl can react instantly to field value modifications initiated by the user.

Often, your application needs to perform a specific action in response to a field modification. Other fields may depend on the modified value, or you may need to verify that the modified value satisfies certain constraints. For example, when a check box is toggled, it is usually necessary to update the recordset field to which it is bound. Visual Basic does not provide this functionality. Without True DataControl, you would have to write code to handle an appropriate event in the control that initiated the change. In the case of a check box, it would be its Click event. Moreover, there is no standard way in Visual Basic code to update the recordset fields with modified values from bound controls. You can only write code that directly sets the recordset field value in the check box’s Click event, but that defeats the purpose of data binding. What have we gained from binding a check box to a field if we have to write code directly updating the field when the check box value is changed?

True DataControl solves this problem, complements of the Visual Basic environment, with well-defined field modification functionality. This frees you from the tedious task of coding event handlers, effectively widening the scope of Visual Basic data binding.

This functionality is unavailable in the Lite version.

With True DataControl, you do not need to write control-specific event handlers. Just set the field’s ModificationMode property to either 1 - Immediate or 2 - Leaving control (the default). Provided that ModificationMode is not 0 - None, True DataControl will react to field modifications (both by the end-user and from code), and perform whatever actions are necessary, such as re-evaluating all expressions that depend on the changed value. True DataControl will also propagate the changes to any dependent fields or control properties, and will even refresh dependent TData controls if necessary.

Note: It is important to understand that "reacting to a field change" only means that True DataControl stores updated field values in its recordset, as in an internal buffer; it does not yet post changes to the database. Changes are posted to the database whenever the TData control is repositioned to another record, or when your code explicitly calls the Recordset.Update method.

The allowable settings for the ModificationMode:Field property are as follows:

1 - Immediate

Suitable for a field represented by controls such as list box, dropdown-list combo box, check box, radio button, or any other control whose value can be changed by a single click or keystroke. Such fields are updated immediately when the user interacts with the control to change the field’s value.

2 - Leaving control

This is the default setting, which is typically used with data entry controls that accept keyboard input, such as text boxes. Field update is triggered when the user moves focus away from the control after changing its value. To trigger an update with each keystroke, use the Immediate setting.

0 - None

True DataControl will not update the field until it is done in due course by Visual Basic, or the UpdateFields method is called. Use this setting when you don’t need automatic field updates, but prefer full programmatic control.

Note: Field update involves checking constraints and preventing the user from leaving control unless the constraints are satisfied. For more information, see Validation and Constraints. Some controls, such as Help and Cancel buttons, must be allowed to receive focus regardless of any constraints. These are controls whose CausesValidation property is set to False. True DataControl honors the CausesValidation setting. In 2 - Leaving control mode, it will not trigger a field update if the focus is moved to a control whose CausesValidation property is set to False.


Validation and Constraints

True DataControl allows you to define two kinds of data validation constraints:

1.

Field-level constraints are defined for each field in the field’s Constraints collection. For more information, see Field Constraints. As the name implies, each constraint belongs to an individual field. True DataControl automatically checks field constraints whenever the field value changes. It also checks other validation conditions on field change, see below.

2.

Record-level constraints are defined in the TData control’s Constraints collection. For more information, see Record Validation. These constraints usually involve multiple field values, and are tested when the TData control is repositioned to a different record or when the modified record is posted to the database. True DataControl does not test record-level constraints when a field value changes.

In addition to these programmer-specified constraints, True DataControl automatically performs data format validation upon every field change. For example, True DataControl will reject input such as 31/31/99 for date fields. If a field's Required property is True, empty data values are rejected as well.

If necessary, you can perform your own validation in code by writing a handler for the WillChangeField event. Record-level validation can be performed in code in the WillChangeRecord event.

Field Validation

Standard Error Message in Field Validation

Using Error Event in Field Validation

Record Validation

True DataControl Error Handling and Bound Controls


Field Validation

When the user modifies the value of a field in a bound control, validation occurs in the following order:

1.

Data format validation.

2.

WillChangeField event code, if present. This event procedure can change the value entered by the user (e.g., convert it to uppercase) and validate it as well.

3.

Required:Field property validation, if specified.

4.

Field-level constraint expressions, if specified.

If one of these fails, True DataControl raises an error. If field validation was triggered by moving focus out of a bound control (the field’s ModificationMode is 2 – Leaving control), True DataControl cancels that focus move, and returns focus to the offending control. In this way, True DataControl effectively prevents the user from leaving a control containing incorrect data. It also gives the user an opportunity to restore the previous value of the field, which permits the user to leave the control. For more information, see Standard error message in field validation.

If the field’s ModificationMode is 1 - Immediate, True DataControl validates each change in the control, even individual keystrokes. In case of an error, the change is automatically canceled.


Standard Error Message in Field Validation

If not overriden by the Error event handler code, the standard True DataControl reaction to a field error is to display a message box with the field name and error description:

This does not include errors detected in the WillChangeField event. You must provide your own error handling if you cancel an update in the WillChangeField event, as True DataControl will not display its standard error message box or fire the Error event in this case.

The message box caption can be changed (most probably, to your application name) by setting the ErrorMsgCaption property.

The prompt to restore the previous value appears only if the field’s ModificationMode is 2 – Leaving control. For ModificationMode = 1 – Immediate, True DataControl always restores the previous value when the message box is closed, without prompting the user. The Lite version, True DataControl Lite also behaves this way, it does not prompt the user for restoring the previous value.

The prompt to restore the previous value can be removed from the message box by setting the ErrorMsgRestore property to False. It can be set to False permanently, or the setting can be changed in the Error event, just before the message box appears. Also, the prompt text can be customized calling the SetUIString method.

When the message box closes, True DataControl returns focus to the bound control where the error occurred. If the user answered Yes to the prompt, True DataControl restores the previous value in the control so the user can move focus out of the control without leaving incorrect value there.

If you do not like the standard restore prompt, you can set ErrorMsgRestore property to False, so the prompt will not appear, and provide your own means of reverting changes. For example, you can rely on the TData control’s Cancel button (set the ButtonCancel property to True), or you might provide a Cancel or Undo command button calling the CancelUpdate method. If you use a command button, make sure to set the button’s CausesValidation property to False, to make the button accessible in case of error. You must use the TData control's CancelUpdate method instead of the standard TData.Recordset.CancelUpdate, because the standard ADO CancelUpdate will do nothing until a field’s value is changed, and it won’t be changed in case of an error, a kind of vicious circle.

Some bound controls will restore the previous value regardless of the user’s answer to the restore prompt. For example, Microsoft DataGrid control behaves this way. This is because it always restores previous value if an error occurs. Some users can consider this behavior rude, it does not allow them to fix an incorrect value, the invalid value is instantly obliterated. True Data cannot override this behavior. If this bothers you, we can only suggest you use a different bound control, one that does not restore previous values on every error. ComponentOne True DBGrid, for example, behaves correctly.


Using Error Event in Field Validation

You can override the standard True DataControl error handling by providing your Error event procedure. Setting the fCancelDisplay argument to True in the Error event procedure cancels the standard message box. You can provide whatever error handling you need, including error messages and other user interaction. If you want to restore the previous field value, you can do it in the Error event calling the CancelUpdate method.

To distinguish the situation where Error event is triggered by a field validation failure, use the Source and ErrorNumber arguments. This is necessary because the Error event occurs not only on validation failures, but also on other errors, such as saving data in the database.

On a field modification failure, the Source argument is set to “TData”, and the ErrorNumber is one of the following:’

2000 | Field constraint violation.
2002 | Required field is left empty.
2003 | Data type conversion error: data entered by the user in a bound control is invalid with respect to the field’s data type.
2005 | Field is read-only. And attempt has been made to change the value of a read-only field.
2006 | Data type conversion error: the new value assigned to a field programmatically is invalid with respect to the field’s data type.

For all these errors, the FieldName argument of the Error event is set to the name of the field where the failure occured.


Record Validation

Record-level validation occurs when True DataControl is repositioned to a different record and when the modified record is posted to the database. True DataControl checks the record-level constraints, evaluates the constraint expressions.

If at least one constraint expression evaluates to False, True DataControl cancels the update operation or record position move. So it never posts invalid data to database, and the user is not allowed to leave a record with invalid data in it.

On a record constraint failure, True DataControl fires the Error event setting its Source argument to “TData” and its ErrorNumber argument to 2001 - Record constraint violation. You can cancel the standard True DataControl error handling by setting the fCancelDisplay argument to True in the Error event procedure. If it is not canceled, a standard message box appears, with the error description, which is the result of the MessageExpression evaluation. The caption of this message box can be customized using the ErrorMsgCaption property.


True DataControl Error Handling and Bound Controls

Errors detected by True DataControl in field and record validation are handled by the True DataControl as described above, with Error event and standard error message. However, some bound controls still consider them as error conditions and may try to apply their own error handling, after one of True DataControl's. This occurs, for example, in the Microsoft DataGrid control. If you try to enter invalid data in a cell, you will see the True DataControl error message followed by an error message from the DataGrid control. This happens because data bound controls like DataGrid are not designed for data sources that can handle errors, they always try to handle errors themselves.

If you encounter such situation, it can be dealt with quite easily: use the bound control’s Error event to cancel the redundant error messages.

This problem will not occur with ComponentOne True DBGrid control, which is aware of the fact that an error is handled by True DataControl, and won't try to handle such error again. Yet another good reason to make ComponentOne True DBGrid your grid of choice!


Crosstab (matrix) Data Presentation

The crosstab feature is available starting from version 7.0, including True DataLite 7.0.

Normally, you will use the crosstab feature of True DataControl with ComponentOne True DBGrid. True DBGrid supports crosstab data presentation (in conjunction with TData or TDataLite) starting from version 7.0. You can use the crosstab feature with other, non-ComponentOne grids too, but then all crosstab columns (see below) will appear as separate fields, you will have to specify all settings for every crosstab column separately.

Crosstab is a common feature of database applications. Until now, True DBGrid did not support crosstab directly, it was necessary to use unbound mode events and complex coding to implement it, or create special temporary database tables or queries. Now, True DBGrid and TData/TDataLite work together to implement crosstab for you. Unlike crosstab implementations in many other tools, TData crosstab is modifiable at run time: you can modifiy values in crosstab columns (cells), if, of course, the underlying recordset is modifiable.

Crosstab is a matrix-like representation where you have multiple columns representing values of a single database column. For example, a MonthlyOrders table has the following fields: CustomerID, Month, Amount, and you need to present the data as a table with twelve columns, one for each month, showing monthly amounts. An example of crosstab data presentation can be found in Tutorial 2 - Crosstab.

Crosstab is only available in DataMode = 0 – DataSource.

In crosstab mode, all visible fields are divided into three categories:

•

Row key fields: fields defining crosstab rows. Different records with the same row key values (they can differ by their column key values) belong to the same crosstab row. For example, if CustomerID is the row key, each customer is displayed in a different row, but multiple records differing only by their Month (column key) value are displayed in the same customer row. There can be multiple row key fields, for example DepartmentID;CustomerID.

•

Column key fields: fields defining crosstab columns. Records with different column key values are displayed in different columns. For example, if Month is the column key, each month occupies a separate column. There can be multiple column key fields, for example Year;Month.

•

Crosstab fields: values of a crosstab field are displayed in crosstab cells, on row/column intersections. For example, if the Amount is a crosstab field and Month is the column key field, one Amount field will generate twelve fields, monthly amounts, at run time. At design time, Amount will remain a single field, so you can conveniently set its properties at design time. These settings will be applied to all crosstab columns it generates (there is a special property, XtabSeparateFields, allowing to override this default behavior). You can have multiple crosstab fields, each of them generating its own crosstab columns. For example, you can have Amount and Discount fields, both of them displaying monthly data, so you will have 24 columns in your crosstab.

You must make sure that the recordset is ordered by row keys. What is essential for TData crosstab implementation, is that all records with a given row key value appear as a contiguous segment of the recordset. In SQL, the common method of ordering the recordset is using ORDER BY clause, for example

SELECT CustomerID, Month, Amount FROM MonthlyOrders ORDER BY CustomerID

To enable crosstab mode, set the Xtab property to True. This and other crosstab-specific properties can be specified on the Crosstab property page.

To specify row key, set the XtabRowKey property. If it is a single field, just set it to the field’s name, for multiple fields use semicolon-separated list, for example, DepartmentID;CustomerID. The order of fields in this list must correspond to the order sequence of the recordset (ORDER BY).

To specify column key, set the XtabColKey property. If it is a single field, just set it to the field’s name, for multiple fields use semicolon-separated list, for example, Year;Month.

For every crosstab field, specify its XtabColumns property. At design time, select the field in the Crosstab property page and enter the string value in the XTabColumns edit box.XtabColumns property value is a string conforming to the following syntax rules:

An XtabColumns string consists of column definitions separated with semicolons. Each column definition has a key expression and a column name:

<key expression>:<column name>

<key expression> is a valid TData expression. Usually, it is just a constant. Don’t forget to enclose it in double quotes if it is a string expression.

<column name> is a string defining the name of the crosstab column. You don’t have to double quote field names.

If you have multiple column key fields (as in the Year;Month example above), the column definition syntax is slightly different. You must supply a valid TData expression (usually, constant) for every column key field, and separate them with colons:

<key expression1>,…,<key expressionN>:<column name>

Example of a single column key field, Month:

1:Jan;2:Feb;3:Mar;4:Apr;5:May;6:Jun;7:Jul;8:Aug;9:Sep;10:Oct;11:Nov;12:Dec

Example of multiple column key fields, Country,Year:

“US”,1999:U.S. 1999;”US”,2000:U.S. 2000;”Canada”,1999:Canada 1999; ”Canada”,2000:Canada 2000

Notice double quotes in constant key expression (you always must enclose constant string expressions in double or single quotes) and the absence of quotes in the column name (it is not an expression, just a string).

XtabColumns is a property of a field. Setting this property makes it a crosstab field. If you have multiple crosstab fields, set XtabColumns for each of them.

The XtabColumns property can also be set at run time in the WillOpenData event.

A special property, XtabSeparateFields controls the way crosstab columns are exposed to True DBGrid at design time.

If XtabSeparateFields = False (default), TDBGrid will see a single field (for every crosstab field) at design time in its property pages (but it will display all crosstab columns properly). In most cases, it is convenient because you usually set up all crosstab columns with identical settings. All settings of the corresponding column will be applied to all crosstab columns it generates. This propagation of settings to all crosstab columns takes place only at design time. At run time, you can resize and set properties of crosstab columns separately, regardless of the XtabSeparateFields value.

If XtabSeparateFields = True, TDBGrid will see crosstab columns as separate data fields, so you can set up each of them separately.

If you have multiple crosstab fields, you can choose one of two possible layouts controlled by the XtabCollate property. If XtabCollate = False (default), the crosstab columns generated by different fields will be interspersed, that is, the corresponding columns will be grouped by the column key value, every group containing all fields with that key value. If XtabCollate = True, the columns will be grouped by the main field, that is, all columns generated by the first field will apear first, then all columns generated by the second fields, and so on.


OLAP: Decision Support, Pivot Table

The Pivot feature is available starting from version 7.0, including True DataLite 7.0.

Normally, you will use the Pivot feature of True DataControl with ComponentOne True DBGrid. True DBGrid supports Pivot (in conjunction with TData or TDataLite) starting from version 7.0. You can use the Pivot feature with other, non-ComponentOne grids too, but they must be able to display hierarchical recordsets, and you will probably find them less convenient to use with TData than ComponentOne True DBGrid, for there won’t be such close integration between the two controls at design time as between TData and True DBGrid. For one thing, you must set the PivotFieldsAllLevels property to False using it with any control other than True DBGrid.

On-Line Analitycal Processing (OLAP) functionality has many names, such as Data Analysis, Decision Support, Pivot Table, Decision Cube, etc. The essence of it is to allow end-users to explore data in different projections and hierarchies. The user can interactively choose and reorder the dimensions in which data are represented and summarized. An OLAP front-end, a pivot table browser/grid displays data in a hierarchical crosstab view.

With TData/TDataLite, True DBGrid 7.0 becomes an OLAP front-end control. It gives you important advantages over other existing OLAP solutions:

•

You no longer have to rely on external tools adding OLAP functionality to your applications, you can use the same grid control that you love, with the same familiar object model.

•

True DBGrid is fully customizable and programmable in OLAP (Pivot) mode, as it is in all other modes. You can make your OLAP solutions look and feel consistently with other parts of your application, so your users won’t need to learn additional, external tools and user interface.

An example of the Pivot feature can be found in Tutorial 10 - OLAP - Decision Support, Pivot Table.

In Pivot mode, True DataControl functions in a very special way. Most of its other features become unavailable because they have no sense in that mode. You can think of a TData control in Pivot mode as of a separate control, different from normal TData, implemented in the same TData control only as a convenience, to spare the hassles of installing two different controls. Only pivot-related properties described below have effect on a TData control in Pivot mode, all other properties are ignored, including all properties specified on all property pages.

The following will give you instructions to set up a TDBGrid control displaying an OLAP cube. For step-by-step instructions and screenshots, consult Tutorial 10 - OLAP - Decision Support, Pivot Table.

To enable pivot mode, set the Pivot property to True.

TData Pivot mode uses ADO MD (Microsoft ActiveX Data Objects (Multi-Dimensional)) that works with an OLAP-enabled OLE DB provider, such as Microsoft OLAP Services. These components must be installed on the client computer. The easiest way to guarantee it is to install Microsoft Office 2000 (Microsoft Excel and MS Query).

First, you need to prepare an OLAP data source that you want to use with TData. It is specified in the PivotConnectionString property. PivotConnectionString accepts any OLAP data connection valid for ADOMD.Catalog object, see Microsoft ADO MD documentation for details. It can be a live on-line connection to an OLAP server, or a connection to an off-line cube file, as in the following example:

“Provider=msolap;DATA SOURCE=C:\OLAPCubes\orders.cub”

For example, you can prepare a cube file in Microsoft Excel 2000, with PivotTable and PivotChart Wizard, see Tutorial 10 - OLAP - Decision Support, Pivot Table.

Set the PivotCubeName property to the name of the desired cube (there can be many cubes in a single OLAP data connection). The default cube name produced by Microsoft Excel is “OCWCube”.

Once PivotConnectionString and PivotCubeName are set, you are ready to bind a TDBGrid control to your TData control. Set TDBGrid.DataSource to TData.

If you use pivot feature with ComponentOne True DBGrid, make sure the PivotFieldsAllLevels is set to True (default). Using it with other, third-party controls, set this property to False.

Also, using ComponentOne True DBGrid, make sure you set DataView = 1 – Hierarchical. Otherwise, the grid will not display the data properly.

Retrieving fields in TDBGrid will show all dimension fields and measure field(s) of the cube. However, if you run the project, the grid will be empty. This is because you need to supply a query, specifying which dimension fields are used as row dimensions, which dimension field is used as the column dimension (TData/TDBGrid allows hierarchy in row dimensions, but not in column dimensions, it always uses a single dimension for columns, represented in a crosstab fashion), and which measure field is used for cell values. This query information must be specified by setting the corresponding properties: PivotRowDimensions (comma-separated list of chosen row dimension fields), PivotColumnDimension (the name of the chosen column dimension field) and PivotMeasure (the name of the chosen measure field).

You, as an application developer, write the code that specifies this query information (PivotRowDimensions, PivotColumnDimension, PivotMeasure) based on end-user selection made in some UI controls, such as list boxes, for example.

Having determined the query, you can apply it calling the PivotOpen method. This will show the result in the grid. As an advanced option, you can specify an arbitrary multidimensional query (an MDX statement) as an optional string parameter in the PivotOpen method, that will override PivotRowDimensions, PivotColumnDimension and PivotMeasure.

Row dimensions are presented in a hierarchical form, so the user can expand/collapse them to get more/less detailed view of the data.

Column dimension are presented as a crosstab: a column for each dimension value. For example, if you have column dimension Country, you will get as many columns as there are countries in the cube.

Grid cells show the measure field, usually a number, representing the measure value corresponding to certain dimension values. A special value of each dimension displays totals, measure values aggregated by this dimension.

All other fields, dimensions and measures, that don’t participate in the end-user selected query, are hidden.

All the powerful versatile features of True DBGrid are available in Pivot mode. You can specify property settings for grid columns representing dimension and measure fields, either at design or at run time. You can write code in grid events to further customize your OLAP front end application. For example, Tutorial 10 - OLAP - Decision Support, Pivot Table shows how to highlight cells meeting certain condition.

Every time you change end-user selection and re-apply PivotOpen, the grid is refreshed showing the updated query in the updated layout.


Using True DataControl in Different Containers

True DataControl can be used in any development environment supporting Microsoft OLE DB data binding specification. However, in certain containers, some of less important features of True DataControl may be not functional, due to container limitations.

This section contains specific information about development environments belonging to the Microsoft Visual Studio product family.

Cannot Bind Elements of Control Array in Visual Basic

Field Modification Modes work only in Visual Basic

The NameSubstitute Property Must Be Used in VC++

Master Control Cannot Be Chosen From Combo Box in VC++

Property Expressions Not Working in VC++


Cannot Bind Elements of Control Array in Visual Basic

A True DataControl limitation prohibits binding controls elements of a control array (controls with non-empty Index property) to a True DataControl. An attempt to bind a control array element to a True DataControl will result in a run-time error message: "Control array elements (controls with non-empty Index property) can't be bound to a True DataControl"

Work around: Do not use control arrays, use separate controls with different Name property values.


Field Modification Modes work only in Visual Basic

ModificationMode = 1 - Immediate and 2 - LeavingControl are supported only in Visual Basic. In other containers, TData behavior is always as in ModificationMode = 0 - None. See Field Modification Modes for detail.

This limitation does not mean that some application features cannot be implemented with True DataControl in non-VB containers. It only means that automatic detection of field modification takes place only in Visual Basic. In other containers, you have to use control events and similar mechanisms, exactly as you do with standard data sources, such as the Microsoft ADODC control.


The NameSubstitute Property Must Be Used in VC++

Using True DataControl in VC++, you have to set its NameSubstitute property at design time. Set this property to the control name, what would be its Name property value in Visual Basic. This property is necessary because VC++ container does not supply its own Name property. True DataControl relies on Name for master-detail relationships.


Master Control Cannot Be Chosen From Combo Box in VC++

Setting up master-detail relationship in VC++ container at design time, all combo boxes that are supposed to show possible Master controls, are empty. You have to type the master's name (the value of its NameSubstitute property) manually. For the same reason, True DataControl Check facility does not detect "Unknown variable" errors in expressions in VC++ container, since expressions such as "TData1.AField" make use of other TData control's names, which are inaccessible in VC++.


Property Expressions Not Working in VC++

Dynamic Control Property Expressions do not work in VC++ container. This is because they depend on the Name property of corresponding controls, and VC++ container does not provide the Name property. See Control Property Expressions for details.


End-User Interface Features

True DataControl has thirteen buttons that invoke built-in user interface functions ready for use in your applications. You control their visibility. These buttons are MoveFirst, PreviousPage, Previous, AddNew, Update, Cancel, QueryMode, Delete, FindDialog, BookmarksDialog, Next, NextPage, and Last. The actions invoked by these buttons can also be invoked from code, without the buttons.

True DataControl Query Mode is described in Query Mode. The two standard dialogs provided by True DataControl, Find and Bookmarks, are described in this chapter. Also described are the True DataControl buttons, including how to control them and their functions programmatically.

Find Dialog

Bookmarks Dialog

True DataControl Buttons

Repeat Feature and Tooltips

Button Properties

Invoking and Substituting Button Functions in Code

Customizing User Interface Strings and Images


Find Dialog

The Find dialog allows the end-user to search recordset for a certain value of a field. It is a built-in feature of True DataControl. All you need to enable the Find functionality, is to expose the Find button to the user by setting ButtonFind=True (it is False by default), or to invoke the dialog from code calling the PressButton method with tdbButtonFind argument.

In the Find dialog, the search field is selected from the Find In Field combo box. The search string can be typed in or selected from the list of recent search strings in the Find What combo box. The Match combo box allows selection of a comparison operation to be used in the search (default: = ("equals")). The Search combo box has three options defining the search scope: Up, Down and All. The search can be case-sensitive or case-insensitive, according to the value of the Match Case check box.

Two True DataControl field properties govern the appearance of True DataControl fields in the Find In Field combo box: Searchable and DisplayName. Only fields with Field.Searchable = True (default) appear in the combo box. The Field.DisplayName property determines a user-friendly textual form in which the field is represented in the combo box.


Bookmarks Dialog

The Bookmarks dialog allows the end-user to

•

bookmark the current record, adding it to the list of bookmarked records,

•

jump to a bookmarked record, and

•

maintain the list of bookmarked records.

This functionality is necessary in many database applications. The built-in Bookmarks dialog means that you have this functionality at your disposal without any manual coding. To enable the Bookmarks functionality, expose the Bookmarks button to the user by setting ButtonBookmark=True (it is False by default), or invoke the dialog from code by calling the PressButton method with the tdbButtonBookmarks argument.

The Bookmarks dialog has a list of bookmarks, an edit area for Bookmark Name and four buttons: Add, Delete, Go To and Cancel.

To bookmark the current row, the end-user must enter a string in the Bookmark Name text box and press the Add button. As the developer, you can make it even easier for end-users by setting the bookmark name in the GetBookmarkName event, so the dialog will appear with the new bookmark’s name already in it. Pressing the Add button closes the dialog. Next time the dialog is invoked, the new bookmark will be added to the list.

To move to a bookmarked row, the end-user selects a bookmark from the list and presses the Go To button.

Any bookmark in the list can be deleted by selecting it from the list and pressing the Delete button.

Refreshing the True DataControl recordset (with the Refresh method, or as a result of repositioning the Master in master-detail relationship, or for another reason) clears the list of available bookmarks.


Handling the GetBookmarkName Event

The programmer can make bookmark names appear automatically, so the user won't have to enter a name for each bookmark manually.

This can be done in the GetBookmarkName event procedure. The GetBookmarkName event is fired before opening the Bookmarks dialog. Setting its BookmarkName argument to a string makes that string appear as the default bookmark name for the current record. In most cases, you will find it useful to set the argument to the value of a recordset field that allows the user to identify the record. For example:

Private Sub TData1_GetBookmarkName(BookmarkName As String)

BookmarkName = TData1("LastName")

End Sub


NamedBookmarks Collection

The list of bookmarks showing in the Bookmarks dialog is available to the programmer as the TData control’s NamedBookmarks collection (run-time only). Each element of that collection is a NamedBookmark object having two properties: Name (type: String) and Value (type: Variant).

NamedBookmark.Name is the bookmark name and NamedBookmark.Value is the bookmark itself, its value.

The programmer can modify the NamedBookmarks collection at run time, controlling the contents of the list in the Bookmarks dialog.


True DataControl Buttons

The following is a brief description of all thirteen True DataControl buttons and their functions.

First/Last

Pressing one of these buttons positions a True DataControl on its first/last record.

Both buttons are visible if the ButtonFirst property is True (default: True).

Previous Page/Next Page

Pressing one of these buttons moves PageSize records backward/forward in the recordset.

Both buttons are visible if the ButtonPage property is True (default: False).

Previous/Next

Pressing one of these buttons moves one record backward/forward in the recordset.

If the user presses one of these buttons and holds the left mouse button, the button causes movement repeatedly, with a small fixed time interval (the “repeat” feature).

If there is no previous/next record in the recordset, i.e., the current record is first/last, the behavior depends on the BOFAction/EOFAction property setting.

Both buttons are visible if the ButtonNext property is True (default: True).

AddNew

Pressing this button adds a new row to the recordset and positions on the newly added row.

It is visible if the ButtonAdd property is True (default: False).

Update

Pressing this button updates the recordset, i.e., sends the modified values to the database.

In batch update mode (LockType =adLockBatchOptimistic), it performs Recordset.UpdateBatch, otherwise, it performs Recordset.Update.

It is visible if the ButtonUpdate property is True (default: False).

Cancel

Pressing this button cancels the changes made by the end-user. It is equivalent to Recordset.CancelBatch in batch update mode (LockType=adLockBatchOptimistic), and to Recordset.CancelUpdate otherwise.

It is visible if the ButtonCancel property is True (default: False).

There is a special property, ConfirmCancel that, if set to True (default: False), makes True DataControl show a confirmation dialog when the Cancel button is pressed.

Query

This toggle button switches a TData control between query and result modes. For more information, see Query Mode. When the button is depressed, the control is in query mode. When it is released, the control is in result mode.

The Query button is visible if the ButtonQuery property is True (default: False).

Delete

Pressing this button deletes the current row from the recordset.

It is visible if the ButtonDelete property is True (default: False).

There is a special property, ConfirmDelete that, if set to True (default: False), makes True DataControl show a confirmation dialog when the Delete button is pressed.

Find

Pressing the Find button invokes the Find Dialog.

It is visible if the ButtonFind property is True (default: False).

Bookmarks

Pressing the Bookmarks button invokes the Bookmarks Dialog.

It is visible if the ButtonBookmark property is True (default: False).


Repeat Feature and Tooltips

Two True DataControl buttons, Next and Previous, have a so-called “repeat” feature:

If the user presses the button while holding down the left mouse button without releasing it, the button’s action is triggered repeatedly, with a small fixed time interval.

Such are two buttons:.

This feature makes it more convenient for the end-user to navigate through the recordset.

True DataControl buttons are provided with tooltips: small text windows that pop up when the mouse lingers over a button. The tooltips are disabled by default. To enable them, set the Tooltips property to True. Tooltips texts can be customized/localized using the SetUIString method.


Button Properties


Button Visibility

By default, only four buttons are visible: First, Previous, Next and Last, consistent with the Visual Basic data control tradition.

Visibility of True DataControl buttons is controlled by the following properties of the True DataControl. All of them are read/write at run time, and can be set at design time both in the Visual Basic Properties window and on the General property page.

ButtonAdd (default: False)

ButtonBookmark (default: False)

ButtonCancel (default: False)

ButtonDelete (default: False)

ButtonFind (default: False)

ButtonFirst (controls the First and Last buttons, default: True)

ButtonNext (controls the Previous and Next buttons, default: True)

ButtonPage (controls the PreviousPage and NextPage buttons, default: False)

ButtonQuery (default: False)

ButtonUpdate (default: False)


Identifying a Button in Code

Several True DataControl methods and events use the following ButtonEnum enumeration constants to identify buttons:

tdbButtonFirst = 0,
tdbButtonPrevious = 1,
tdbButtonNext = 2,
tdbButtonLast = 3,
tdbButtonNextPage = 4,
tdbButtonPrevPage = 5,
tdbButtonAdd = 6,
tdbButtonDelete = 7,
tdbButtonUpdate = 8,
tdbButtonCancel = 9,
tdbButtonBookmarks = 10,
tdbButtonFind = 11,
tdbButtonQuery = 12


Button Enabled State

By default, True DataControl manages the enabled state of each button according to the current circumstances. For example, the Update button is enabled if a record has been modified.

The programmer can modify this default behavior by calling the EnableButton method.

It has two arguments: a button ID (ButtonEnum) and the enabled state, which can be one of the following three constant values:

tdbButtonEnabled = 0

Unconditionally enables the button.

tdbButtonDisabled = 1

Unconditionally disables the button.

tdbButtonEnabledDefault = 2

Resets previously set enabled set, so the button’s enabled state is maintained by the True DataControl default rules.

See Identifying a button in code for more information.


Invoking and Substituting Button Functions in Code

The ButtonPressed event occurs when a button is pressed by the end-user, before the actual button action is performed. If you prefer to execute your own action instead of the standard one, do so in the ButtonPressed event, and set the Cancel argument to True, which will cancel the standard action associated with the button.

The PressButton method simulates pressing a button, and performing the button action. It can be used even if the button is invisible or disabled. The ButtonPressed event is not fired by a PressButton call.

The PressButton method is especially useful when you want to benefit from the standard True DataControl dialogs, Find and Bookmarks, but don’t want them invoked with standard buttons. You can open the standard dialogs calling

TData1.PressButton tdbButtonFind

and

TData1.PressButton tdbButtonBookmarks


Customizing User Interface Strings and Images

Images shown on the face of True DataControl buttons can be customized with the SetButtonPicture method. Calling this method, provide a button ID, button-enabled state (True or False), and the image that can be loaded from a file with LoadPicture. You must provide two images for each button that you want to customize; one will be displayed when the button is enabled, the other when it is disabled.

Every string that is used by the True DataControl end-user interface can be localized (for international use), and customized in any other way by calling the SetUIString method. The SetUIString method has two arguments: one identifies a user interface string, the other is the string that replaces the default one. To identify all the strings used in its end-user interface, True DataControl defines a special TDStringEnum enumeration consisting of 31 constants.


Property Pages

True DataControl Property Pages provide an easy-to-use tree view designer that enables you to visually specify True DataControl properties and collections. The property pages can also assist you when you build True DataControl expressions.


True DataControl Context Menu

Right-click anywhere on the TData control at design time to display the context menu, which is a superset of the context menu that Visual Basic provides for all ActiveX controls.

The first eight commands are controlled by Visual Basic; the last three commands belong to True DataControl. These context menu commands operate as follows:

TData Properties

This command displays the True DataControl property pages. You can also display the property pages by selecting (Custom) from the Visual Basic Properties window.

Retrieve Fields

This command can be used only in data source mode (DataMode = 0 – Data Source). It populates the True DataControl Fields collection with the fields from data source, SourceRecordset.

If there are fields already defined in the TData control, this command will remove them, and all information associated with them (such as range conditions and constraints). If this is going to happen, the TData control issues a warning to the user and will not proceed without confirmation.

This command is also available in the Fields property page with the Retrieve Fields button.

Check

This command performs syntax checking of all expressions and other settings and properties of the TData control. The Check button in property pages will also perform a syntax check. See Syntax checking for details.


Using True DataControl Property Pages

Select TData Properties from the control's context menu to display the property pages dialog. You can also display the property pages by selecting (Custom) from the Visual Basic Properties window. To accept the changes made on any page, click the OK button at the bottom of the property page dialog. Click Cancel to discard any changes. The property pages dialog will be closed after you click OK or Cancel.

You can also click the Apply button to commit your changes without closing the dialog, which allows you to continue making changes on that property page Note that selecting a different property page tab will also commit any changes that you made.

You can click the Check button in property pages at any time to perform syntax check, verify True Data settings in its property pages. Any detected errors are immediately reported to you in a special message box. It is highly recommended to check syntax after every change to your control. See Syntax checking for details.

Some of the less important True DataControl properties cannot be edited in property pages, and should be specified in the Visual Basic Properties window.

Syntax Checking

Expression Editing

DataSource Page

General Page

Parameters Page

Fields Page

Filters Page

Property Expressions Page

Constraints Page

Crosstab Page


Syntax Checking

True DataControl can check your settings to detect possible errors that may result from incorrect syntax in an expression, or inconsistent settings of interdependent properties. Syntax check can be performed by pressing the property page Check button, or by selecting the Check item from the control’s context menu.

IMPORTANT: Do not run your program if True DataControl reports a syntax error. Fix the error first. Some errors may cause unpredictable behavior.

If errors have been detected, True DataControl opens a window with the list of found errors:

To view an error, navigate through the error list and select an error to view, then press the Go To Error button. The property page where the error originated opens and the focus is set to the particular tree node and control containing the incorrect information. But the Go To Error button is enabled only if you press the Check button in property pages. It is disabled if you select the Check item from the control’s context menu. In this case, the error list window is displayed only to notify you of errors. If you need to use Go To Error button to view one of these errors, press the Check button in property pages.


Expression Editing

True DataControl property pages have special provisions to help you enter expressions. You will easily recognize edit controls intended for entering expressions by the presence of an ellipsis button at their right edge:

If there are two adjacent controls, each with its own ellipsis button, then the first (left) contains the expression itself and the second (right) contains a condition, which is a boolean expression that controls whether the first expression should be evaluated. If the condition associated with an expression evaluates to False, the expression is ignored.

Click on the ellipsis button to open the True DataControl Expression Editor:

Using the expression editor, you can build or edit an expression by selecting elements from the four lists in the bottom half of the window:

Parameters

Parameter variables defined in the Parameters property page.

Fields

Field variables retrieved from the data source or defined in the Fields property page.

Operators

VBScript operators supported by True DataControl.

Functions

VBScript functions supported by True DataControl.

Double-click an element in any of these lists to paste it into the Expression text box at the top of the window. Alternatively, you can type expressions directly into this text box.

If the Master property is set, you can use the From combo box to control which variables are displayed in the Parameters and Fields lists. Select either the TData control or one of its ancestors in the master-detail hierarchy to filter the lists accordingly.

Use the Operators and Functions and Constants combo boxes to control which items are displayed in the corresponding lists. See the VBScript Reference for a complete listing.

Clicking OK or pressing Enter performs a syntax check of the expression, closes the expression editor, and returns focus to the active expression edit control in the property page. Use the Cancel button to close the expression editor and discard changes. Use the Check button to perform a syntax check without closing the expression editor.


DataSource Page

The DataSource page defines the source of data for a TData control. For more information, see Data Access Modes. This page is unavailable in True DataControl Lite.

The DataMode combo box (upper-left corner) sets the DataMode property, one of the three modes in which a TData control can function. The DataMode property is supposed to be determined once in control’s lifetime, since changing it, although possible, has drastic effects.

The LockType combo box (lower-right corner) sets the LockType property, which determines the locking behavior of the control’s Recordset. Setting LockType to 1 – adLockReadOnly makes the TData Recordset read-only.

All other controls in the DataSource page are applicable only for data source mode (DataMode = 0 – Data Source). They are disabled in the memory array and the user events data modes.

The DataSource page design is modeled after the property pages of the standard ADO data control (Microsoft ADODC). This ensures smooth upgrade path for users familiar with ADODC. The difference is that three separate ADODC property pages: General, Authentication, and RecordSource, are combined in one True DataControl DataSource page for more convenience.

To define a data source in the DataSource page, start by specifying a Source of Connection. You can use one of three options: use a Data Link File, an ODBC Data Source Name, or enter the Connection String directly. These options are simply different ways of specifying the ConnectionString property. ConnectionString is the only property that is edited here. If you choose to enter the ConnectionString directly, you can use the Build button to open the Data Link Properties dialog. This is a standard dialog (the same is used in ADODC and other OLE DB/ADO data sources) allowing you to select an OLE DB provider, and specify its initialization properties that you need to establish connection with a data source.

The Other Attributes edit box allows you to add some custom text to ConnectionString that can’t be specified in the Data Link Properties dialog.

The Authentication group (UserName and Password) is also used to establish connection with a data source, if needed.

Once you have established the connection with the data source, you can specify a particular table, SQL query, or other command text that defines the RecordSource of the TData control. First, select the CommandType indicating how the RecordSource string must be interpreted. Then, depending on the CommandType, you can select a Table or Stored Procedure Name from the combo box list the TData control retrieves from the data source, or you can type directly in the Command text (SQL) text box.

Once you have specified the data source properties, press the Test button to test the data connection. If the connection source or RecordSource is not correctly specified, you will receive an error message indicating the reason for failure.


General Page

The General page is used to set the overall characteristics of a TData control, that is, those properties belonging to the TData control itself. The remaining pages manage the control’s collections.

The General page manages only the most important, frequently changed properties of the TData control. You should specify less important TData control properties in the Visual Basic Properties window.

The General property page is used to set the following properties:

Master

Specifies the TData control on which this control is dependent in a master-detail relationship.

AutoRefresh

Controls the automatic refresh of a detail control upon changes in the master (in a master-detail relationship)

LinkType

Specifies how the control is linked to the master True DataControl, if it is a linked control (participates in 1-1 link)

Filtered

Enables/disables filtering

ButtonAdd

Specifies whether the Add button is visible

ButtonBookmark

Specifies whether the Bookmarks button is visible

ButtonCancel

Specifies whether the Cancel button is visible

ButtonDelete

Specifies whether the Delete button is visible

ButtonFind

Specifies whether the Find button is visible

ButtonFirst

Specifies whether the First and Last buttons are visible

ButtonNext

Specifies whether the Next and Previous buttons are visible

ButtonPage

Specifies whether the NextPage and previousPage buttons are visible

ButtonQuery

Specifies whether the Query button is visible

ButtonUpdate

Specifies whether the Update button is visible


Parameters Page

The Parameters page is used to maintain the Parameters collection. Use the Parameters property to access the Parameters collection in code.

True DataControl parameters are variables that store values independent of the particular record on which the TData control is positioned. In this way they differ from fields. Fields are variables too. However, their values depend on the current record. Both fields and parameters are accessible in True DataControl expressions and from code. See True DataControl Parameters for details.

The Parameters page is initially empty. Click the New button to create a new parameter with default attributes. Alternatively, you can right-click the Parameters list and choose New from the context menu.

To remove a parameter from the list, select it and click the Delete button, or right-click it and choose Delete from the context menu. Change the order of the parameters by dragging individual items within the Parameters list.

When you select an item in the Parameters list, the other controls on the page display the properties of the selected parameter:

Name

Specifies the parameter name.

Type

Determines the data type of the parameter.

SQLParameter

Associates the parameter with a symbolic name used as a parameter in an SQL statement used as the control’s RecordSource. See Parameterized SQL for details. Leave this property empty if you don’t need to attach the parameter to an SQL parameter.

ValueExpression

Defines the expression used to assign a value to the parameter. Leave this property empty if you don’t want automatic evaluation of the parameter, prefer to set it in code.


Fields Page

The Fields page is used to maintain the Fields collection, which is the most important of True DataControl’s collections. Use the Fields property to access the Fields collection in code.

True DataControl fields are variables storing values dependent on the particular record on which the TData control is positioned. These fields form the TData Recordset. They are exposed to data-aware controls bound to the TData control. See the detailed description in True DataControl Fields.

If you use the TData control in data source mode, the Fields collection is automatically populated when you first open the Fields page after setting the data source properties. However, if you change data source properties later, the existing fields are preserved. To re-populate the Fields collection from the new data source, click the Retrieve Fields button on the Fields page. Alternatively, you can right-click the TData control on the form and choose Retrieve Fields from the control's context menu.

In memory array and user events modes, the Fields collection is initially empty.

To create a new field, click the New button and select New Field from the button's context menu. Alternatively, you can right-click the Fields list and choose New Field from the list's context menu. To remove a field from the list, select it and click the Delete button, or right-click it and choose Delete from the context menu.

You can change the order of the fields by dragging individual items within the Fields list.

When you select an item in the Fields list, the other controls on the page display the properties of the selected field. The topmost controls are three option buttons representing the three kinds of fields supported by True DataControl:

Data | Data field values are stored directly in the underlying data source. In data source mode, a data field corresponds to a field in the SourceRecordset. Data fields can also reside in memory (in memory array mode) or be supplied by code (in user events mode).
Calculated | Calculated field values are not stored in a database. They are evaluated at run time based upon the CalculatedExpression property. You can also supply values in code using the CalcFields event.
Linked | Linked fields are used to specify a one-to-one relationship between the field in a master TData control and the field of a dependent TData control.

The controls below the option buttons define the properties of the selected field. Depending upon the kind of field, selected DataMode and other settings; some of these controls may not be available.

Name | Specifies the name of the field.
DataSourceField | Specifies the name of the SourceRecordset field from which this True DataControl field is derived. It only has sense for data fields in data source mode. For a linked field, the Linked Field combo box appears instead of Data Source Field.
LinkedField | For a linked field, determines (together with LinkedControl) the name of a field in the LinkedControl (a dependent TData control), to which the field is linked. The Linked Field combo box (appearing only for linked fields, instead of DataSource Field) contains all possible fields in dependents to which a linked field can be linked. The items contain both control name and field name, dot-separated. You must select one of the available items.
DisplayName | Specifies a user-friendly name, under which the field appears in the Find Dialog.
Visible | Determines whether the field is exposed to data-aware controls.
ReadOnly | Determines whether the field can be modified by the end-user.
Searchable | Determines whether the field is included in the Find Dialog.
MaxLength | For string fields only, this setting specifies the maximum number of characters the field can contain.
ModificationMode | Determines how the TData control reacts to changes in the field’s value caused by end-user interaction.
CalculatedExpression | Specifies the expression used to calculate the field's value for calculated fields, and sometimes for data fields.
CalcConditionExpression | Represented by the Condition edit box beside Calculated Expression. Specifies a boolean expression that determines whether the associated calculated expression should be evaluated.
DefaultExpression | Specifies the default value to be assigned to this field in a newly added record.
QueryMode | Specifies whether the field should appear only in query mode, only in result mode, or in both modes.
QueryOperation | Specifies the comparison operation used with the field generating the query filter condition in query mode.

In addition to these field properties, you can define one or more range conditions and constraints for each field. For more information, see Field Range Conditions and Field Constraints. To do this, click the New button and select New Range Condition or New Constraint from the button's context menu. Alternatively, you can right-click the Fields list and choose either command from the list's context menu. To remove a range condition or a constraint from the list, select it and click the Delete button, or right-click it and choose Delete from the context menu. Note: Range conditions are unavailable in True DataControl Lite.

Each range condition and each constraint is represented as a child node of the associated field within the Fields list. When you select one of these child nodes, the field property controls described earlier are replaced with controls representing either the range condition or constraint properties, depending upon the selection.

If multiple range conditions are defined, they work as if they were connected by a logical AND operator. The same holds true for field-level constraints.

For range conditions, the following controls are displayed. See Field Range Conditions for details.

ComparisonOperation | Specifies the type of comparison. Allowable values are <, <=, <>, =, >=, >, and also starts with and contains (string fields only). The default value is = (equals).
SkipIfEmpty | Specifies how to handle the range condition when a variable contained within the ValueExpression is empty.
ValueExpression | Specifies the operand to be used for comparison. The resulting range condition is the field op value, where field is the data field that owns this range condition, op is the selected comparison operator, and value is the result of this expression.
ConditionExpression | Represented by the Condition edit box beside Value Expression. Specifies an optional boolean expression controlling the applicability of this range condition. If this expression is not empty and evaluates to False, the entire range condition will be ignored.

For constraints, the following controls are displayed. See Field Constraints for details.

ConstraintExpression | Specifies a boolean expression that determines validity of field modification.
ConditionExpression | Represented by the Condition edit box beside Constraint Expression. Specifies an optional boolean expression controlling the applicability of the constraint. If this expression is not empty and evaluates to False, the entire constraint will be ignored.
MessageExpression | Specifies a string expression that determines the error message to be displayed when a constraint violation occurs.


Filters Page

The Filters page is used to maintain the FilterExpressions collection. Use the FilterExpression property to access the FilterExpressions collection in code.

Filter expressions restrict the set of records retrieved to the Recordset. For each fetched record, the TData control evaluates each filter expression and excludes the record from the resulting recordset if the filter expression evaluates to False. See Filters for details.

If multiple filter expressions are defined, they work as if they were connected by a logical AND operator.

IMPORTANT: Do not forget that filter expressions are only evaluated if the Filtered property of the TData control is True. To enable filters, check the box labeled Filtered on the General property page or set the Filtered property in code.

The Filters page is initially empty. Click the New button to create an uninitialized filter and enable the other controls on the page. Alternatively, you can right-click the Filters list and choose New from the context menu.

To remove a filter from the list, select it and click the Delete button, or right-click it and choose Delete from the context menu. You can change the evaluation order of the filters by dragging individual items within the Filters list.

When you select an item in the Filters list, the other controls on the page display the attributes of the selected filter:

FilterExpression

Specifies a boolean expression that will be evaluated once per record to filter the recordset.

ConditionExpression

Represented by the Condition edit box beside Filter Expression. Specifies an optional boolean expression that will be evaluated once per record to determine whether the associated filter expression should be evaluated at all. If the condition expression is empty or evaluates to True, the filter expression will be evaluated; if the condition expression evaluates to False, the filter expression will not be evaluated.

NOTE: Neither expression will be evaluated if the Filtered property of the control is False.


Property Expressions Page

The Property Expressions page is used to maintain the PropertyExpressions collection. Use the PropertyExpressions property to access the PropertyExpressions collection in code.

True DataControl provides you with a powerful feature: you can associate expressions with any property of any control belonging to the parent form of the TData control. This allows you to make True DataControl maintain control property values automatically, without writing any code. See Control Property Expressions for details.

To create a new entry in the Control Properties list, expand the name of the desired control in the Available Controls list, then select the property you want to create an expression for. Alternatively, you can type the fully qualified property name (such as Label1.Font.Bold) into the Property box. After you have specified the property, click the New button, or right-click the Control Properties list and choose New from the context menu. Then you can type the desired expression in the Value Expression box, or create the expression in the Expression Editor.

To remove a control property from the list, select it and click the Delete button, or right-click it and choose Delete from the context menu. You can change the evaluation order of the control properties by dragging individual items within the Control Properties list.

When you select an item in the Control Properties list, the other controls on the page display the properties of the selected property expression:

Property

This edit box represents two properties of a PropertyExpression object: ControlName and PropertyName. Together they form a fully qualified property name starting with a control name, such as Label1.BackColor. Nested properties such as Label1.Font.Bold are also supported. You can select a node in the Available Controls tree view, that will fill the Property edit box with a full property name. Or you can type a fully qualified property name in this edit box manually.

ValueExpression

Specifies an expression that provides the value for the associated property at run time.


Constraints Page

The Constraints page is used to maintain the Constraints collection. Use the Constraints property to access the Constraints collection in code.

These are record-level constraints. Unlike field-level constraints, record-level constraints impose restrictions on the record as a whole. See more about record-level constraints in Validation and Constraints.

If multiple constraint expressions are defined, they work as if they were connected by a logical AND operator.

The Constraints page is initially empty. Click the New button to create an uninitialized constraint and enable the other controls on the page. Alternatively, you can right-click the Constraints list and choose New from the context menu. To remove a constraint from the list, select it and click the Delete button, or right-click it and choose Delete from the context menu. You can change the evaluation order of the constraints by dragging individual items within the Constraints list.

When you select an item in the Constraints list, the other controls on the page display the attributes of the selected constraint:

ConstraintExpression

Specifies a boolean expression that determines the validity of a modified record. If the constraint expression evaluates to False, record modification is not allowed.

ConditionExpression

Represented by the Condition edit box beside Constraint Expression. Specifies an optional boolean expression controlling the applicability of the constraint. If this expression is not empty and evaluates to False, the entire constraint will be ignored.

MessageExpression

Specifies a string expression that determines the error message to be displayed when a constraint violation occurs. If you leave this property blank, the TData control displays a generic "Constraint violation" message.


Crosstab Page

The Crosstab page is used to set crosstab-related properties. It is only available starting from version 7.0, including True DataControl Lite 7.0. See Crosstab (matrix) data presentation for details on the crosstab feature.

The Crosstab page allwos you to specify properties essential for crosstab functionality (see Crosstab (matrix) data presentation for more information):

XTab | Crosstab mode is enabled if this property is True (check box checked), otherwise it is disabled.
XTabSeparateFields | If this property is True (check box checked), crosstab columns are exposed to data bound controls as separate fields, so their settings can be specified separately. If this property is False (check box unchecked; default), all crosstab coluns represented by a crosstab field are exposed as a single field, to facilitate design time settings, which are usually identical for columns representing the same field.
XTabCollate | If there are multiple crosstab fields, this property specifies one of the two layout options: If it is False (check box unchecked; default), the crosstab columns generated by different fields are interspersed. If it is True (check box checked), the columns will be grouped by the main field.
XTabRowKey | Field or list of fields constituting the row key, fields whose values define crosstab rows.
XTabColKey | Field or list of fields constituting the column key, fields whose values define crosstab columns.
XtabColumns | This is a field property. To specify it, select a field in the list on the left-hand side of the page. Setting this property makes the field a crosstab field and defines crosstab columns generated by the field. See Crosstab (matrix) data presentation for more information.


True DataControl 8.0 Reference

Constraint Object

Constraints Collection

Field Object All Members

Fields Collection

FilterExpression Object

FilterExpressions Collection

NamedBookmark Object

NamedBookmarks Collection

Parameter Object

Parameters Collection

PropertyExpression Object

PropertyExpressions Collection

RangeCondition Object

RangeConditions Collection

RowBuffer Object


Constraint Object

All of the properties and methods for the Constraint object are listed in the following tables.


Constraint Object All Members

Constraint Object Properties

ConditionExpression | Condition determining whether the constraint should be applied.
ConstraintExpression | Specifies the expression used to test a constraint.
MessageExpression | Specifies the expression evaluating to the message text that is shown when a constraint is not satisfied.


Constraint Object Properties


ConditionExpression Property (Constraint)

Condition determining whether the constraint should be applied.

Syntax

Constraint.ConditionExpression = variant

Remarks

Read/Write at run time and design time. Property applies to Constraint object.

This property specifies the applicability expression for a constraint.

If this expression is empty or evaluates to False, the constraint is skipped.

If this expression evaluates to True, the constraint is tested.

See Validation and Constraints for more information on constraints.

See True DataControl Expressions for more information about expressions in general.

See Also

Constraint Object


ConstraintExpression Property (Constraint)

Specifies the expression used to test a constraint.

Syntax

Constraint.ConstraintExpression = variant

Remarks

Read/Write at run time and design time. Property applies to Constraint object.

This property specifies the constraint expression that is evaluated to test a constraint. If it evaluates to True, the constraint is satisfied, otherwise it is not.

See Validation and Constraints for more information on constraints.

See True DataControl Expressions for more information about expressions in general. Evaluation rules for ConstraintExpression are as follows:

Expression Level: Record level

Synchronous Evaluation: For field-level constraints, evaluated before the field is modified. For record-level constraints, evaluated before the modified record is posted to the database, or before the TData control is repositioned to a different record.

Asynchronous Evaluation: No action.

See Also

Constraint Object


MessageExpression Property (Constraint)

Specifies the expression evaluating to the message text that is shown when a constraint is not satisfied.

Syntax

Constraint.MessageExpression = variant

Remarks

Read/Write at run time and design time. Property applies to Constraint object.

When a constraint check fails (ConstraintExpression evaluates to False), this expression determines the message text describing the reason of the failure. The MessageExpression is evaluated and the result is used as the error message text. It is first passed as the Description argument to the Error event. If the Error event procedure does not cancel the message, the text appears in the standard error message box.

If this expression is empty or evaluates to empty string, TData displays a generic “Constraint violation” message.

See Validation and Constraints for more information on constraints.

See True DataControl Expressions for more information about expressions in general. Evaluation rules for MessageExpression are as follows:

Expression Level: Record level

Synchronous Evaluation: Evaluated on constraint violation, before the Error event is fired.

Asynchronous Evaluation: No action.

See Also

Constraint Object


Constraints Collection

All of the properties and methods for the Constraints collection are listed in the following tables.


Constraints Collection All Members

Constraints Collection Properties

Count | Returns the number of items in a collection.
Item | Returns a single collection item.

Constraints Collection Methods

Add | Adds a new item to the collection.
Remove | Removes an existing item from the collection.


Constraints Collection Properties


Count Property (Constraints)

Returns the number of items in a collection.

Syntax

collection.Count

Remarks

Read-only at run time. Not available at design time. Property applies to NamedBookmarks, Constraints, Fields, FilterExpressions, Parameters, PropertyExpressions, and RangeConditions collections.

This property returns the number of items in a collection.

Collections are zero-based, which means that the items in a collection are indexed from 0 to Count - 1.

See Also

Constraints Collection


Item Property (Constraints)

Returns a single collection item.

Syntax

collection.Item (index)

Remarks

Property applies to Constraints, Fields, FilterExpressions, NamedBookmarks, Parameters, PropertyExpressions, and RangeConditions collections.

Arguments: index is an expression that specifies the collection member to be accessed.

Return Value: A reference to the specified object.

Use the Item method to access a specific member of a True DataControl collection. All collections accept a zero-based index argument. The Fields and Parameters collections also accept name as an index.

Note: The Item property is not required. The following expressions are equivalent:

TData1.Fields(0)

TData1.Fields.Item(0)

See Also

Constraints Collection


Constraints Collection Methods


Add Method (Constraints)

Adds a new item to the collection.

Syntax

collection.Add (Index)

Remarks

Method applies to NamedBookmarks, Constraints, Fields, FilterExpressions, Parameters, PropertyExpressions, and RangeConditions collections.

Arguments: Index is the integer ordinal position in the collection on which to place the newly created object.

Return Value: A reference to the newly created object.

This method creates a new instance of the appropriate object, adds it to the collection, and returns it to the caller.

The newly created object’s properties have default values that you need to set in order to make the object useful. The newly created object is placed on the Index position in the collection, and all other items with collection indexes greater than or equal to Index are shifted up by 1 to create the place for the newly inserted item.

If Index is greater than or equal to Count (the number of items already in the collection), the new object is appended to the end of the collection.

See Also

Constraints Collection


Remove Method (Constraints)

Removes an existing item from the collection.

Syntax

collection.Remove (Index)

Remarks

Method applies to NamedBookmarks, Constraints, Fields, FilterExpressions, Parameters, PropertyExpressions, and RangeConditions collections.

Arguments: Index is an index in the collection. It can either be the name of an item in the collection (only for Fields and Parameters collections), or an integer ordinal position in the collection.

Return Value: None

Use the Remove method to delete a specific member of a TData control collection.

All collections accept a zero-based integer Index argument. The Fields and Parameters collections also accept the name of an object as the Index argument.

See Also

Constraints Collection


Field Object All Members

All of the properties and methods for the Field object are listed in the following tables.


Field Object All Members

Field Object Properties

CalcConditionExpression | Condition determining whether the field’s calculated expression should be evaluated.
CalculatedExpression | Specifies the expression used to calculate field values.
Constraints | Returns the collection of field constraints.
DataSourceField | Sets/returns database field name for a field.
DataSourceReadOnly | Returns whether a data field is read-only in the underlying database.
DataSourceRequired | Returns whether a data field is mandatory (can't be left empty) in the underlying database.
DataSourceType | Returns the original data type of a data field in the underlying database.
DefaultExpression | Specifies the expression used to calculate default field values on adding a new row.
DisplayName | Returns/sets the user-friendly name of a field in the Find dialog.
Exists | Returns whether a field's DataSourceField:Field exists in the database.
FieldKind | Sets/returns the field kind (data, calculated or linked).
LinkedControl | Specifies the linked control to whose field the field is linked.
LinkedField | Specifies the field within a linked control to which this field is linked.
MaxLength | Sets/returns the maximum length of data accepted by a field.
ModificationMode | Specifies the control's behavior on end-user changes made to a control bound to the field.
Name | Sets/returns field name.
QueryMode | Specifies whether a field appears in query mode, datasource mode or both.
QueryOperation | Specifies a comparison operation applied to a field in query mode.
RangeConditions | Returns the collection of range conditions for a field.
ReadOnly | Sets/returns whether a field can be modified.
Required | Sets/returns whether a field is mandatory, should not be left empty on data modification.
Searchable | Specifies whether the field appears in the Find dialog.
Type | Sets/returns field data type.
Value | Sets/returns field value.
Visible | Sets/returns whether a field is exposed to data consumers.
XTabColDef | For a crosstab column (field instance), returns the name of the design-time field from which it was generated.
XtabColumns | For crosstab fields, list of key values and column names defining columns (fields) generated by the crosstab field.


Field Object Properties

CalcConditionExpression Property

CalculatedExpression Property

Constraints Property (Field)

DataSourceField Property (Field)

DataSourceReadOnly Property

DataSourceRequired Property

DataSourceType Property

DefaultExpression Property

DisplayName Property (Field)

Exists Property

FieldKind Property

LinkedControl Property

LinkedField Property

MaxLength Property

ModificationMode Property

Name Property

QueryMode Property (Field)

QueryOperation Property

RangeConditions Property

ReadOnly Property

Required Property

Searchable Property

Type Property (Field)

Value Property (Field)

Visible Property (Field)

XTabColDef Property

XTabColumns Property (Field)


CalcConditionExpression Property

Condition determining whether the field’s calculated expression should be evaluated.

Syntax

Field.CalcConditionExpression = variant

Remarks

Read/Write at run time and design time. Property applies to Field object.

This property specifies the applicability expression for the CalculatedExpression of a field; it determines whether the associated calculated expression should be evaluated.

If this expression is empty or evaluates to True, the calculated expression will be evaluated.

If this expression evaluates to False, the calculated expression will not be evaluated.

The CalcConditionExpression property is generally used with data fields that have a non-empty CalculatedExpression. There is not much sense for a data field to have a non-empty CalculatedExpression and an empty CalcConditionExpression, because then it would be just like a calculated field (sometimes it might be useful though, for storing modified values). CalculatedExpression may be used, for example, to initialize an empty data field with the value of another field that has just been modified. For instance, to initialize the value of the BillTo field with the value of the ShipTo field when the latter has just been entered, you would set the former's CalculatedExpression to ShipTo, and its associated CalcConditionExpression to IsEmpty(BillTo).

See True DataControl Fields for information about data fields and calculated fields. See True DataControl Expressions for general information about expressions.

See Also

Field Object


CalculatedExpression Property

Specifies the expression used to calculate field values.

Syntax

Field.CalculatedExpression = variant

Remarks

Read/Write at run time and design time. Property applies to Field object.

This property specifies the expression used to calculate the field's value. It is normally used for calculated fields, but data fields can also have calculated expressions, in which case the field's value changes whenever one of the fields referenced in the expression changes.

If your algorithm for calculating fields is too complex to be represented by expressions, you can use the CalcFields event to determine the values of calculated fields.

See True DataControl Fields for information about data fields and calculated fields. See True DataControl Expressions for general information about expressions. Evaluation rules for CalculatedExpression are as follows:

Expression Level: Record level

Synchronous Evaluation: Evaluated after a record has been fetched from the database.

Asynchronous Evaluation: Updates the field value.

This property has associated applicability condition in the CalcConditionExpression.

See Also

Field Object


Constraints Property (Field)

Returns the collection of field constraints.

Syntax

Field.Constraints

Remarks

Read-only at run time. Not available at design time. Property applies to Field object.

This property returns a collection of Constraint objects, field-level constraints defined for a particular field. See Validation and Constraints for details.

See Also

Field Object


DataSourceField Property (Field)

Sets/returns database field name for a field.

Syntax

Field.DataSourceField = string

Remarks

Read/Write at run time and design time. Property applies to Field object.

This property specifies the name of the SourceRecordset field from which the TData control field is derived. It only relevant for data fields (not calculated or linked fields) in data source mode (DataMode = 0 – DataSource).

When data fields are created by retrieving fields from a data source (using the Retrieve Fields button on the Fields page or the Retrieve Fields context menu item), this property is filled with the name of the corresponding data source field (the Name property gets the same value). You can change this property later, although it is rarely needed.

If you create a new data field at design time or in code, you must set its DataSourceField property. Data fields whose DataSourceField property does not correspond to any field in the data source are ignored; they do not show up in the TData Recordset.

For more information, see True DataControl Fields.

See Also

Field Object


DataSourceReadOnly Property

Returns whether a data field is read-only in the underlying database.

Syntax

Field.DataSourceReadOnly

Remarks

Read-only at run time. Not available at design time. Type: Boolean.
Property applies to Field object.

For a data field in data source mode (DataMode = 0 – DataSource), this property returns True if the corresponding field is read-only in the underlying data source (database). In this case, the field’s ReadOnly property always returns True and cannot be changed.

The DataSourceField property returns False in all other cases.

For more information, see True DataControl Fields.

See Also

Field Object


DataSourceRequired Property

Returns whether a data field is mandatory (can't be left empty) in the underlying database.

Syntax

Field.DataSourceRequired

Remarks

Read-only at run time. Not available at design time. Type: Boolean. Property applies to Field object.

For a data field in data source mode (DataMode = 0 – DataSource), this property returns True if the corresponding field is required (cannot be set to Null in a modified or new record) in the underlying data source (database).

The DataSourceRequired property returns False in all other cases.

For more information, see True DataControl Fields.

See Also

Field Object


DataSourceType Property

Returns the original data type of a data field in the underlying database.

Syntax

Field.DataSourceType = long

Remarks

Read/Write at run time. Not available at design time. Property applies to Field object.

This property is intended for advanced users, it rarely needs to be set to anything other than the default.

It indicates the ADO/OLE DB data type of the field as it is exposed to the clients, the bound controls. Its value is one of the types listed in the ADO DataTypeEnum. ADO/OLE DB types include variant data types allowed for TData control fields (see Type property), and contain some additional types. For example, ADO has several types corresponding to the date type (tdbTypeDate): adDate, adDBDate, adDBTime and adDBTimeStamp. They are all date/time types, but have some subtle differences.

By default, for data fields in data source mode (DataMode = 0 – DataSource), this property is set to the ADO/OLE DB type of the corresponding data source field. This type can be different from Type, as the example with date types shows. For all four types in the example the Type is set to tdbTypeDate.

For all other kinds of TData control fields, the default value of DataSourceType is the Type property value.

Bound controls see the field’s DataSourceType as the true type of the field. The ADO type of a field in TData.Recordset.Fields is also determined by the DataSourceType property. You can set the DataSourceType property to a certain ADO/OLE DB type and thus make the field appear to the clients as having the specified type, in case you need a specific type not supported by the Type property.

See ADO documentation for details on the ADO/OLE DB data types, ADO Field.Type property and DataTypeEnum constants.

See Also

Field Object


DefaultExpression Property

Specifies the expression used to calculate default field values on adding a new row.

Syntax

Field.DefaultExpression = variant

Remarks

Read/Write at run time and design time. Property applies to Field object.

This property determines the default value to be assigned to the field in a newly added record. When a new record is added to the Recordset, this expression is evaluated for every data field where it is not empty, and all such fields receive the default values obtained from the DefaultExpression evaluation. After this is done, the TData control evaluates calculated fields.

This expression belongs to the recordset level, meaning it can’t use field values, only constants, parameters and variables of the Master control if there is a master-detail relationship.

See True DataControl Fields for more information on fields.

See True DataControl Expressions for more information about expressions in general. Evaluation rules for DefaultExpression are as follows:

Expression Level: Recordset level

Synchronous Evaluation: Evaluated after a new record has been added to the recordset, before evaluating calculated fields.

Asynchronous Evaluation: No action.

See Also

Field Object


DisplayName Property (Field)

Returns/sets the user-friendly name of a field in the Find dialog.

Syntax

Field.DisplayName = string

Remarks

Read/Write at run time and design time. Property applies to Field object.

This property specifies the user-friendly name of the field. By default, its value is equal to that of the Name property. But the Name has to obey strict rules, because it is used to identify the field in True DataControl expressions where only correct identifiers are allowed. For example, Name can’t contain spaces. The DisplayName property allows you to specify a separate name for user interface purposes.

In the current TData control version, the DisplayName property is used for the sole purpose of customizing field names appearing in the Find Dialog. Future versions can use it in other contexts, so it is a good idea to specify DisplayName for fields whose names are not self-explanatory.

See Also

Field Object


Exists Property

Returns whether a field's DataSourceField:Field exists in the database.

Syntax

Field.Exists

Remarks

Read-only at run time. Not available at design time. Type: Boolean. Property applies to Field object.

This property indicates if the field is ignored, and excluded from the recordset.

It is only relevant in data source mode (DataMode = 0 – DataSource), and is read-only, intended solely for information purposes.

For a data field, Exists = False means that the field’s DataSourceField property contains a name that does not correspond to any field in the data source. Such fields are ignored, excluded from the Recordset. In all other cases, Exists = True.

See True DataControl Fields for more information.

See Also

Field Object


FieldKind Property

Sets/returns the field kind (data, calculated or linked).

Syntax

Field.FieldKind = value

Remarks

Read/Write at run time and design time. Property applies to Field control.

Design Time | Run Time
0 - Data | tdbDataField
1 - Calculated | tdbCalculatedField
2 - Linked | tdbLinkedField

This property determines whether the field is:

A data field, stored in the data source

A calculated field, not stored in the data source

A linked field, corresponding to a field in a TData control linked to this control in a one-to-one relationship

See Three kinds of fields for details.

See Also

Field Object


LinkedControl Property

Specifies the linked control to whose field the field is linked.

Syntax

Field.LinkedControl = string

Remarks

Read/Write at design time and at run time. Property applies to Field object.

This property works together with the LinkedField property. It is only relevant for linked fields (FieldKind = 2 – Linked).

It specifies the name of a TData control that is linked to another TData control via a common linked field.

Example: Suppose the TDataCustomers control is linked to the TDataOrders control. The TDataOrders control has a field CustomerName, which represents the TDataCustomers.CustomerName field. Then TDataOrders.CustomerName is a linked field, and it is linked to TDataCustomers.CustomerName. This is specified by the LinkedControl and LinkedField properties in the following way:

TDataOrders.Fields(“CustomerName”).FieldKind = tdbLinkedField

TDataOrders.Fields(“CustomerName”).LinkedControl = “TDataCustomers”

TDataOrders.Fields(“CustomerName”).LinkedField = “CustomerName”

For more information, see One-to-One Links.

See Also

Field Object


LinkedField Property

Specifies the field within a linked control to which this field is linked.

Syntax

Field.LinkedField = string

Remarks

Read/Write at design time and at run time. Property applies to Field object.

This property works together with the LinkedControl property. It is only relevant for linked fields (FieldKind = 2 – Linked).

The field is considered linked to the linked control’s field as defined by the LinkedField property. This effectively means that the field from the dependent control appears in the master control’s Recordset. The LinkedField property specifies the name of a field in the dependent (linked) TData control.

Example: Suppose the TDataCustomers control is linked to the TDataOrders control. The TDataOrders control has a field CustomerName, which represents the TDataCustomers.CustomerName field. Then TDataOrders.CustomerName is a linked field, and it is linked to TDataCustomers.CustomerName. This is specified by the LinkedControl and LinkedField properties in the following way:

TDataOrders.Fields(“CustomerName”).FieldKind = tdbLinkedField

TDataOrders.Fields(“CustomerName”).LinkedControl = “TDataCustomers”

TDataOrders.Fields(“CustomerName”).LinkedField = “CustomerName”

For more information, see One-to-One Links.

See Also

Field Object


MaxLength Property

Sets/returns the maximum length of data accepted by a field.

Syntax

Field.MaxLength = long

Remarks

Read/Write at run time and design time. Property applies to Field object.

This property indicates the maximum number of characters allowed for string field values. It is only relevant for string fields (Type = 8 – String).

For data fields (FieldKind = 0 – Data) in data source mode (DataMode = 0 – DataSource), MaxLength is determined by the data source and cannot be changed. For other fields, it can be set to restrict the length of allowed field values.

If the MaxLength property is set to 0, or to inverse zero (the negative long integer with all bits equal to 1), the length of field values is unrestricted. This is the default value of the MaxLength property.

See Also

Field Object


ModificationMode Property

Specifies the control's behavior on end-user changes made to a control bound to the field.

Syntax

Field.ModificationMode = value

Remarks

Read/Write at run time and design time. Property applies to Field object. Not available in True DataControl Lite.

Design Time | Run Time
0 – None | tdbModifModeNone
1 – Immediate | tdbModifModeImmediate
2 – Leaving control (default) | tdbModifModeOnControlExit

This property determines how the TData control reacts to changes in the field’s value that are caused by end-user interaction.

When set to 0 – None, the TData control does nothing, deferring to the container (Visual Basic) to decide when the field should be updated.

The 1 – Immediate setting triggers an instant field update for every change that occurs in a bound control, even for individual keystrokes.

The default setting, 2 – Leaving control, triggers field updates when the bound control loses focus, or when the current cell position in a bound grid changes.

For more information, see Field Modification Modes.

See Also

Field Object


Name Property

Sets/returns field name.

Syntax

Field.Name = string

Remarks

Read/Write at run time and design time. Property applies to Field object.

This property specifies the name of a field. This must be a unique (case-insensitive) name that identifies the field in TData control expressions and in the TData control Recordset. It also serves as an index to the Fields collection returned by the Fields property. The default name for a newly added field is FIELD_number, where number is the lowest integer that would yield a unique name.

Note: In order to be used directly in TData expressions, a field’s name must be a proper identifier, that is, it must begin with a letter and contain only letters, digits, and underscores. If you have a field with spaces or other non-identifier characters, you can use the Field() function in expressions, for example, Field(“A very important field”). The Field() function returns the value of the field whose Name is specified as the function argument.

See Also

Field Object


QueryMode Property (Field)

Specifies whether a field appears in query mode, datasource mode or both.

Syntax

Field.QueryMode = value

Remarks

Read/Write at run time and design time. Property applies to Field object.

Design Time | Run Time
0 – Both (default) | tdbQueryAndDataSource
1 – Query only | tdbQueryOnly
2 – DataSource only | tdbDataSourceOnly

property specifies whether the field should appear only in query mode, only in result mode, or in both modes.

If set to 0 – Both, the field is visible regardless of the TData.QueryMode setting.

If set to 1 – Query only, the field is visible only when TData.QueryMode = True.

If set to 2 – DataSource only, the field is visible only when TData.QueryMode = False.

For more information, see Query Mode.

See Also

Field Object


QueryOperation Property

Specifies a comparison operation applied to a field in query mode.

Syntax

Field.QueryOperation = value

Remarks

Read/Write at run time and design time. Property applies to Field object.

Design Time | Run Time
0 - < | tdbLessThan
1 - <= | tdbLessThanOrEqual
2 - = (default) | tdbEqual
3 - >= | tdbGreaterThanOrEqual
4 - > | tdbGreaterThan
5 – starts with | tdbStartsWith
6 – contains | tdbContains

This property specifies the comparison operation used with the field, when the TData control generates the QueryFilter condition in query mode.

For more information, see Query Mode.

See Also

Field Object


RangeConditions Property

Returns the collection of range conditions for a field.

Syntax

Field.RangeConditions

Remarks

Read-only at run time. Not available at design time. Property applies to Field object. Not available in True DataControl Lite.

This property returns a collection of RangeCondition objects. Each object in the collection defines a range condition for the field. See Field Range Conditions for details.

See Also

Field Object


ReadOnly Property

Sets/returns whether a field can be modified.

Syntax

Field.ReadOnly = boolean

Remarks

Read/Write at run time and design time. Property applies to Field object.

This property determines whether the field can be modified by the end-user.

The default value is False, which means that the field may be edited.

If set to True, the end-user cannot modify the field, but its value can still be changed in code or by evaluation of a TData control expression.

In data source mode, if a data field is read-only in the data source, its DataSourceReadOnly and ReadOnly properties are set to True and cannot be changed.

For more information, see True DataControl Fields.

See Also

Field Object


Required Property

Sets/returns whether a field is mandatory, should not be left empty on data modification.

Syntax

Field.Required = boolean

Remarks

Read/Write at run time and design time. Property applies to Field object.

This property determines whether the field must be assigned an actual value when records are updated or added.

The default value is False, which means that a value need not be specified.

If set to True, an attempt to empty the field, or to update or add a record with this field empty will result in an error message.

For more information, see True DataControl Fields.

See Also

Field Object


Searchable Property

Specifies whether the field appears in the Find dialog.

Syntax

Field.Searchable = boolean

Remarks

Read/Write at run time and design time. Property applies to Field object.

This property determines whether the field is included in the Find Dialog.

If set to True, the field is included in the Find in Field combo box.

If set to False, the field is excluded.

See Also

Field Object


Type Property (Field)

Sets/returns field data type.

Syntax

Field.Type = value

Remarks

Read/Write at run time and design time. Property applies to Field object.

Design Time | Run Time
11 – Boolean | tdbTypeBoolean
16 – Byte | tdbTypeByte
6 – Currency | tdbTypeCurrency
7 – Date | tdbTypeDate
5 – Double | tdbTypeDouble
2 – Integer | tdbTypeInteger
3 – Long | tdbTypeLong
4 – Single | tdbTypeSingle
8 – String (default) | tdbTypeString
12 – Variant | tdbTypeVariant

This property determines the variant data type of the field.

For data fields in data source mode, and for linked fields in any mode, the value is derived from the underlying data source, so this property cannot be changed.

For other fields, that is, for calculated fields and data fields in memory array and user events mode, the programmer must specify the field data type.

See True DataControl Fields for details.

See Also

Field Object


Value Property (Field)

Sets/returns field value.

Syntax

Field.Value = variant

Remarks

Read/Write at run time. Not available at design time. Property applies to Field object.

This property is used to get/set the field value.

Setting field value in code involves field validation and triggers the WillChangeField and FieldChangeComplete events. For more information, see Validation and Constraints.

See True DataControl Fields for more information.

Note: This property is the default (implicit) property of the Field object, so it can be omitted in Visual Basic code.

See Also

Field Object


Visible Property (Field)

Sets/returns whether a field is exposed to data consumers.

Syntax

Field.Visible = boolean

Remarks

Read/Write at run time and design time. Property applies to Field object.

This property determines whether the field is exposed to data-aware controls.

If set to True (default), the field is included in the Recordset and exposed to the bound controls and other clients.

If set to False, the field is hidden from bound controls and other clients and excluded from Recordset. It still can be used by the TData control and all its dependent TData controls internally, in expressions and in the collection returned by the Fields property.

For more information, see True DataControl Fields.

See Also

Field Object


XTabColDef Property

For a crosstab column (field instance), returns the name of the design-time field from which it was generated.

Syntax

Field.XTabColDef

Remarks

Read-only at run time. Unavailable at design time. Type: String. Property applies to Field object, starting from version 7.0.

This property applies to crosstab mode. For a crosstab column (field instance), it returns the name of the design-time field from which it was generated.

In crosstab mode, a single TData field defined at design time can generate multiple fields (crosstab columns) at run time. Such fields are called crosstab fields. This property allows to find out at run time, whether a field is a crosstab column (if it is not, the property returns empty string) and which crosstab field it belongs to.

For more information, see Crosstab (matrix) data presentation.

See Also

Field Object


XTabColumns Property (Field)

For crosstab fields, list of key values and column names defining columns (fields) generated by the crosstab field.

Syntax

Field.XTabColumns = string

Remarks

Read/Write at design time and at run time. Property applies to TData control and TDataLiteconotrol starting from version 7.0.

This property applies to crosstab mode. Setting it to a non-empty string, you define a fields as a crosstab field. The property values must obey special syntax rules allowing to specify a list of crosstab values. Every value in the list generates a column (a special field, so called crosstab column) at run time, with a name also specified in the list.

An XtabColumns string consists of column definitions separated with semicolons. Each column definition has a key expression and a column name:

<key expression>:<column name>

<key expression> is a valid TData expression. Usually, it is just a constant. Don’t forget to enclose it in double quotes if it is a string expression.

<column name> is a string defining the name of the crosstab column. You don’t have to double quote field names.

If you have multiple column key fields, the column definition syntax is slightly different. You must supply a valid TData expression (usually, constant) for every column key field, and separate them with colons:

<key expression1>,…,<key expressionN>:<column name>

Example of a single column key field, Month:

1:Jan;2:Feb;3:Mar;4:Apr;5:May;6:Jun;7:Jul;8:Aug;9:Sep;10:Oct;11:Nov;12:Dec

Example of multiple column key fields, Country,Year:

“US”,1999:U.S. 1999;”US”,2000:U.S. 2000;”Canada”,1999:Canada 1999; ”Canada”,2000:Canada 2000

Notice double quotes in constant key expression (you always must enclose constant string expressions in double or single quotes) and the absence of quotes in the column name (it is not an expression, just a string).

For more information, see Crosstab (matrix) data presentation.

See Also

Field Object


Fields Collection

All of the properties and methods for the Constraints collection are listed in the following tables.


Fields Collection All Members

Fields Collection Properties

Count | Returns the number of items in a collection.
Item | Returns a single collection item.

Fields Collection Methods

Add | Adds a new item to the collection.
Remove | Removes an existing item from the collection.


Fields Collection Properties


Count Property (Fields)

See Count Property (Constraints).


Item Property (Fields)

See Item Property (Constraints).


Fields Collection Methods


Add Method (Fields)

See Add Method (Constraints).


Remove Method (Fields)

See Remove Method (Constraints).


FilterExpression Object

All of the properties and methods for the FilterExpression object are listed in the following tables.


FilterExpression Object All Members

FilterExpression Object Properties

ConditionExpression | Specifies whether the filter expression is applied or skipped.
FilterExpression | Specifies the expression that has to evaluate to True for a record to be included in the recordset.


FilterExpression Object Properties


ConditionExpression Property (FilterExpression)

See ConditionExpression Property (Constraint).


FilterExpression Property (FilterExpression)

Specifies the expression that has to evaluate to True for a record to be included in the recordset.

Syntax

FilterExpression.FilterExpression = variant

Remarks

Read/Write at run time and design time. Property applies to FilterExpression object.

This property specifies the filter expression that is evaluated to test a filter.

If it evaluates to True and other filter conditions are also satisfied, the record is included in the Recordset.

If it evaluates to False, the record is excluded from the Recordset.

See Filters for more information.

See True DataControl Expressions for more information about expressions in general. Evaluation rules for FilterExpression are as follows:

Expression Level: Record level

Synchronous Evaluation: Evaluated after a record has been fetched from the database and all calculated expressions have been evaluated.

Asynchronous Evaluation: Action depends on the variable whose change triggers the asynchronous evaluation. It forces refresh of the TData control unless the changed variable is a field (not a parameter) belonging to this control. Changes to parameters or ancestor fields force refresh.

See Also

FilterExpression Object


FilterExpressions Collection

All of the properties and methods for the FilterExpressions collection are listed in the following tables.


FilterExpressions Collection All Members

FilterExpressions Collection Properties

Count | Returns the number of items in a collection.
Item | Returns a single collection item.

FilterExpressions Collection Methods

Add | Adds a new item to the collection.
Remove | Removes an existing item from the collection.


FilterExpressions Collection Properties


Count Property (FilterExpressions)

See Count Property (Constraints).


Item Property (FilterExpressions)

See Item Property (Constraints).


FilterExpressions Collection Methods


Add Method (FilterExpressions)

See Add Method (Constraints).


Remove Method (FilterExpressions)

See Remove Method (Constraints).


NamedBookmark Object

All of the properties and methods for the NamedBookmark object are listed in the following tables.


NamedBookmark Object All Members

NamedBookmark Object Properties

Name | Sets/returns a user-friendly name assigned to a bookmark shown in the Find dialog.
Value | Sets/returns a user-friendly name assigned to a bookmark shown in the Find dialog.


NamedBookmark Object Properties


Name Property (NamedBookmark)

Sets/returns a user-friendly name assigned to a bookmark shown in the Find dialog.

Syntax

NamedBookmark.Name = string

Remarks

Read/Write at run time. Not available at design time. Property applies to NamedBookmark object.

This property specifies the name of a NamedBookmark object used in Bookmarks Dialog. Usually, this property is set by the programmer in the GetBookmarkName event, or by the end-user in the Bookmarks Dialog.

See Also

NamedBookmark Object


Value Property (NamedBookmark)

Sets/returns a user-friendly name assigned to a bookmark shown in the Find dialog.

Syntax

NmaedBookmark.Value = variant

Remarks

Read/Write at run time. Not available at design time. Property applies to NamedBookmark object.

This property specifies the bookmark in a NamedBookmark object used in the Bookmarks Dialog.

See Also

NamedBookmark Object


NamedBookmarks Collection All Members

NamedBookmarks Collection Properties

Count | Returns the number of items in a collection.
Item | Returns a single collection item.

NamedBookmarks Collection Methods

Add | Adds a new item to the collection.
Remove | Removes an existing item from the collection.


NamedBookmarks Collection Properties


Count Property (NamedBookmarks)

See Count Property (Constraints).


Item Property (NamedBookmarks)

See Item Property (Constraints).


NamedBookmarks Collection Methods


Add Method (NamedBookmarks)

See Add Method (Constraints).


Remove Method (NamedBookmarks)

See Remove Method (Constraints).


Parameter Object

All of the properties and methods for the Parameter object are listed in the following tables.

Parameter Object All Members

Parameter Object Properties

Name | Sets/returns parameter name.
SQLParameter | Sets/returns the name of an SQL parameter associated with this parameter.
Type | Sets/returns parameter data type.
Value | Sets/returns parameter value.
ValueExpression | Specifies the expression used to calculate the value of a parameter.


Parameter Object Properties

Name Property (Parameter)

SQLParameter Property

Type Property (Parameter)

Value Property (Parameter)

ValueExpression Property (Parameter)


Name Property (Parameter)

Sets/returns parameter name.

Syntax

Parameter.Name = string

Remarks

Read/Write at run time and design time. Property applies to Parameter object.

This property specifies the name of a parameter. This must be a unique (case-insensitive) name that identifies the parameter in TData control expressions. It also serves as an index to the collection returned by the Parameters property. The parameter name must begin with a letter and contain only letters, digits, and underscores. The default name for a newly added parameter is PARAMETER_number, where number is the lowest integer that would yield a unique name.

See Also

Parameter Object


SQLParameter Property

Sets/returns the name of an SQL parameter associated with this parameter.

Syntax

Parameter.SQLParameter = string

Remarks

Read/Write at run time and design time. Property applies to Parameter object. Not available in True DataControl Lite.

This property allows you to connect a True DataControl parameter (a Parameter object) to a parameter in an SQL statement that is used as the RecordSource of the TData control.

If this property is left empty, the Parameter object is unrelated to SQL parameters.

If this property is set to a non-empty string, this parameter will be associated with an SQL parameter. The association is performed based on the parameters’ ordinal positions in the Parameters collection and in the SQL statement. TData control parameters with an empty SQLParameter property do not participate in the association.

The above rule implies that the actual string assigned to the SQLParameter property is not important. What important is the fact that SQLParameter is non-empty, and the index of the parameter in the Parameters collection. However, it is reasonable to always set SQLParameter to the corresponding SQL parameter name, if SQL parameters are named.

See Parameterized SQL for details.

See Also

Parameter Object


Type Property (Parameter)

Sets/returns parameter data type.

Syntax

Parameter.Type = value

Remarks

Read/Write at run time and design time. Property applies to Parameter object.

Design Time | Run Time
11 – Boolean | tdbTypeBoolean
16 – Byte | tdbTypeByte
6 – Currency | tdbTypeCurrency
7 – Date | tdbTypeDate
5 – Double | tdbTypeDouble
2 – Integer | tdbTypeInteger
3 – Long | tdbTypeLong
4 – Single | tdbTypeSingle
8 – String (default) | tdbTypeString
12 – Variant | tdbTypeVariant

This property determines the variant data type of the parameter. See True DataControl Parameters for details.

See Also

Parameter Object


Value Property (Parameter)

Sets/returns parameter value.

Syntax

Parameter.Value = variant

Remarks

Read/Write at run time. Not available at design time. Property applies to Parameter object.

This property is used to get/set the parameter value. Parameter value can be maintained by its ValueExpression, or by explicitely setting the Value property in code, or both.

See True DataControl Parameters for more information.

Note: This property is the default (implicit) property of the Parameter object, so it can be omitted in Visual Basic code.

See Also

Parameter Object


ValueExpression Property (Parameter)

Specifies the expression used to calculate the value of a parameter.

Syntax

Parameter.ValueExpression = variant

Remarks

Read/Write at run time and design time. Property applies to Parameter object.

This property specifies the expression that provides the parameter value.

If this property is left empty, the parameter value can still be set in code.

True DataControl evaluates this expression when the TData control is loaded, and on every refresh, before populating the Recordset, because parameter values can influence recordset contents.

Asynchronous evaluation of this expression, triggered by a change of a variable in it, can cause a refresh. It happens when the parameter is used in an expression causing a refresh, such as a range condition or filter expression.

See True DataControl Parameters for more information.

See True DataControl Expressions for more information about expressions in general. Evaluation rules for ValueExpression are as follows:

Expression Level: Recordset level

Synchronous Evaluation: Evaluated before the recordset is populated with records.

Asynchronous Evaluation: Action depends on whether or not the parameter is used in an expression forcing refresh. If so, changing the parameter value forces refresh.

See Also

Parameter Object


Parameters Collection

All of the properties and methods for the Parameters collection are listed in the following tables.


Parameters Collection All Members

Parameters Collection Properties

Count | Returns the number of items in a collection.
Item | Returns a single collection item.

Parameters Collection Methods

Add | Adds a new item to the collection.
Remove | Removes an existing item from the collection.


Parameters Collection Properties


Count Property (Parameters)

See Count Property (Constraints).


Item Property (Parameters)

See Item Property (Constraints).


Parameters Collection Methods


Add Method (Parameters)

See Add Method (Constraints).


Remove Method (Parameters)

See Remove Method (Constraints).


PropertyExpression Object

All of the properties and methods for the PropertyExpression object are listed in the following tables.


PropertyExpression Object All Members

PropertyExpression Object Properties

ControlName | Specifies a control whose property is governed by the property expression.
PropertyName | Specifies the property that is governed by the property expression.
ValueExpression | Specifies the expression used to evaluate the value of a control property.


PropertyExpression Object Properties


ControlName Property

Specifies a control whose property is governed by the property expression.

Syntax

PropertyExpression.ControlName = string

Remarks

Read/Write at run time and design time. Property applies to PropertyExpression object.

This property defines the name of the control whose property is governed by the PropertyExpression object. It is the control’s Name property, with Index in parentheses, if this is an element of a control array. Examples: Text1, Form1, TextArray(2).

See Control Property Expressions for details.

This property is used in conjunction with the PropertyName property. Full property name consists of ControlName and PropertyName separated with dot. Example: Label1.Font.Bold

See Also

PropertyExpression Object


PropertyName Property

Specifies the property that is governed by the property expression.

Syntax

PropertyExpression.PropertyName = string

Remarks

Read/Write at run time and design time. Property applies to PropertyExpression object.

This property defines the name of the property governed by the PropertyExpression object. For example, BackColor.

Nested properties such as Font.Bold are also supported.

See Control Property Expressions for details.

This property is used in conjunction with the PropertyName property. Full property name consists of ControlName and PropertyName separated with a dot ("."). Example: Label1.Font.Bold

See Also

PropertyExpression Object


ValueExpression Property (PropertyExpression)

Specifies the expression used to evaluate the value of a control property.

Syntax

PropertyExpression.ValueExpression = variant

Remarks

Read/Write at run time and design time. Property applies to PropertyExpression object.

This property specifies the expression that provides the value for the associated property at run time. The TData control evaluates this expression after positioning on a record, and when some variable in this expression changes. Control property is then set to the result of this evaluation. This way, True DataControl maintains the value of a property of any control depending on certain variables.

See Control Property Expressions for more information.

See True DataControl Expressions for more information about expressions in general. Evaluation rules for ValueExpression are as follows:

Expression Level: Record level

Synchronous Evaluation: Evaluated after the TData control has been positioned on a record.

Asynchronous Evaluation: Updates the value of the associated control property.

See Also

PropertyExpression Object


PropertyExpressions Collection

All of the properties and methods for the PropertyExpressions collection are listed in the following tables.


PropertyExpressions Collection All Members

PropertyExpressions Collection Properties

Count | Returns the number of items in a collection.
Item | Returns a single collection item.

PropertyExpressions Collection Methods

Add | Adds a new item to the collection.
Remove | Removes an existing item from the collection.


PropertyExpressions Collection Properties


Count Property (PropertyExpressions)

See Count Property (Constraints).


Item Property (PropertyExpressions)

See Item Property (Constraints).


PropertyExpressions Collection Methods


Add Method (PropertyExpressions)

See Add Method (Constraints).


Remove Method (PropertyExpressions)

See Remove Method (Constraints).


RangeCondition Object

All of the properties and methods for the RangeCondition object are listed in the following tables.


RangeCondition Object All Members

RangeCondition Object Properties

ComparisonOperation | Sets/returns the comparison operation used in a range condition.
ConditionExpression | Specifies whether the range condition is applied or skipped.
SkipIfEmpty | If True, the range condition is skipped when any of the variables occuring in the ValueExpression is empty.
ValueExpression | Specifies the expression with whose value all fetched values are compared.


RangeCondition Object Properties

ComparisonOperation Property

ConditionExpression Property (RangeCondition)

SkipIfEmpty Property

ValueExpression Property (RangeCondition)


ComparisonOperation Property

Sets/returns the comparison operation used in a range condition.

Syntax

RangeCondition.ComparisonOperation = value

Remarks

Read/Write at run time and design time. Property applies to RangeCondition object.

Design Time | Run Time
0 – < | tdbLessThan
1 – <= | tdbLessThanOrEqual
2 – = (default) | tdbEqual
3 – >= | tdbGreaterThanOrEqual
4 – > | tdbGreaterThan
5 – starts with | tdbStartsWith
6 – contains | tdbContains

This property specifies the type of comparison used by the RangeCondition object. See Field Range Conditions for more information.

See Also

RangeCondition Object


ConditionExpression Property (RangeCondition)

Specifies whether the range condition is applied or skipped.

Syntax

RangeCondition.ConditionExpression = variant

Remarks

Read/Write at run time and design time. Property applies to RangeCondition object.

This property specifies the applicability expression for a range condition.

If this expression is empty or evaluates to False, the range condition is skipped, ignored in fetching data to Recordset.

If this expression evaluates to True, the range condition is applied to restrict records fetched to the Recordset.

For more information, see Field Range Conditions.

See True DataControl Expressions for more information about expressions in general.

See Also

RangeCondition Object


SkipIfEmpty Property

If True, the range condition is skipped when any of the variables occuring in the ValueExpression is empty.

Syntax

RangeCondition.SkipIfEmpty = boolean

Remarks

Read/Write at run time and design time. Property applies to RangeCondition object.

This property specifies how to handle the range condition when a variable contained within the ValueExpression is empty.

If set to True (the default), the range condition is skipped; it will not restrict the resulting recordset. Sometimes the range condition should not be skipped if there are undefined variables in it, but rather produce an empty recordset. In these cases, you must set this property to False. However, the default setting (True) is useful for ad-hoc query forms where the user is not required to specify values for all fields.

If this property is set to False, the range condition is imposed even if it contains variables with empty values. In this case, the outcome of the range condition depends on the result of ValueExpression evaluation. For example, it can use IsEmpty and IsNull functions to test for empty values.

See Field Range Conditions for more information.

See Also

RangeCondition Object


ValueExpression Property (RangeCondition)

Specifies the expression with whose value all fetched values are compared.

Syntax

RangeCondition.ValueExpression = variant

Remarks

Read/Write at run time and design time. Property applies to RangeCondition object.

This property specifies the expression that provides the value used as the operand in the comparison.

The resulting range condition is field op value, where field is the data field that owns the range condition, op is the selected comparison operator (ComparisonOperation), and value is the result of this expression.

See Field Range Conditions for more information.

See True DataControl Expressions for more information about expressions in general. Evaluation rules for ValueExpression are as follows:

Expression Level: Recordset level

Synchronous Evaluation: Evaluated before the recordset is populated with records.

Asynchronous Evaluation: Forces refresh of the TData control.

See Also

RangeCondition Object


RangeConditions Collection

All of the properties and methods for the RangeConditions collection are listed in the following tables.


RangeConditions Collection All Members

RangeConditions Collection Properties

Count | Returns the number of items in a collection.
Item | Returns a single collection item.

RangeConditions Collection Methods

Add | Adds a new item to the collection.
Remove | Removes an existing item from the collection.


RangeConditions Collection Properties


Count Property (RangeConditions)

See Count Property (Constraints).


Item Property (RangeConditions)

See Item Property (Constraints).


RangeConditions Collection Methods


Add Method (RangeConditions)

See Add Method (Constraints).


Remove Method (RangeConditions)

See Remove Method (Constraints).


RowBuffer Object All Members

RowBuffer Object Properties

Bookmark | The bookmark of a row in the buffer.
ColumnCount | Number of columns (data fields) in each row of the buffer.
ColumnIndex | Returns the field index of a column in the RowBuffer.
ColumnName | Returns the field name of a column in the RowBuffer.
RowCount | Number of rows passed/returned in the buffer.
Value | Array of values passed/returned in the buffer.


RowBuffer Object Properties

Bookmark Property

ColumnCount Property

ColumnIndex Property

ColumnName Property

RowCount Property

Value Property (RowBuffer)


Bookmark Property

This property returns or sets a bookmark for the specified row within a RowBuffer object.

Syntax

rowbuffer.Bookmark(Row) = variant

Remarks

Read/Write at run time. Not available at design time. Property applies to RowBuffer object.

This property returns or sets a bookmark for the specified row within a RowBuffer object that is passed to an event handler for a TData control in user events mode (its DataMode property is set to 2 - User Events).

The Row argument is a long integer specifying the row where the bookmark is placed. The range of this argument can be from 0 to RowCount - 1.

In user events mode, a bookmark contains a user-defined value that uniquely identifies each row of data.

In the UserReadData and UserAddData events, your code must provide bookmarks for the rows being fetched or added. In the UserWriteData and UserDeleteRow events, the TData control passes one of these bookmarks as a parameter so your code can take the appropriate action.

See Also

RowBuffer Object


ColumnCount Property

Number of columns (data fields) in each row of the buffer.

Syntax

rowbuffer.ColumnCount

Remarks

Read-only at run time. Not available at design time. Property applies to RowBuffer object.

This property indicates the number of columns (data fields) in the RowBuffer object passed to an event procedure for a TData control in user events mode. Columns in a row buffer are indexed from 0 to ColumnCount - 1.

See Also

RowBuffer Object


ColumnIndex Property

Returns the field index of a column in the RowBuffer.

Syntax

rowbuffer.ColumnIndex (Col)

Remarks

Read-only at run time. Not available at design time. Property applies to RowBuffer object.

This property returns the index of the field corresponding to a column in the RowBuffer object passed to an event procedure for a TData control in user events mode. The index corresponds to the index of the field in the collection returned by the Fields property.

The Col argument is an integer specifying the desired column. The range of this argument can be from 0 to ColumnCount - 1.

The ColumnIndex property allows you to determine the field index associated with a RowBuffer column. It is provided for identification of the column in order for the user to fill in the Value property array with appropriate data. It is necessary because the RowBuffer object may not contain all fields. It contains only those fields required by the TData control for its operation, for optimization purposes. It may contain no fields at all, in which case ColumnCount is zero, so the only relevant information in the RowBuffer object is row bookmarks.

You can use either this property or the ColumnName property.

See Also

RowBuffer Object


ColumnName Property

Returns the field name of a column in the RowBuffer.

Syntax

rowbuffer.ColumnName (Col)

Remarks

Read-only at run time. Not available at design time. Property applies to RowBuffer object.

This property returns the name of the field corresponding to a column in the RowBuffer object passed to an event procedure for a TData control in user events mode.

The Col argument is an integer specifying the desired column. The range of this argument can be from 0 to ColumnCount - 1.

The ColumnName property allows you to determine the field name associated with a RowBuffer column. It is provided for identification of the column in order for the user to fill in the Value property array with appropriate data. It is necessary because the RowBuffer object may not contain all fields. It contains only those fields required by the TData control for its operation, for optimization purposes. It may contain no fields at all, in which case ColumnCount is zero, so the only relevant information in the RowBuffer object is row bookmarks.

You can use either this property or the ColumnIndex property.

See Also

RowBuffer Object


RowCount Property

Number of rows passed/returned in the buffer.

Syntax

rowbuffer.RowCount = long

Remarks

Read/Write at run time. Not available at design time. Property applies to RowBuffer object.

This property returns or sets the number of rows in a RowBuffer object passed to an event handler for a TData control in user events mode, with its DataMode property set to 2 - User Events.

When the UserReadData event is fired, this property indicates the number of rows requested from the data source. When the UserWriteData or UserAddData event is fired, this property always returns 1, since only a single row can be updated or added at a time.

Rows in a row buffer are indexed from 0 to RowCount - 1.

If your UserReadData event handler is able to supply RowCount rows, then it should do so without changing the value of RowCount. However, if there are not enough rows in your data source, then your handler should supply as many rows as it can and set the value of RowCount accordingly. You can set RowCount to zero to indicate that an end-of-data condition has occurred.

You can also set RowCount to zero in a UserWriteData or UserAddData handler to indicate that an error condition has occurred.

See Also

RowBuffer Object


Value Property (RowBuffer)

Array of values passed/returned in the buffer.

Syntax

rowbuffer.Value(Row, Column) = variant

Remarks

Read/Write at run time. Not available at design time. Property applies to RowBuffer object.

This property returns or sets the data value for the specified cell within a RowBuffer object passed to an event handler for a TData control in user events mode (with DataMode property set to 2 - User Events).

The Row argument is a long integer specifying the row where the value is placed. The range of this argument can be from 0 to RowCount - 1.

The Column argument is a long integer specifying the column where the value is placed. The range of this argument can be from 0 to ColumnCount - 1.

The Value property represents a two-dimensional array used to transfer data between a RowBuffer object (supplied by the TData control) and your event handlers. In the UserReadData event, your code must use the Value property to provide data values for the rows being fetched. In the UserAddData and UserWriteData events, the Value property conveys the user's changes to your event handlers.

See Also

RowBuffer Object


TData Control All Members

TData Control Properties

AllowEarlyOpen | Can be set to False to work around limitations of some data bound controls.
Appearance | Enables/disables 3-D display effects for the control.
ApproxCount | Sets/returns the approximate number of rows in recordset in user events mode.
Array | Specifies an XArrayDB object as the control's data source.
AutoRefresh | Controls automatic refresh of detail control upon change in master.
BackColor | Sets/returns the background color.
BOFAction | Action taken on reaching BOF (begin of file).
ButtonAdd | Determines if the Add button is visible.
ButtonBookmark | Determines if the Bookmarks button is visible.
ButtonCancel | Determines if the Cancel button is visible.
ButtonDelete | Determines if the Delete button is visible.
ButtonFind | Determines if the Find button is visible.
ButtonFirst | Determines if the First and Last buttons are visible.
ButtonNext | Determines if the Previous and Next buttons are visible.
ButtonPage | Determines if the Previous Page and Next Page buttons are visible.
ButtonQuery | Determines if the Query button is visible.
ButtonUpdate | Determines if the Update button is visible.
CacheSize | Returns/sets the number of rows to keep cached navigating through the recordset.
CallDataRead | Specifies if the DataRead event is fired.
CallDataWrite | Specifies if the DataWrite event is fired.
Caption | Text displayed in the middle section of the control.
ChangeInProgress | If True, prevents automatic refresh while making batch changes.
CommandTimeout | Amount of time to wait for the command to return (in seconds).
CommandType | Indicates the type of command.
ConfirmCancel | Determines whether to show confirmation message box when the Cancel button is pressed.
ConfirmDelete | Determines whether to show confirmation message box when the Delete button is pressed.
ConnectionString | Determines the ADO connection string used to establish data connection in data source mode.
ConnectionTimeout | Amount of time to wait for the connection to open before aborting it.
Constraints | Contains a collection of constraint objects.
ConvertEmptyToNull | Specifies if empty string values should be converted to Null on save.
ConvertNullToEmpty | Specifies if Null values of string fields should be converted to empty strings on retrieval.
CursorLocation | Determines if server-side or client-side cursors are used (which cursor engine used).
CursorType | Sets the cursor type to use for the underlying recordset.
DataMember | Qualifies the DataSource property setting.
DataMode | Specifies the type of data storage on which the control operates.
DataSource | Sets/returns the source of underlying data in DataMode = 0 – DataSource.
DesignConnection | If True, live database connection is always used at design time.
DesignTimeout | Seconds to wait for database connection at design time before aborting it.
Enabled | Enables/disables user interaction.
EOFAction | Action taken on reaching EOF (end of file).
ErrorMsgCaption | Overrides default message box caption for run-time errors.
ErrorMsgRestore | Specifies whether to prompt for resetting value on field value errors.
Fields | Contains a collection of field objects.
Filtered | Enables/disables filtering.
FilterExpressions | Contains a collection of filter expression objects.
Font | Specifies the font used to display the caption text.
ForeColor | Sets/returns the foreground color.
LinkType | Specifies how this control is linked to another TData control.
LockType | Sets/returns the type of locking (concurrency) to use.
ManualUpdate | If True, SourceRecordset changes are not automatically saved to the database on Update.
Master | Specifies the TData control on which this control is dependent.
MaxRecords | Maximum number of records to retrieve when opened.
Mode | Describes the mode in which the current connection is opened.
MouseIcon | Sets a custom mouse icon.
MousePointer | The type of mouse pointer displayed when over the control.
NameSubstitute | Used in containers that don’t support the standard Name property (e.g., VC++).
NamedBookmarks | Contains a collection of named bookmark objects, for Bookmarks button dialog.
Orientation | Control's orientation, either horizontal or vertical.
PageSize | Sets/returns the number of records in a page.
Parameters | Contains a collection of parameter objects.
Password | For OLE DB providers that support password.
PooledConnectionCount | Returns the number of connections in the pool shared by all TData controls.
PooledConnections | Returns connections in the pool shared by all TData controls.
PropertyExpressions | Contains a collection of property expression objects.
QueryFilter | Returns the Filter string that can be applied to an ADO recordset, composed from user-supplied data in query mode.
QueryMode | If True, the control is in query mode.
Recordset | Returns the ADO recordset object representing control's data.
RecordSource | Source of recordset in data source mode: SQL, other command text or table name.
RefreshOnSrcChange | Determines whether SourceRecordset changes trigger refresh.
ResyncAfterUpdate | Determines whether to call SourceRecordset.Resync immediately after SourceRecordset.Update.
SafeMode | If True, ADO recordsets are used with extra caution, avoiding certain problems in various OLE DB providers.
SourceConnection | Sets/returns the ADO connection used to connect to underlying data in data source mode.
SourceRecordset | Sets/returns the ADO recordset used as underlying data in data source mode.
Tooltips | Determines if the button tooltips are enabled.
UserName | For OLE DB providers that support user name.
Xtab | If True, the control is used in crosstab mode.
XTabColKey | For crosstab mode, comma-delimited list of key fields defining crosstab columns.
XTabCollate | For crosstab mode with multiple crosstab fields, if set to True, makes all columns for one field appear after all columns for another.
XTabRowKey | For crosstab mode, comma-delimited list of primary key fields defining crosstab rows.
XTabSeparateFields | For crosstab mode, if set to True, exposes crosstab columns as independent fields at design time.

TData Control Methods

ArrayIndexToBookmark | Converts array index to bookmark in memory array mode
BookmarkToArrayIndex | Converts bookmark to array index in memory array mode
ButtonEnabled | Returns the enabled state of a control button
CancelUpdate | Enhanced version of ADO CancelUpdate, includes resetting bound controls
Drag | Begins, ends, or cancels a drag operation of the control
EnableButton | Sets the enabled state of a button
Move | Moves the position of the control on the form
PressButton | Invokes the action of a control’s button
RaiseError | Used to specify error description in user mode events
Refresh | Refetches all data
RetrieveFields | Retrieves field layout from the source recordset
SetButtonPicture | Changes the picture on a button
SetUIString | Changes a string shown to the end-user
ShowWhatsThis | Displays the appropriate help topic for the control
UpdateFields | Updates the recordset with modified values from bound controls
ZOrder | Places the control at the front or back of the z-order

TData Control Events

ButtonPressed | Occurs when a control button is pressed.
ButtonStateChanged | Occurs when a control button's enable state changes.
CalcFields | Occurs before calculated field expressions are evaluated.
CalcFieldsComplete | Occurs after calculated field expressions have been evaluated.
DataRead | Occurs immediately after retrieving a row of values from the data source.
DataWrite | Occurs immediately before saving changed values to the data source.
Error | Occurs as a result of an error that takes place when no user code is being executed.
FieldChangeComplete | Occurs after a field value has changed.
Filter | Occurs before filter expressions are evaluated.
FilterComplete | Occurs after filter expressions have been evaluated.
GetBookmarkName | Occurs when Bookmarks Dialog is being opened. Allows you to specify the current bookmark name.
MoveComplete | Occurs after the current row position has changed.
OpenData | Occurs at startup and on every refresh. Allows to set the underlying recordset (SourceRecordset property) or XArrayDB (Array property) object.
OpenDataComplete | Occurs at startup and on every refresh, after the OpenData event.
RecordChangeComplete | Occurs after a record has been added/deleted/updated/restored.
RecordsetChangeComplete | Occurs after the whole recordset has changed.
UserAddData | Occurs when a new row is added in DataMode = 2 – UserEvents.
UserDeleteRow | Occurs when a row needs to be deleted in DataMode = 2 – UserEvents.
UserFindData | Occurs in DataMode = 2 - UserEvents, when the control needs to find a row based upon a simple filter.
UserReadData | Occurs when the control requires data in DataMode = 2 – UserEvents.
UserWriteData | Occurs when a row needs to be modified in DataMode = 2 – UserEvents.
WillChangeField | Occurs before a field value changes.
WillChangeRecord | Occurs before the current row position changes.
WillChangeRecordSet | Occurs before the whole contents of the recordset change due to a pending operation.
WillMove | Occurs before the current row position changes.
WillOpenData | Occurs at startup and on every refresh, before the OpenData event.


TData Control Properties

AllowEarlyOpen Property

Appearance Property

ApproxCount Property

Array Property

AutoRefresh Property

BackColor Property

BOFAction Property

ButtonAdd Property

ButtonBookmark Property

ButtonCancel Property

ButtonDelete Property

ButtonFind Property

ButtonFirst Property

ButtonNext Property

ButtonPage Property

ButtonQuery Property

ButtonUpdate Property

CacheSize Property

CallDataRead Property

CallDataWrite Property

Caption Property

ChangeInProgress Property

CommandTimeout Property

CommandType Property

ConfirmCancel Property

ConfirmDelete Property

ConnectionString Property

ConnectionTimeout Property

Constraints Property

ConvertEmptyToNull Property

ConvertNullToEmpty Property

CursorLocation Property

CursorType Property

DataMember Property

DataMode Property

DataSource Property

DesignConnection Property

DesignTimeout Property

Enabled Property

EOFAction Property

ErrorMsgCaption Property

ErrorMsgRestore Property

Fields Property

Filtered Property

FilterExpressions Property

Font Property

ForeColor Property

LinkType Property

LockType Property

ManualUpdate Property

Master Property

MaxRecords Property

Mode Property

MouseIcon Property

MousePointer Property

NameSubstitute Property

NamedBookmarks Property

Orientation Property

PageSize Property

Parameters Property

Password Property

PooledConnectionCount Property

PooledConnections Property

PropertyExpressions Property

QueryFilter Property

QueryMode Property

Recordset Property

RecordSource Property

RefreshOnSrcChange Property

ResyncAfterUpdate Property

SafeMode Property

SourceConnection Property

SourceRecordset Property

Tooltips Property

UserName Property

XTab Property

XTabColKey Property

XTabCollate Property

XTabRowKey Property

XTabSeparateFields Property


AllowEarlyOpen Property

Can be set to False to work around limitations of some data bound controls.

Syntax

TData.AllowEarlyOpen = value

Remarks

Read/Write at design time. Read-only at run time. Property applies to TData control.

This property is False by default and should be set to True only for the purpose of making some

bound controls work with TData that normally would not. For example, Microsoft Hierarchical FlexGrid will have problems with painting (highlighting current row) if AllowEarlyOpen is not set to True.

In Visual Basic, during form startup, before the form Load event is fired, control events are not yet ready to fire. TData relies on run time events for its functionality, events such as WillOpenData, OpenData and OpenDataComplete. Also, in DataMode = 2 – UserEvent, TData relies on events for populating its recordset with data. Therefore, TData cannot function properly during the early phases of form startup. But most of data bound controls request data from their data source exactly at that stage, when TData is not ready to provide the data.

To resolve this problem, TData returns empty recordset when it is requested before it is ready. Once the startup process is complete, TData notifies bound controls that it is now ready to provide data.

Note: At design time, this property is not available in property pages and must be set in the Visual Basic Properties window.

See Also

TData Control


Appearance Property

Enables/disables 3-D display effects for the control.

Syntax

TData.Appearance = value

Remarks

Read/Write at run time and design time. Property applies to TData control and TDataLite control.

Design Time | Run Time
0 - Flat | 0
1 - 3D (default) | 1

When this property is set to 1 - 3D, the control is painted with three-dimensional effects. When this property is set to 0 - Flat, no visual effects are used.

Note: At design time, this property is not available in the property pages and must be set in the Visual Basic Properties window.

See Also

TData Control


ApproxCount Property

Sets/returns the approximate number of rows in recordset in user events mode.

Syntax

TData.AproxCount = long

Remarks

Read/Write at run time. Not available at design time. Property applies to TData control.

This property sets or returns the approximate number of rows in the TData control’s Recordset.

The ApproxCount property is used in user events mode (DataMode = 2 – UserEvents) in conjunction with the ApproximatePosition argument of the UserReadData event. It is typically necessary for some bound controls to calibrate their vertical scroll bar. If this property is not set, the approximate count and position functionality is disabled. As some data bound controls may depend on this functionality, it is strongly recommended that you set this property.

Note: Setting the ApproxCount property in data modes other than user events mode has no effect. However, getting the ApproxCount property will query the underlying data source and return the row count.

See Also

TData Control


Array Property

Specifies an XArrayDB object as the control's data source.

Syntax

TData.Array= XarrayDB

Remarks

Read/Write at run time. Not available at design time. Property applies to TData control and TDataLite control.

The Array property specifies an ComponentOne XArrayDB object that acts as a data source. This property is used only when DataMode is set to 1 - MemoryArray. It has no effect in the other two data modes.

You do not need to set the Array property explicitly in code. In memory array mode, TData control automatically creates an XArrayDB object containing one row of empty data, with one column for each field. You can redimension and populate the array returned by the Array property in the OpenData event.

You can also create, re-dimension, and populate an XArrayDB object in code, then assign it to the Array property of a TData control in the OpenData event. If you create a new XArrayDB object, it is your responsibility to make its ColumnCount equal to the number of data fields in the TData control.

Setting the Array property to an XArrayDB object outside the OpenData event causes a refresh of the TData control. You are not allowed to set the Array property in True DataControl events other than OpenData.

See Also

For more information, see Memory Array Mode.

TData Control


AutoRefresh Property

Controls automatic refresh of detail control upon change in master.

Syntax

TData.AutoRefresh = value

Remarks

Read/Write at run time and design time. Property applies to TData control.

Design Time | Run Time
0 - None | tdbNoRefresh
1 - Immediate | tdbImmediate
2 - When Idle (default) | tdbWhenIdle

Specifies whether and when a TData control is repopulated with new data upon a change in its master TData control. The AutoRefresh property only affects dependent TData controls, that is, those with the Master property set to a non-empty value.

If AutoRefresh is 0 - None, changes in the master do not cause automatic refresh, so you must call the Refresh method explicitly to synchronize this control with its master. You can use this setting to bypass the automatic refresh of a detail control in a master-detail relationship.

If AutoRefresh is 1 - Immediate, any change to the value of a master’s field or parameter, as well as any repositioning of the master’s current row, immediately triggers a refresh of this TData control. Since this can be a time-consuming operation, the Immediate setting is recommended only for forms that display one master record at a time.

If AutoRefresh is 2 - When Idle, changes in the master control cause an automatic refresh of this TData control, just as with the Immediate setting. The difference is that the process is optimized for fast navigation, such as when multiple master records are displayed in a bound grid. With this setting, refresh operations are performed after a short delay, in idle time, so that the user will not notice any delay other than that needed to retrieve the master records. For example, if the user repeatedly presses the down arrow key on a master grid in quick succession, the master TData control will not refresh the detail records until it stops receiving notifications caused by the repetitive keyboard activity.

See Also

TData Control


BackColor Property

Sets/returns the background color.

Syntax

TData.BackColor = color

Remarks

Read/Write at run time and design time. Property applies to TData control and TDataLite control.

This property controls the background color of the middle area (between buttons) of the control. Colors may be specified as RGB values or system default colors.

Note: At design time, this property is not available in the property pages and must be set in the Visual Basic Properties window.

See Also

TData Control


BOFAction Property

Action taken on reaching BOF (begin of file).

Syntax

TData.BOFAction = value

Remarks

Read/Write at run time and design time. Property applies to TData control and TDataLite control.

Design Time | Run Time
0 - MoveFirst | adDoMoveFirst
1 - StayBOF | adStayBOF

This property determines the action taken when the user attempts to move backward past the first data record by pressing the TData control’s Previous button. When set to 0 - MoveFirst (the default), the control makes the first record current. When set to 1 - StayBOF, the control positions before the beginning of the recordset (BOF), and disables its Move Previous button.

Note: At design time, this property is not available in property pages and must be set in the Visual Basic Properties window.

See Also

TData Control


ButtonAdd Property

Determines if the Add button is visible.

Syntax

TData.ButtonAdd = boolean

Remarks

Read/Write at run time and design time. Property applies to TData control and TDataLite control. See True DataControl buttons for details.

See Also

TData Control


ButtonBookmark Property

Determines if the Bookmarks button is visible.

Syntax

TData.ButtonBookmark = boolean

Remarks

Read/Write at run time and design time. Property applies to TData control and TDataLite control. See True DataControl buttons for details.

See Also

TData Control


ButtonCancel Property

Specifies whether the Cancel button is visible.

Syntax

TData.ButtonCancel = boolean

Remarks

Read/Write at run time and design time. Property applies to TData control and TDataLite control. See True DataControl buttons for details.

See Also

TData Control


ButtonDelete Property

Specifies whether the Delete button is visible.

Syntax

TData.ButtonDelete = boolean

Remarks

Read/Write at run time and design time. Property applies to TData control and TDataLite control. See True DataControl buttons for details.

See Also

TData Control


ButtonFind Property

Specifies whether the Find button is visible.

Syntax

TData.ButtonFind = boolean

Remarks

Read/Write at run time and design time. Property applies to TData control and TDataLite control. See True DataControl buttons for details.

See Also

TData Control


ButtonFirst Property

Specifies whether the First and Last buttons are visible.

Syntax

TData.ButtonFirst = boolean

Remarks

Read/Write at run time and design time. Property applies to TData control and TDataLite control. See True DataControl buttons for details.

See Also

TData Control


ButtonNext Property

Specifies whether the Previous and Next buttons are visible.

Syntax

TData.ButtonNext = boolean

Remarks

Read/Write at run time and design time. Property applies to TData control and TDataLite control. See True DataControl buttons for details.

See Also

TData Control


ButtonPage Property

Specifies whether the PreviousPage and NextPage buttons are visible.

Syntax

TData.ButtonPage = boolean

Remarks

Read/Write at run time and design time. Property applies to TData control and TDataLite control. See True DataControl buttons for details.

See Also

TData Control


ButtonQuery Property

Specifies whether the Query button is visible.

Syntax

TData.ButtonQuery = boolean

Remarks

Read/Write at run time and design time. Property applies to TData control and TDataLite control. See True DataControl buttons for details.

See Also

TData Control


ButtonUpdate Property

Specifies whether the Update button is visible.

Syntax

TData.ButtonUpdate = boolean

Remarks

Read/Write at run time and design time. Property applies to TData control and TDataLite control. See True DataControl buttons for details.

See Also

TData Control


CacheSize Property

Returns/sets the number of rows to keep cached navigating through the recordset.

Syntax

TData.CacheSize = long

Remarks

Read/Write at run time and design time. Property applies to TData control.

This property indicates the number of records from a recordset object that are cached locally in memory. Default is 50. This is a standard ADO recordset property. It applies to the TData control’s Recordset. In data source mode, it also applies to the SourceRecordset created by the TData control. This property can be set at any time during the control’s lifetime.

Note: At design time, this property is not available in property pages and must be set in the Visual Basic Properties window.

See Also

TData Control


CallDataRead Property

This property specifies whether TData calls the DataRead event.

Syntax

TData.CallDataRead = string

Remarks

Read/Write at run time and design time. Property applies to TData control and TDataLite control.

The default is False – DataRead does not occur. Firing DataRead when it is not used can be an unnecessary burden for performance. If you intend to use the DataRead event, set this property to True.

Note: At design time, this property is not available in property pages and must be set in the Visual Basic Properties window.

See Also

TData Control


CallDataWrite Property

This property specifies whether TData calls the DataWrite event.

Syntax

TData.CallDataWrite = string

Remarks

Read/Write at run time and design time. Property applies to TData control and TDataLite control.

The default is False – DataWrite does not occur. Firing DataWrite when it is not used can be an unnecessary burden for performance. If you intend to use the DataWrite event, set this property to True.

Note: At design time, this property is not available in property pages and must be set in the Visual Basic Properties window.

See Also

TData Control


Caption Property

Specifies the text displayed in the middle area (between buttons) of the control.

Syntax

TData.Caption = string

Remarks

Read/Write at run time and design time. Property applies to TData control and TDataLite control.

Note: At design time, this property is not available in property pages and must be set in the Visual Basic Properties window.

See Also

TData Control


ChangeInProgress Property

If True, prevents automatic refresh while making batch changes.

Syntax

TData.ChangeInProgress = boolean

Remarks

Read/Write at run time. Not available at design time.
Property applies to TData control and TDataLite control.

This property, when set to True, prevents an automatic refresh of the TData control for the duration of some bulk changes to its collections, field/parameter values and, SourceRecordset and Array properties.

The ChangeInProgress property is normally set to False. It can only be set to True in code for a short time, while performing several changes to the TData control. It must be set back to False immediately once the changes are done. Actions performed with ChangeInProgress set to True cannot include TData methods such as Refresh, UpdateFields, etc. Only the setting of properties is allowed. The ChangeInProgress property cannot be used inside TData events.

Set ChangeInProgress to True when you start batch changes and don't want the TData Recordset to refresh until you are done with them. Setting it back to False applies the changes and refreshes the recordset (and other TData's recordsets if they are connected to this TData control as dependents in master-detail relationships) if necessary. This applies when:

•

Changing the value of a parameter. For more information, see True DataControl Parameters.

•

Changing the value of a field that causes refresh of a dependent TData control. For more information, see Master-Detail Relationships.

•

Setting TData.SourceRecordset. For more information, see Setting SourceRecordset and DataSource at run time.

•

Setting TData.Array. For more information, see Memory Array Mode.

•

Changing TData collections and their objects. For more information, see Modifying True DataControl collections from code.

See Also

TData Control


CommandTimeout Property

Indicates how long to wait (in seconds) while executing a command in data source mode.

Syntax

TData.CommandTimeout = long

Remarks

Read/Write at run time and design time. Property applies to TData control.

This property indicates how long to wait (in seconds) while executing a command in data source mode (DataMode = 0 - DataSource) creating SourceRecordset, before terminating the attempt and generating an error. Default is 30 seconds.

This is a standard ADO property. It can be set at any time during the control’s lifetime, but it will take effect only if set at design time, in WillOpenData event or after the Refresh method is called.

Note: At design time, this property is not available in property pages and must be set in the Visual Basic Properties window.

See Also

TData Control


CommandType Property

This property indicates how the RecordSource text is to be interpreted while creating SourceRecordset in data source mode (DataMode = 0 - DataSource).

Syntax

TData.CommandType = value

Remarks

Read/Write at run time and design time. Property applies to TData control.

Values
8 | adCmdUnknown (default)
1 | adCmdText
2 | adCmdTable
4 | adCmdStoredProc
512 | adCmdTableDirect

When set to 8 – adCmdUnknown, the TData control makes calls to the OLE DB provider to determine if the RecordSource text is a SQL statement, a stored procedure, or a table name. This can create performance overhead, so it is recommended that you change the CommandType property if you know the type of command you are using.

When set to 1 – adCmdText, the TData control interprets the RecordSource text as a command text (usually, a SQL statement).

When set to 2 – adCmdTable, or to 512 – adCmdTableDirect, the TData control interprets the RecordSource text as a table name. The difference between adCmdTable and adCmdTableDirect is that adCmdTableDirect can be slightly more optimal since ADO does not try to use a command opening the recordset (see ADO documentation for details).

When set to 4 – adCmdStoredProc, the TData control interprets the RecordSource text as a stored procedure name.

CommandType is a standard ADO property. It can be set at any time during the control’s lifetime, but it will take effect only if set at design time, in WillOpenData event or after the Refresh method is called.

See Also

TData Control


ConfirmCancel Property

Determines whether or not to open a confirmation dialog when the Cancel button is pressed.

Syntax

TData.ConrfirmCancel = boolean

Remarks

Read/Write at run time and design time. Property applies to TData control and TDataLite control.

Note: At design time, this property is not available in the property pages and must be set in the Visual Basic Properties window.

See Also

TData Control


ConfirmDelete Property

Determines whether or not to open a confirmation dialog when the Delete button is pressed.

Syntax

TData.ConrfirmDelete = boolean

Remarks

Read/Write at run time and design time. Property applies to TData control and TDataLite control.

Note: At design time, this property is not available in the property pages and must be set in the Visual Basic Properties window.

See Also

TData Control


ConnectionString Property

This property determines the ADO connection string used to establish a data connection when creating SourceRecordset in data source mode (DataMode = 0 - DataSource).

Syntax

TData.ConnectionString = string

Remarks

Read/Write at run time and design time. Property applies to TData control.

Contains detailed information organized as a series of argument=value statements separated by semicolons. The connection string contains all necessary information (except UserName and Password) for establishing a connection with a data source, usually a database.

At design time, the DataSource property page provides three options for specifying the ConnectionString:

•

By Data Link File Name

•

By ODBC Data Source Name

•

By building a connection string with the standard Build dialog, or by entering it directly.

ConnectionString is a standard ADO property. It can be set at any time during the control’s lifetime, but it will take effect only if set at design time, in WillOpenData event or after the Refresh method is called.

See Also

TData Control


ConnectionTimeout Property

Amount of time to wait for the connection to open before aborting it.

Syntax

TData.ConnectionTimeout = long

Remarks

Read/Write at run time and design time. Property applies to TData control.

This property indicates how long to wait (in seconds) while establishing a connection in data source mode (DataMode = 0 - DataSource) creating SourceRecordset, before terminating the attempt and generating an error. Default is 15 seconds.

This is a standard ADO property. It can be set at any time during the control’s lifetime, but it will take effect only if set at design time, in WillOpenData event or after the Refresh method is called.

Note: At design time, this property is not available in property pages and must be set in the Visual Basic Properties window.

See Also

TData Control


Constraints Property

Returns a collection of Constraint objects, record-level constraints defined in the TData control.

Syntax

TData.Constraints

Remarks

Read-only at run time. Not available at design time. Property applies to TData control.

See Validation and Constraints for details.

See Also

TData Control


ConvertEmptyToNull Property

Specifies if empty string values should be converted to Null on save.

Syntax

TData.ConvertEmptyToNull = boolean

Remarks

Read/Write at run time and design time. Property applies to TData control and TDataLite control.

If set to True (default), this property makes TData save empty string values in the database as Null values. Otherwise, empty strings are written literally, as empty strings. Most databases will convert them to Null anyway, so it rarely makes sense to change the default ConvertEmptyToNull=True to False. Non-string fields are not affected by this property, there values are never automatically converted to Null. If you need to convert some particular values (for example, 0) to Null for such fields, use the DataWrite event. For more information, see Modifying Field Values Retrieving and Saving Them in the Data Source.

Note: At design time, this property is not available in the property pages and must be set in the Visual Basic Properties window.

See Also

TData Control


ConvertNullToEmpty Property

Specifies if Null values of string fields should be converted to empty strings on retrieval.

Syntax

TData.ConvertNullToEmpty = boolean

Remarks

Read/Write at run time and design time. Property applies to TData control and TDataLite control.

If set to True (default), this property makes TData convert Null values of string fields read from the data source to empty string. This make it easier to deal with such values in expressions and code, since VBScript and Visual Basic expressions have special behavior on Null values, which is usually undesirable, and empty strings are easier to handle. Non-string fields are not affected by this property. If you need to convert Nulls to some particular values for such fields, use the DataRead event. For more information, see Modifying Field Values Retrieving and Saving Them in the Data Source.

Note: At design time, this property is not available in the property pages and must be set in the Visual Basic Properties window.

See Also

TData Control


CursorLocation Property

Determines if server-side or client-side cursors are used (which cursor engine used).

Syntax

TData.CursorLocation = value

Remarks

Read/Write at run time and design time. Property applies to TData control.

Values
2 | adUseServer
3 | adUseClient (default)

This property determines whether server-side or client-side cursors are used for the SourceRecordset in data source mode (DataMode = 0 - DataSource).

When set to 2 – adUseServer, cursors supplied by the data-provider are used. These cursors are sometimes more flexible and might have better performance. However, some features of the Microsoft Client Cursor Provider (for example, Sort and Filter), used with client-side cursors will be unavailable with this setting.

When set to 3 – adUseClient, local cursor library, the Microsoft Client Cursor Provider is used for the cursor engine. It supports additional functionality, such as Filter and Sort properties.

CursorLocation is a standard ADO recordset property. It can be set at any time during the control’s lifetime, but it will take effect only if set at design time, in the WillOpenData event or after the Refresh method is called.

Notes: At design time, this property is not available in property pages and must be set in the Visual Basic Properties window.

The CursorLocation property affects the SourceRecordset only. The TData control’s Recordset always has the 3 – adUseClient setting, which, in fact, has no implications for TData.Recordset.

Caution: Using 3 – adUseClient adds some important functionality to ADO recordsets, such as Filter and Sort, but it is inappropriate for large recordsets for performance reasons. Using 3 – adUseClien, all the data is first fetched from the server to the client, and only then your recordset becomes active. For more information, see Optimizing data access performance and Improvements over standard ADO data sources.

See Also


CursorType Property

Sets the cursor type to use for the underlying recordset.

Syntax

TData.CursorType = value

Remarks

Read/Write at run time and design time. Property applies to TData control.

Values |
1 | adOpenKeyset
2 | adOpenDynamic
3 | adOpenStatic (default)

This property determines the type of cursor used for the SourceRecordset in data source mode (DataMode = 0 - DataSource).

1 – adOpenKeyset - Keyset cursor. Data changes made by other users to rows of your recordset are visible to your recordset, but you can't see records that other users add and delete.

2 – adOpenDynamic - Dynamic cursor. Additions, changes, and deletions by other users are visible.

3 – adOpenStatic - Static cursor. Additions, changes, or deletions by other users are not visible.

CursorType is a standard ADO recordset property. It can be set at any time during the control’s lifetime, but it will take effect only if set at design time, in WillOpenData event or after the Refresh method is called.

Notes: At design time, this property is not available in property pages and must be set in the Visual Basic Properties window.

The CursorType property affects SourceRecordset only. The TData control’s Recordset always has the 3 – adOpenStatic setting.

See Also

TData Control


DataMember Property

Qualifies the DataSource property setting.

Syntax

TData.DataMember = string

Remarks

Read/Write at design time and run time. Property applies to TData control and TDataLite control starting from version 8.0.

This property qualifies the DataSource property setting for ADO/OLE DB data sources exposing multiple recordsets. It defines which recordset (member) is used.

For more information, see DataSource property.

See Also

TData Control


DataMode Property

Specifies the type of data storage on which the control operates.

Syntax

TData.DataMode = value

Remarks

Read/Write at design time. Read-only at run time. Property applies to TData control and TDataLite control.

Design Time | Run Time
0 - DataSource (default) | tdbModeDataSource
1 - MemoryArray | tdbModeMemoryArray
2 - UserEvents | tdbModeUserEvents

This property efines the source and storage of data on which a TData control operates.

When set to 0 - DataSource (the default), the TData control uses an ADO recordset as its underlying data. The recordset can be created by the TData control automatically if you set all relevant data source properties, or else you can set the SourceRecordset property in code.

When set to 1 - Memory Array, the TData control creates an XArrayDB object containing one row of empty data, with one column for each field. Alternatively, you can set the Array property to a pre-initialized XArrayDB object in code.

When set to 2 - User Events, you must write a handler for the UserReadData event. Depending upon the requirements of your application, you may also need to write handlers for the UserAddData, UserWriteData, UserDeleteRow, and UserFindData events. This mode is unavailable in True DataControl Lite.

For more information, see Data Access Modes.

See Also

TData Control


DataSource Property

Sets/returns the source of underlying data in DataMode = 0 – DataSource.

Syntax

Set TData.DataSource = value

Remarks

Read/Write at design time and run time. Property applies to TData control and TDataLite control starting from version 7.0.

This property defines the source of underlying data in DataMode = 0 - DataSource. it is used to bind TData control to a standard ADO/OLE DB data source, such as an ADODC control or Visual Basic DataEnvironment.

If the DataSource property is non-empty, it overrides all data source properties (available in the DataSource property page) and SourceRecordset setting.

At run time, DataSource can be set in the OpenData event or outside TData events. Setting SourceRecordset in code outside TData events refreshes the TData control. It is not allowed to set DataSource in TData events other than OpenData.

With data sources exposing multiple recordsets, you need to use the DataMember property along with DataSource, to specify which member (recordset) is used. Setting DataMember/DataSource at run time, set DataMember first, before DataSource, to ensure that the correct member is used when TData refreshes.

Setting the DataSource property is the only option in True DataControl Lite, see Binding TDataLite to a data source. In True DataControl, this option is available starting from version 7.0.

For more information, see Data Access Modes and Binding TDataLite to a data source.

See Also

TData Control


DesignConnection Property

If true, live database connection is always used at design time.

Syntax

TData.DesignConnection = boolean

Remarks

Read/Write at design time. Ignored at run time. Property applies to TData control.

This property determines whether a TData control uses live database connection at design time. It has effect only for DataMode = 0 – DataSource.

If set to True (default), TData tries to establish database connection when it needs information from the database. That is, when the Fields property page is opened, performing syntax check and on some other occasions.

Set this property to False if you are working in disconnected environment, or if establishing connection is too time consuming or unnecessary. Setting it to False only means that TData won’t attempt to establish connection on its own. It will still try to establish connection when you perform Retrieve Fields or press the Test button on the DataSource property page.

Note: At design time, this property is not available in the property pages and must be set in the Visual Basic Properties window.

For more information, see DesignTimeout property.

See Also

TData Control


DesignTimeout Property

Seconds to wait for database connection at design time before aborting it.

Syntax

TData.DesignTimeout = long

Remarks

Read/Write at design time. Ignored at run time. Property applies to TData control.

This property indicates how long to wait (in seconds) at design time while establishing a connection to the database, before terminating the attempt. Default is 5 seconds. It has effect only for DataMode = 0 – DataSource.

Note: At design time, this property is not available in the property pages and must be set in the Visual Basic Properties window.

For more information, see DesignConnection property.

See Also

TData Control


Enabled Property

Enables/disables user interaction.

Syntax

TData.Enabled = boolean

Remarks

Read/Write at run time and design time. Property applies to TData control and TDataLite control.

This property determines whether a TData control can respond to end-user interaction. If True (the default), the user can press the control’s buttons with the mouse. If False, the user cannot manipulate the control directly.

Note: At design time, this property is not available in the property pages and must be set in the Visual Basic Properties window.

See Also

TData Control


EOFAction Property

Action taken on reaching EOF (end of file).

Syntax

TData.EOFAction = value

Remarks

Read/Write at run time and design time. Property applies to TData control and TDataLite control.

Design Time | Run Time
0 - MoveLast (default) | adDoMoveLast
1 - StayEOF | adStayEOF
2 - AddNew | adDoAddNew

This property determines the action taken when the user attempts to move forward past the last data record by pressing the TData control’s Next button. When set to 0 - MoveLast (the default), the control makes the last record current. When set to 1 - StayEOF, the control positions after the end of the recordset (EOF) and disables its Move Last button. When set to 2 - AddNew, the control adds a new row to the recordset and positions on the newly added row.

Note: At design time, this property is not available in the property pages and must be set in the Visual Basic Properties window.

See Also

TData Control


ErrorMsgCaption Property

Overrides the default message box caption for run-time errors.

Syntax

TData.ErrorMsgCaption = string

Remarks

Read/Write at run time and design time. Property applies to TData control and TDataLite control.

Set this property to override the default message box caption for run-time errors shown to the end-user. If this property is left empty (the default), run-time error message boxes are displayed with the default caption:

ComponentOne True Data Control 8.0

or

ComponentOne True Data Control Lite 8.0

By assigning a nonempty value to the ErrorMsgCaption property, you can change this caption to whatever is appropriate for your application. You can also set this property in your Error event handler to provide different captions for different types of errors.

Note: At design time, this property is not available in the property pages and must be set in the Visual Basic Properties window.

See Also

TData Control


ErrorMsgRestore Property

Specifies whether to prompt for resetting value on field value errors.

Syntax

TData.ErrorMsgRestore = boolean

Remarks

Read/Write at run time and design time. Property applies to TData control.

This property controls the prompt to restore the field's previous value, appearing in the error message on field errors: "Do you want to restore the previous value?"

When set to True, the standard prompt appears in the standard error message wherever applicable.

When set to False, this property suppresses the standard prompt. Standard error messages don’t prompt the user to restore the previous value.

You can set this property at run time, including in your Error event handler where you can decide whether you need the standard prompt or not.

Note: At design time, this property is not available in the property pages and must be set in the Visual Basic Properties window.

See Also

TData Control


Fields Property

Contains a collection of field objects.

Syntax

TData.Fields

Remarks

Read-only at run time. Not available at design time. Property applies to TData control and TDataLite control.

This property returns a collection of Field objects. Every item in this collection defines a TData control field. See True DataControl Fields for details.

See Also

TData Control


Filtered Property

Enables/disables filtering.

Syntax

TData.Filtered = boolean

Remarks

Read/Write at run time and design time. Property applies to TData control and TDataLite control.

This property determines whether a TData control should apply filters.

If True, the control applies filters defined in the collection returned by the FilterExpressions property. It also fires the Filter event where records can be filtered in code.

If False, all filters are ignored and the Filter event does not fire. The default value is False.

See Also

TData Control


FilterExpressions Property

Contains a collection of filter expression objects.

Syntax

TData.FilterExpressions

Remarks

Read-only at run time. Not available at design time. Property applies to TData control and TDataLite control.

This property returns a collection of FilterExpression objects. Every item in this collection defines a filter expression for the TData control. See Filters for details.

See Also

TData Control


Font Property

Specifies the font used to display the caption text.

Syntax

TData.Font = font

Remarks

Read/Write at run time and design time. Property applies to TData control and TDataLite control.

This property returns or sets the font object used to display the Caption text in the middle area (between buttons) of the control.

Note: At design time, this property is not available in the property pages and must be set in the Visual Basic Properties window.

See Also

TData Control


ForeColor Property

Sets/returns the foreground color.

Syntax

TData.ForeColor = color

Remarks

Read/Write at run time and design time. Property applies to TData control and TDataLite control.

This property controls the color in which the Caption text is displayed in the middle area (between buttons) of the control. Colors may be specified as RGB values or system default colors.

Note: At design time, this property is not available in the property pages and must be set in the Visual Basic Properties window.

See Also

TData Control


LinkType Property

Specifies how this control is linked to another TData control.

Syntax

TData.LinkType = value

Remarks

Read/Write at design time. Read-only at run time. Property applies to TData control.

Design Time | Run Time
0 - None (default) | tdbLinkNone
1 - Outer | tdbLinkOuter
2 - Inner | tdbLinkInner

This property specifies whether and how a dependent TData control is linked in a one-to-one relationship with its Master control.

If set to 0 - None (the default), the control does not participate in a one-to-one link, even if its Master property is set. Unless you intend to create a one-to-one link between two TData controls, you should use this default setting.

If set to 1 - Outer, the control is linked to its Master control, and master records that have no counterpart in this control are included in the resulting recordset (linked fields are left empty in such records).

If set to 2 - Inner, the control is linked to its Master control, and master records that have no counterpart in this control are excluded from the resulting recordset.

See Also

TData Control


LockType Property

Sets/returns the type of locking (concurrency) to use.

Syntax

TData.LockType = value

Remarks

Read/Write at run time and design time. Property applies to TData control and TDataLite control.

Values
-1 | adLockUnspecified
1 | adLockReadOnly
2 | adLockPessimistic
3 | adLockOptimistic (default)
4 | adLockBatchOptimistic

This property determines the type of locks placed on records during editing. In particular, it determines if the TData Recordset is read only (1 – adLockReadOnly) and if the batch update mode is used (4 – adLockBatchOptimistic).

LockType is a standard ADO recordset property. It applies both to Recordset (in all data modes) and to SourceRecordset (only in data source mode).

When set to -1 – adLockUnspecified, the type of locks and whether the recordset may be modified are determined by the data provider. This setting is only applicable in data source mode.

When set to 1 – adLockReadOnly, the Recordset is read-only, users can’t alter the data.

When set to 2 – adLockPessimistic, the Recordset employs pessimistic locking, record by record. The provider does what is necessary to ensure successful editing of the records, usually by locking records at the data source immediately upon editing.

When set to 3 – adLockOptimistic, the Recordset uses optimistic locking, record by record. The provider locks records only when the Recordset’s Update method is called.

The 4 – adLockBatchOptimistic setting is equivalent to adLockOptimistic, but it also enables the batch update mode. When an ADO recordset is in batch update mode, changes are not transferred to the data source (database) until the recordset’s UpdateBatch method is called. If it is not in batch update mode, changes are transferred to the data source on leaving the current row and when the recordset’s Update method is called.

LockType can be set at any time during the control’s lifetime, but it will take effect only if set at design time, in the WillOpenData event or after the Refresh method is called.

See Also

TData Control


ManualUpdate Property

If true, SourceRecordset changes are not automatically saved to the database on Update.

Syntax

TData.ManualUpdate = boolean

Remarks

Read/Write at run time and design time. Property applies to TData control and TDataLite control.

This property is False by default. Setting it to True disables automatic update of the database when TData.Recordset.UpdateBatch is called. Use it when you need to execute your own code for database update. Setting ManualUpdate to True only works in conjunction with LockType = adLockBatchOptimistic. It is normally used with disconnected recordsets, see Using TData in distributed applications (disconnected recordset support).

Note: At design time, this property is not available in property pages and must be set in the Visual Basic Properties window.

See Also

TData Control


Master Property

Specifies the TData control on which this control is dependent.

Syntax

TData.Master = string

Remarks

Read/Write at design time. Read-only at run time. Property applies to TData control.

This property specifies the name of the TData control that acts as the master in a master-detail relationship with this (dependent) TData control. The default value is an empty string, which indicates that the control has no master.

Both master and dependent controls must be on the same form.

Note: If you are establishing a one-to-one link between a dependent control and its master, you need to set the LinkType property to either 1 - Outer, or 2 - Inner.

For more information, see Master-Detail Relationships.

See Also

TData Control


MaxRecords Property

Maximum number of records to retrieve when opened.

Syntax

TData.MaxRecords = long

Remarks

Read/Write at run time and design time. Property applies to TData control.

This property indicates the maximum number of records to return to the SourceRecordset from a query when creating the SourceRecordset in data source mode (DataMode = 0 - DataSource). The default setting is zero, which means the provider returns all existing records.

This is a standard ADO property. It can be set at any time during the control’s lifetime, but it will take effect only if set at design time, in the WillOpenData event, or after the Refresh method is called.

Note: At design time, this property is not available in property pages and must be set in the Visual Basic Properties window.

See Also

TData Control


Mode Property

Describes the mode in which the current connection is opened.

Syntax

TData.Mode = value

Remarks

Read/Write at run time and design time. Property applies to TData control.

Values
0 – adModeUnknown (default) | Indicates that the permissions cannot be determined
1 - adModeRead | Indicates read-only permissions
2 - adModeWrite | Indicates write-only permissions
3 - adModeReadWrite | Indicates read/write permissions
4 - adModeShareDenyRead | Prevents others from opening connection with read permissions
8 - adModeShareDenyWrite | Prevents others from opening connection with write permissions
12 - adModeShareExclusive | Prevents others from opening connection
16 - adModeShareDenyNone | Allows others to open connection with any permissions

This property determines permissions for modifying the data that the provider should use on the current connection, with the TData control’s SourceRecordset. This property is only relevant in data source mode (DataMode = 0 - DataSource).

Mode is a standard ADO property. It can be set at any time during the control’s lifetime, but it will take effect only if set at design time, in WillOpenData event or after the Refresh method is called.

Notes: At design time, this property is not available in property pages and must be set in the Visual Basic Properties window.

Using client-side cursors, (CursorLocation = 3 – adUseClient) the Mode property can only be set to 0 – adModeUnknown.

See Also

TData Control


MouseIcon Property

Sets a custom mouse icon.

Syntax

TData.MouseIcon = picture

Remarks

Read/Write at run time and design time. Property applies to TData control and TDataLite control.

The MouseIcon property specifies a custom icon that is used when the MousePointer property is set to 99 - Custom. This property is equivalent to the standard MouseIcon property of intrinsic Visual Basic controls.

Note: At design time, this property is not available in the property pages and must be set in the Visual Basic Properties window.

See Also

TData Control


MousePointer Property

The type of mouse pointer displayed when over the control.

Syntax

TData.MousePointer = value

Remarks

Read/Write at run time and design time. Property applies to TData control and TDataLite control.

Values
0 | Default
1 | Arrow
2 | Cross
3 | I-Beam
4 | Icon
5 | Size
6 | Size NE SW
7 | Size NS
8 | Size NW SE
9 | Size W E
10 | Up Arrow
11 | Hourglass
12 | No Drop
13 | Arrow and Hourglass
14 | Arrow and Question
15 | Size All
99 | Custom

This property returns or sets a value that indicates the type of mouse pointer to be displayed when the mouse is over the TData control.

Note: At design time, this property is not available in the property pages and must be set in the Visual Basic Properties window.

See Also

TData Control


NameSubstitute Property

Used in containers that don’t support the standard Name property (e.g., VC++)

Syntax

TData.NameSubstitute

Remarks

Read/Write at design time. Read-only at run time. Property applies to TData control.

This property is used in containers that don't support the standard Name property (or the equivalent Id property), such as in VC++ container.

This property is always ignored when True DataControl is used in Visual Basic, Visual InterDev or Visual J++.

In VC++, set this property to the control's name at design time. Use the string that would be its Name property in Visual Basic.

This property is necessary because VC++ container does not supply its own Name property, and True DataControl relies on Name for master-detail relationships.

See Also

TData Control


NamedBookmarks Property

Contains a collection of named bookmark objects, for Bookmarks button dialog.

Syntax

TData.NamedBookmarks

Remarks

Read-only at run time. Not available at design time. Property applies to TData control and TDataLite control.

This property returns a collection of NamedBookmark objects used in the Bookmarks Dialog.

See Also

TData Control


Orientation Property

Controls orientation, either horizontal or vertical.

Syntax

TData.Orientation = value

Remarks

Read/Write at run time and design time. Property applies to TData control and TDataLite control.

Design Time | Run Time
0 - Horizontal (default) | tdbHorizontal
1 - Vertical | tdbVertical

Determines control orientation, either horizontal or vertical.

Note: At design time, this property is not available in the property pages and must be set in the Visual Basic Properties window.

See Also

TData Control


PageSize Property

Sets/returns the number of records in a page.

Syntax

TData.PageSize = long

Remarks

Read/Write at run time and design time. Property applies to TData control and TDataLite control.

This property indicates how many records constitute one page in the Recordset. Default is 10.

This is a standard ADO recordset property. It can be set at any time during the control’s lifetime. As a recordset property, it does not have much use other than for clients that will want to query it for some reason.

TData control uses the PageSize property for its Previous Page and Next Page buttons. For more information, see True DataControl buttons.

Note: At design time, this property is not available in property pages and must be set in the Visual Basic Properties window.

See Also

TData Control


Parameters Property

Contains a collection of parameter objects.

Syntax

TData.Parameters

Remarks

Read-only at run time. Not available at design time. Property applies to TData control and TDataLite control.

This property returns a collection of Parameter objects. Every item in this collection defines a True DataControl parameter. See True DataControl Parameters for details.

See Also

TData Control


Password Property

For OLE DB providers that support password.

Syntax

TData.Password = string

Remarks

Read/Write at run time and design time. Property applies to TData control.

The TData control uses the Password property to establish the connection to a data source, for providers that require UserName and Password authorization,. Otherwise, it can be left empty (default). This property is relevant only for data source mode (DataMode = 0 – DataSource).

This is a standard ADO property. It can be set at any time during the control’s lifetime, but it will take effect only if set at design time, in WillOpenData event or after the Refresh method is called.

Note: At design time, this property is not available in the property pages and must be set in the Visual Basic Properties window.

See Also

TData Control


PooledConnectionCount Property

Returns the number of connections in the pool shared by all TData controls.

Syntax

TData.PooledConnectionCount = long

Remarks

Read-only at run time. Not available at design time. roperty applies to TData control.

This property returns the number of connection objects currently in the pool of connections shared by all TData controls. To retrieve a connection object from pool, use the PooledConnections property. See Connection pooling for details. Don’t use this property for any other purposes than to make sure the connection pool works as intended.

See Also

TData Control


PooledConnections Property

Returns connections in the pool shared by all TData controls.

Syntax

TData.PooledConnections(Index)

Remarks

Read-only at run time. Not available at design time. roperty applies to TData control.

Arguments: index is the number of connection, from 0 to PooledConnectionCount.

This property returns a connection object from the pool of connections shared by all TData controls. See Connection pooling for details. Don’t use this property for any other purposes than to make sure the connection pool works as intended.

See Also

TData Control


PropertyExpressions Property

Contains a collection of property expression objects.

Syntax

TData.PropertyExpressions

Remarks

Read-only at run time. Not available at design time. Property applies to TData control and TDataLite control.

This property returns a collection of PropertyExpression objects. See Control Property Expressions for details.

See Also

TData Control


QueryFilter Property

Returns the Filter string that can be applied to an ADO recordset, composed from user-supplied data in query mode.

Syntax

TData.QueryFilter

Remarks

Read-only at run time. Not available at design time. Property applies to TData control and TDataLite control.

This property returns the string generated from recordset data when the control is in query mode (see QueryMode property). The resulting string is an ADO filter that can be assigned to the Filter property of an ADO recordset.

See Query Mode for details.

See Also

TData Control


QueryMode Property

If true, the control is in query mode.

Syntax

TData.QueryMode = boolean

Remarks

Read/Write at run time and design time.
Property applies to TData control and TDataLite control.

If set to True, the TData control is in query mode. If set to True at design time, the control enters query mode on startup.

Setting this property to False terminates query mode, generates QueryFilter and applies the filter to the TData control.

This property can be set to True only in data source mode (DataMode = 0 – DataSource).

Default: False.

See Query Mode for details.

Note: At design time, this property is not available in the property pages and must be set in the Visual Basic Properties window.

See Also

TData Control


Recordset Property

Returns the ADO recordset object representing control’s data.

Syntax

TData.Recordset

Remarks

Read-only at run time. Not available at design time. Property applies to TData control and TDataLite control.

The Recordset property returns the ADO recordset object representing the TData control’s data, its recordset. This is a standard ADO recordset, so the programmer can use ADO recordset methods, such as Update, Delete, etc., to manipulate the TData control and its data. See Using the Recordset property for details.

The Recordset property is read-only, meaning you can’t set it in code. If you want to base a TData control on an existing ADO recordset object, set the SourceRecordset property.

See Also

TData Control


RecordSource Property

Source of recordset in data source mode: SQL, other command text or table name.

Syntax

TData.RecordSource = string

Remarks

Read/Write at run time and design time. Property applies to TData control.

The RecordSource property defines the textual description of the source of recordset in data source mode: SQL, other command text, table name, or stored procedure name. It is used when the TData control creates its SourceRecordset.

Interpretation of the RecordSource property, whether it is a table name, SQL statement, or a stored procedure name, depends on the CommandType property.

This property is relevant only for data source mode (DataMode = 0 – DataSource). It can be set at any time during the control’s lifetime, but it will take effect only if set at design time, in WillOpenData event or after the Refresh method is called.

See Also

TData Control


RefreshOnSrcChange Property

Determines whether SourceRecordset changes trigger refresh.

Syntax

TData.RefreshOnSrcChange = boolean

Remarks

Read/Write at run time and design time. Property applies to TData control and TDataLite control.

This property is True by default. Setting it to False disables automatic refresh of the TData control on changes to its SourceRecordset as a whole. If you call TData.SourceRecordset.Requery in code, or SourceRecordset changes in other ways (for example, if it is a detail recordset in master-detail relationship in VB DataEnvironment, and its master record changes), then TData automatically refreshes itself if RefreshOnSrcChange = False. Set this property to False if this is undesirable, for example, when you make multiple changes to the SourceRecordset and want to refresh TData only once, when all changes are completed.

Note: At design time, this property is not available in property pages and must be set in the Visual Basic Properties window.

See Also

TData Control


ResyncAfterUpdate Property

Determines whether to call SourceRecordset.Resync immediately after SourceRecordset.Update.

Syntax

TData.ResyncAfterUpdate = boolean

Remarks

Read/Write at run time and design time. Property applies to TData control and TDataLite control.

This property is False by default. Set it to True if you want TData to call SourceRecordset.Resync(adAffectCurrent, adResyncAllValues) immediately after sending data to the database (calling SourceRecordset.Update).This is useful when saving data in the database can change some field values. For example, if you use an autoincrement field (AutoNumber in MS Access, newid() function in SQL Server) with TData.CursorLocation = adUseClient, you won't see the new value unless TData.ResyncAfterUpdate = True.

Note: At design time, this property is not available in property pages and must be set in the Visual Basic Properties window.

See Also

TData Control


SafeMode Property

If True, ADO recordsets are used with extra caution, avoiding certain problems in various OLE DB providers.

Syntax

TData.SafeMode = boolean

Remarks

Read/Write at run time and design time. Property applies to TData control.

This property is False by default, and you don’t need to bother about it unless you experience problems. This property can be used with CursorLocation = adUseServer to work around problems with some OLE DB providers. Some of OLE DB provider problems are avoided regardless of the SafeMode value. Others require extra activity that can hamper performance, so this activity takes place only if SafeMode is set to True. See Fixing problems with adUseServer for more information.

This property has effect only if DataMode = 0 – DataSource and CursorLocation = adUseServer.

If SafeMode is set to True, TData uses SourceRecordset with extra caution, avoiding OLE DB provider problems.

For example, avoiding provider problems occuring with non-empty Recordset.Filter incurs a performance penalty, so it is necessary to set SafeMode to True in this case.

There are some provider problems that TData is unable to avoid.

Note: At design time, this property is not available in property pages and must be set in the Visual Basic Properties window.

See Also

TData Control


SourceConnection Property

Sets/returns the ADO connection used to connect to underlying data in data source mode.

Syntax

TData.SourceConnection

Remarks

Read/Write at run time. Not available at design time. Property applies to TData control.

This property can be used to optimize database resource consumption in DataMode = 0 - DataSource when the default connection pooling does not apply. It is a run-time only property, with read/write access. You can set this property to an ADO Connection object created in code. Then TData will use that connection object when it creates its SourceRecordset.

You can create a single Connection object (or several such objects) in code and assign it to each TData's SourceConnection property. Then they will all share the same database connection.

As with SourceRecordset, there are two possible ways to set the SourceConnection property:

•

You can set it in OpenData event, or

•

You can set it from code outside of any TData events. In this case, setting SourceConnection will trigger immediate refresh unless you enclose it in TData.ChangeInProgress=True/False.

If you set SourceConnection and don't set SourceRecordset, TData will create SourceRecordset based on its current data source property settings, using the Connection object you specified.

If you set SourceRecordset in your code, then don't set SourceConnection. There is no need for that since a recordset you created in code is already attached to a specific connection.

See Also

TData Control


SourceRecordset Property

Sets/returns the ADO recordset used as underlying data in data source mode.

Syntax

TData.SourceRecordset

Remarks

Read/Write at run time. Not available at design time. Property applies to TData control.

The SourceRecordset property can be used only in data source mode (DataMode = 0 – DataSource). It sets/returns the ADO recordset, source of underlying data.

It is important to distinguish between SourceRecordset and Recordset properties:

•

Recordset is the actual data exposed by the TData control to its clients, whereas SourceRecordset is the data source, database where TData control gets and stores its data.

•

Recordset exists in all three data mode. SourceRecordset only has sense for DataMode = 0 – DataSource.

•

Recordset can contain more fields than SourceRecordset. Calculated fields are not part of SourceRecordset.

•

If you need to operate on the TData control’s data, or set/retrieve the current row bookmark, you must use the Recordset property, not SourceRecordset.

SourceRecordset is created by True DataControl automatically if all data source properties are specified correctly. Alternatively, SourceRecordset can be set to an ADO recordset in the OpenData event.

Setting SourceRecordset in code outside TData events refreshes the TData control. It is not allowed to set SourceRecordset in TData events other than OpenData.

See Data Source Mode for details.

See Also

TData Control


Tooltips Property

Determines if the button tooltips are enabled.

Syntax

TData.Tooltips = boolean

Remarks

Read/Write at run time and design time. Property applies to TData control and TDataLite control.

This property determines if the button tooltips are enabled.

When set to True, the TData control shows button tooltips.

If set to False, tooltips are invisible.

See Repeat feature and tooltips for details.

Note: At design time, this property is not available in the property pages and must be set in the Visual Basic Properties window.

See Also

TData Control


UserName Property

For OLE DB providers that support user name.

Syntax

TData.UserName = long

Remarks

Read/Write at run time and design time. Property applies to TData control.

The TData control uses the UserName property to establish the connection to a data source, for providers that require UserName and Password authorization. Otherwise, it can be left empty (default). This property is relevant only for data source mode (DataMode = 0 – DataSource).

This is a standard ADO property. It can be set at any time during the control’s lifetime, but it will take effect only if set at design time, in WillOpenData event or after the Refresh method is called.

Note: At design time, this property is not available in the property pages and must be set in the Visual Basic Properties window.

See Also

TData Control


XTab Property

If true, the control is used in crosstab mode.

Syntax

TData.XTab = boolean

Remarks

Read/Write at design time. Read-only at run time. Property applies to TData control and TDataLiteconotrol starting from version 7.0.

Setting this property to True enables crosstab mode.

For more information, see Crosstab (matrix) data presentation.

See Also

TData Control


XTabColKey Property

For crosstab mode, comma-delimited list to key fields defining crosstab columns.

Syntax

TData.XTabColKey = string

Remarks

Read/Write at design time and at run time. Property applies to TData control and TDataLiteconotrol starting from version 7.0.

This property applies to crosstab mode. It specifies column key fields, the semicolon-separated list of fields defining cross tab columns. Records with different column key values are displayed in different columns. For example, if TData1.XTabColKey = “Month“, each month occupies a separate column. There can be multiple column key fields, for example TData1.XTabColKey = “Year;Month”.

For more information, see Crosstab (matrix) data presentation.

See Also

TData Control


XTabCollate Property

For crosstab mode with multiple crosstab fields, if set to True, makes all columns for one field appear after all columns for another.

Syntax

TData.XTabCollate = boolean

Remarks

Read/Write at design time and at run time. Property applies to TData control and TDataLiteconotrol starting from version 7.0.

This property applies to crosstab mode. It only has effect when there are more than one crosstab columns. In that case, if XTabCollate = False (default), the crosstab columns generated by different fields are interspersed, that is, the corresponding columns are grouped by the column key value, every group containing all fields with that key value. If XTabCollate = True, the columns are grouped by the main field, that is, all columns generated by the first field apear first, then all columns generated by the second fields, and so on.

For more information, see Crosstab (matrix) data presentation.

See Also

TData Control


XTabRowKey Property

For crosstab mode, comma-delimited list of primary key fields defining crosstab rows.

Syntax

TData.XTabRowKey = string

Remarks

Read/Write at design time and at run time. Property applies to TData control and TDataLiteconotrol starting from version 7.0.

This property applies to crosstab mode. It specifies row key fields, the semicolon-separated list of fields defining cross tab rows. Different records with the same row key values (they can differ by their column key values) belong to the same crosstab row. For example, if TData1.XTabRowKey = “CustomerID“, each customer is displayed in a different row, but multiple records differing only by their Month (column key) value are displayed in the same customer row. There can be multiple row key fields, for example, TData1.XTabRowKey = “DepartmentID;CustomerID”

For more information, see Crosstab (matrix) data presentation.

See Also

TData Control


XTabSeparateFields Property

For crosstab mode, if set to True, exposes crosstab columns as independent fields at design time.

Syntax

TData.XTabSeparateFields = boolean

Remarks

Read/Write at design time and at run time. Property applies to TData control and TDataLiteconotrol starting from version 7.0.

This property applies to crosstab mode. controls the way crosstab columns are exposed to True DBGrid control at design time. With bound controls other than ComponentOne True DBGrid (version 7.0 or better), If XTabSeparateFields is always considered True.

If set to False (default), TDBGrid will see a single field (for every crosstab field) at design time in its property pages (but it will display all crosstab columns properly). In most cases, it is convenient to set up all crosstab columns with identical settings. All settings of the corresponding column will be applied to all crosstab columns it generates. This propagation of settings to all crosstab columns takes place only at design time. At run time, crosstab columns can resized and their properties can be changed independently, regardless of the XTabSeparateFields value.

If this property is set to True, TDBGrid will see crosstab columns as separate data fields, so they can be set up separately.

See also: For more information, see Crosstab (matrix) data presentation.

See Also

TData Control


TData Control Methods

ArrayIndexToBookmark Method

BookmarkToArrayIndex Method

ButtonEnabled Method

CancelUpdate Method

Drag Method

EnableButton Method

Move Method

PressButton Method

Refresh Method

RaiseError Method

RetrieveFields Method

SetButtonPicture Method

SetUIString Method

ShowWhatsThis Method

UpdateFields Method

ZOrder Method


ArrayIndexToBookmark Method

Converts array index to bookmark in memory array mode.

Syntax

TData.ArrayIndexToBookmark Index

Remarks

Method applies to TData control and TDataLite control.

Arguments: Index is a Long integer specifying a row index in the XArrayDB object, between LowerBound and UpperBound.

Return Value: Variant representing the bookmark of the row identified by the Index argument.

This method is relevant only for DataMode = 1 - MemoryArray. Given a row index in the XArrayDB object, it returns the bookmark that corresponds to that row. If such index does not exist, the method returns empty variant.

Bookmarks in memory array mode are Long numbers, but the bookmark of a row can be different from its index if some rows were deleted from the XArrayDB object.

The BookmarkToArrayIndex method performs inverse conversion.

See Also

TData Control


BookmarkToArrayIndex Method

Converts bookmark to array index in memory array mode.

Syntax

TData.BookmarkToArrayIndex Bookmark

Remarks

Method applies to TData control and TDataLite control.

Arguments: Bookmark is a variant identifying a row in the True DataControl Recordset in memory array mode.

Return Value: Long integer index of the row in the XArrayDB object , between LowerBound and UpperBound.

This method is relevant only for DataMode = 1 - MemoryArray. Given a row bookmark, it returns corresponding index in the XArrayDB object. If the bookmark does not identify an existing row, the method returns LowerBound - 1.

Bookmarks in memory array mode are Long numbers, but the bookmark of a row can be different from its index if some rows were deleted from the XArrayDB object.

The ArrayIndexToBookmark method performs inverse conversion.

See Also

TData Control


ButtonEnabled Method

Returns the enabled state of a control button.

Syntax

TData.ButtonEnabled Index

Remarks

Method applies to TData control and TDataLite control.

Arguments: Index is one of the TDButtonEnum constants, identifying a button of the True DataControl, see EnableButton method.

Return Value: Returns boolean value: True if the button is enabled, False if it is disabled.

This method can be used if the developer wants to implement actions of TData buttons in custom command buttons or other controls. This method, together with the ButtonStateChanged event, allows the developer to enable/disable command buttons and other controls under exactly the same circumstances when standard TData buttons are enabled/disabled.

See also: EnableButton method, ButtonStateChanged event, True DataControl Buttons.

See Also

TData Control


CancelUpdate Method

Enhanced version of ADO CancelUpdate, includes resetting bound controls.

Syntax

TData.CancelUpdate

Remarks

Method applies to TData control.

Arguments: None

Return Value: None

This method is an improved version of the standard ADO CancelUpdate/CancelBatch methods. These standard methods have a deficiency that the True DataControl CancelUpdate method corrects.

First, it does what the standard ADO method does; it cancels all pending changes. In batch update mode (TData.LockType=adLockBatchOptimistic), it cancels changes made to any rows after the last Recordset.UpdateBatch call. When not in batch update mode, it cancels changes made to the current record after the last Recordset.Update call. (These two cases are actually equal, since non-current rows can have pending changes only in batch update mode).

Next, the True DataControl CancelUpdate method reverts all changes made in bound controls that have not yet been sent to the recordset. This covers an important case, when the end-user has modified the value of a field in a bound control, but that value has not yet been assigned to the field. The most common occurance of this is when the value is invalid; the field does not accept it. There are no changes made to Recordset yet, so Recordset.CancelUpdate does nothing. On the other hand, the user obviously expects it to replace the invalid value with the current data source value. That's what TData.CancelUpdate does, it refreshes all bound controls with the current data source values, regardless of any other circumstances.

See Also

TData Control


Drag Method

Begins, ends, or cancels a drag operation of the control.

Syntax

TData.Drag [action]

Remarks

Method applies to TData control.

Arguments: action is an optional constant or value that specifies the action to perform.

Return Value: None

This method operates like the standard Drag method of intrinsic Visual Basic controls. It begins, ends, or cancels a drag operation of a TData control.

See Also

TData Control


EnableButton Method

Sets the enabled state of the button.

Syntax

TData.EnableButton Index, Enabled

Remarks

Method applies to TData control and TDataLite control.

Arguments: Index is one of the TDButtonEnum constants, identifying a button of the True DataControl.

Enabled is one of the three TDButtonEnum constants, indicating the enabled state of a button.

Return Value: None

This method allows you to control the enabled state of a button, which is identified by one of the following constants (TDButtonEnum) specified by the Index argument:

0 – tdbButtonFirst

1 - tdbButtonPrevious

2 - tdbButtonNext

3 - tdbButtonLast

4 - tdbButtonNextPage

5 - tdbButtonPrevPage

6 - tdbButtonAdd

7 - tdbButtonDelete

8 - tdbButtonUpdate

9 - tdbButtonCancel

10 - tdbButtonBookmarks

11 - tdbButtonFind

12 - tdbButtonQuery.

The enabled state of the button is one of the following constants (TDButtonEnabledEnum) specified by the Enabled argument:

0 – tdbButtonEnabled

Unconditionally enables the button.

1 - tdbButtonDisabled

Unconditionally disables the button.

2 - tdbButtonEnabledDefault

Defers to True DataControl to

enable/disable the button accoding to

the current circumstances. For example,

the Update button is enabled if a record

has been modified.

By default, if you don't call the EnableButton method from code, all buttons behave as bwButtonEnabledDefault.

For more information, see True DataControl Buttons.

See Also

TData Control


Move Method

Moves the position of the control on the form.

Syntax

TData.Move left, top, width, height

Remarks

Method applies to TData control and TDataLite control.

Arguments: left, top, width, and height are integers that specify the new position and size of the control.

Return Value: None

This method operates like the standard Move method of intrinsic Visual Basic controls. It moves the control (changes its geometric coordinates) relative to its parent control or form.

See Also

TData Control


PressButton Method

Invokes the action of a control’s button.

Syntax

TData.PressButton Index

Method applies to TData control and TDataLite control.

Arguments: Index is one of the TDButtonEnum constants, identifying a button of the TData control.

Return Value: None

This method allows you to perform the action associated with a True DataControl button. It can be called even if the button is invisible or disabled. The ButtonPressed event is not fired by a call to PressButton.

The button is identified by one of the following constants (TDButtonEnum) specified by the Index argument:

0 – tdbButtonFirst

1 - tdbButtonPrevious

2 - tdbButtonNext

3 - tdbButtonLast

4 - tdbButtonNextPage

5 - tdbButtonPrevPage

6 - tdbButtonAdd

7 - tdbButtonDelete

8 - tdbButtonUpdate

9 - tdbButtonCancel

10 - tdbButtonBookmarks

11 - tdbButtonFind

12 - tdbButtonQuery

For more information, see True DataControl Buttons.

See Also

TData Control


Refresh Method

Refetches all data.

Syntax

TData.Refresh [NoEvents]

Remarks

Method applies to TData control and TDataLite control.

Arguments: NoEvents is an optional Boolean argument that controls event firing during a refresh. The default value is False.

Return Value: None

This method refreshes the TData control Recordset by refetching all data from the data source. The TData control positions on the first row after a refresh.

In DataMode = 0 - DataSource, the Refresh method re-establishes the database connection if at least one of the data source properties of the TData control has been changed. Otherwise, it just refetches the data from SourceRecordset. This can be useful if you need to synchronize TData with somehow changed contents of SourceRecordset. If you need to synchronize with the changes made to the database by other users, bear in mind that the Refresh method will not do that automatically, since such changes are not yet reflected in SourceRecordset. To ensure that TData shows the latest state of the database, use Refresh in conjunction with the ADO Requery method:

TData1.SourceRecordset.Requery

TData1.Refresh True

If the NoEvents argument is False (default), the WillOpenData, OpenData and OpenDataComplete events are fired in the refresh. If NoEvents argument is True, no events are fired; the TData control refreshes its recordset and notifies all bound controls about the change.

When the Refresh method is called, the TData control re-establishes the database connection if necessary (if data source properties have changed). Before doing this, if NoEvents=False (default), it fires the WillOpenData event. If the code in WillOpenData changes collections, TData adjusts itself to the new collection settings. Then the OpenData event is fired. The OpenData event gives you an opportunity to set the SourceRecordset property to a desired recordset (or to set the Array property in DataMode = 1 - MemoryArray). After that, the source recordset is re-queried or recreated, if necessary. Once all of this is done, the OpenDataComplete event fires.

A special case of the Refresh method is when it is called with NoEvents=True (Refresh True). Then no events are fired. This case is useful when the programmer knows that underlying data have changed, but all the TData control settings remain the same. For example, in DataMode = 1 - MemoryArray, after modifying the XArrayDB object in code, Refresh True should be called to refresh data shown in the TData control. An exception to this rule is when the change is made in the OpenData event, in which case you should not call Refresh. A refresh with NoEvents = True can be used in other data modes too. In DataMode = 2 - UserEvents, it should be called after some intrinsic data or state changes, to refetch the data. It can also be used in DataMode = 0 - DataSource, to reflect changes made to the SourceRecordset, although it is rarely needed. Most changes made to SourceRecordset, e.g., setting Filter or Sort, are reflected by the TData control automatically.

You do not have to call Refresh after making changes to True DataControl collections, since the refresh will occur automatically, see Modifying True DataControl collections from code.

See Also

TData Control


RaiseError Method

Used to specify error description in user mode events.

Syntax

TData.RaiseError (ErrorNumber, Source, Description, [HelpFile], [HelpContext])

Remarks

Method applies to TData control.

Arguments: ErrorNumber is a Long integer that identifies the nature of the error.

Source is a string naming the object or application that generated the error.

Description is a string describing the error.

HelpFile is an optional string containing the fully qualified path to the help file in which help on this error can be found.

HelpContext is an optional Long integer, the context ID identifying a topic within helpfile that provides help for the error.

Return Value: None

This method can be used in user events mode (DataMode = 2 – UserEvents) event procedures to describe an error detected while performing operations with a customized data source. Intended for use in the following events: UserReadData, UserWriteData, UserAddData, UserDeleteRow, UserFindData.

See Also

TData Control


RetrieveFields Method

Retrieves field layout from the source recordset.

Syntax

TData.RetrieveFields

Remarks

Method applies to TData control and TDataLite control.

Arguments: None

Return Value: None

The RetrieveFields method removes all fields from the and retrieves field definitions from the SourceRecordset.

This method is only allowed when DataMode = 0 (tdbModeDataSource). It is illegal to call RetrieveFields from any TData event procedure.

Calling RetrieveFields changes TData collections (namely, the Fields collection). According to general rules, that means you will need to set TData1.ChangeInProgress = True before doing that, and set TData1.ChangeInProgress = False once you are done with all changes, unless retrieving fields is meant to be the only change before TData automatically refreshes.

The method is useful in situations where the fields are not known beforehand, at design time, and it is necessary to change some collection settings once the SourceRecordset property is set: either modify field definitions retrieved from SourceRecordset, or to adjust some settings, e.g., expressions, to the retrieved fields. If RetrieveFields is not called, TData retrieves fields from SourceRecordset automatically when it refreshes. If you want control over this process, call RetrieveFields explicitly after you set SourceRecordset, then you will be able to adjust collection settings to the newly retrieved fields before TData refreshes (TData will not retrieve fields on refresh if RetrieveFields was called explicitly).

Private Sub Form_Load()

Dim cn As New ADODB.Connection

Dim rs As New ADODB.Recordset

TData1.ChangeInProgress = True

cn.CursorLocation = adUseClient

cn.Open ("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Program Files\ComponentOne Studio\Common\TDBGDemo.mdb;Persist Security Info=False")

rs.Open "Customers", cn, adOpenStatic, adLockOptimistic, adCmdTable

Set TData1.SourceRecordset = rs

TData1.RetrieveFields

TData1.Fields("CustomerID").Visible = False

TData1.ChangeInProgress = False

Set DataGrid1.DataSource = TData1

End Sub

See Also

TData Control


SetButtonPicture Method

Changes the picture on a button.

Syntax

TData.SetButtonPicture Index, Enabled, Picture

Remarks

Method applies to TData control and TDataLite control.

Arguments: Index is one of the TDButtonEnum constants, identifying a button of the TData control.

Enabled is a Boolean value. Setting it to True indicates that the specified picture must be used when the button is enabled, False means the picture is used when the button is disabled.

Picture is a variant value containing the picture image. It can be obtained from the LoadPicture function.

Return Value: None

This method allows you to customize the picture for a button identified by one of the following constants (TDButtonEnum) specified by the Index argument:

0 - tdbButtonFirst

1 - tdbButtonPrevious

2 - tdbButtonNext

3 - tdbButtonLast

4 - tdbButtonNextPage

5 - tdbButtonPrevPage

6 - tdbButtonAdd

7 - tdbButtonDelete

8 - tdbButtonUpdate

9 - tdbButtonCancel

10 - tdbButtonBookmarks

11 - tdbButtonFind

12 - tdbButtonQuery

You need to supply two images for each button that you choose to customize. Call SetButtonPicture twice, with the Enabled argument set to True and False. One image is used when the button is enabled, the other when it is disabled.

See Also

TData Control


SetUIString Method

Changes a string shown to the end-user.

Syntax

TData.SetUIString Index, text

Remarks

Method applies to TData control and TDataLite control.

Arguments: Index is one of the TDStringEnum constants, identifying a string that appears in the True DataControl end-user interface (button tooltips, Find and Bookmarks dialogs, confirmation and error messages).

text is a String value that is substituted instead of the standard TData control string for the particular user-interface element identified by the Index argument.

Return Value: None

This method allows you to customize and/or localize (for languages other than English) any string presented by the TData control to the end-user. The only exception is the message box caption, which is governed by a special property, ErrorMsgCaption.

TDStringEnum is a big enumeration listing all True DataControl user interface strings. The following is the list of possible Index values:

Prompt strings: tdbStringRestorePrompt = 0

Prompt to restore the field's previous value, appearing in the error message on field errors: "Do you want to restore the previous value?".

Button tooltips:

tdbStringTooltipFirst = 1,

tdbStringTooltipPrevious = 2,

tdbStringTooltipNext = 3,

tdbStringTooltipLast = 4,

tdbStringTooltipNextPage = 5,

tdbStringTooltipPrevPage = 6,

tdbStringTooltipAdd = 7,

tdbStringTooltipDelete = 8,

tdbStringTooltipUpdate = 9,

tdbStringTooltipCancel = 10,

tdbStringTooltipBookmarks = 11,

tdbStringTooltipFind = 12,

tdbStringTooltipQuery = 13

Confirmation messages:

tdbStringConfirmDelete = 14,

tdbStringConfirmCancel = 15

Control captions in the Bookmarks dialog:

tdbStringBookmarksCaption = 16,

tdbStringBookmarksNameLabel = 17,

tdbStringBookmarksAdd = 18,

tdbStringBookmarksDelete = 19,

tdbStringBookmarksGoto = 20,

tdbStringBookmarksCancel = 21

Information messages:

tdbStringFindNotFound = 22

Text of the "not found" message appearing in the Find dialog: "The search item was not found".

Control captions in the Find dialog:

tdbStringFindCaption = 23,

tdbStringFindFieldLabel = 24,

tdbStringFindWhatLabel = 25,

tdbStringFindMatchLabel = 26,

tdbStringFindSearchLabel = 27,

tdbStringFindMatchCase = 28,

tdbStringFindFirst = 29,

tdbStringFindNext = 30,

tdbStringFindCancel = 31

tdbStringFindMatchEqual = 32,

tdbStringFindMatchGreaterOrEqual = 33,

tdbStringFindMatchGreater = 34,

tdbStringFindMatchLessOrEqual = 35,

tdbStringFindMatchLess = 36,

tdbStringFindMatchStartsWith = 37,

tdbStringFindMatchContains = 38,

tdbStringFindSearchUp = 39,

tdbStringFindSearchDown = 40,

tdbStringFindSearchAll = 41

See Also

TData Control


ShowWhatsThis Method

Displays the appropriate help topic for the control.

Syntax

TData.ShowWhatsThis

Remarks

Method applies to TData control and TDataLite control.

Arguments: None

Return Value: None

This method operates like the standard ShowWhatsThis method of intrinsic Visual Basic controls. It displays a selected topic in a help file using the What's This popup.

See Also

TData Control


UpdateFields Method

Updates the recordset with modified values from bound controls.

Syntax

TData.UpdateFields

Remarks

Method applies to TData control.

Arguments: None

Return Value: None

The UpdateFields method gives you functionality that is absent in the ADO data control (Microsoft ADODC). If the end-user has changed the value in a bound control, calling UpdateFields will send this pending change to the TData control Recordset and set the corresponding field.

Unless you call this method, the field is updated in accordance with its ModificationMode property: on every change in the control, if ModificationMode = 1 – Immediate; when the control loses focus, if ModificationMode = 2 – Leaving control; when the user leaves current record, if ModificationMode = 0 – None.

See Also

TData Control


ZOrder Method

Places the control at the front or back of the z-order.

Syntax

TData.ZOrder position

Remarks

Method applies to TData control and TDataLite control.

Arguments: position is an integer that specifies the z-order (0 = front, 1 = back).

Return Value: None

This method operates like the standard ZOrder method of intrinsic Visual Basic controls. It places the TData control at the front or back of the z-order within its graphical level.

See Also

TData Control


TData Control Events

ButtonPressed Event

ButtonStateChanged Event

CalcFields Event

CalcFieldsComplete Event

DataRead Event

DataWrite Event

Error Event

FieldChangeComplete Event

Filter Event

FilterComplete Event

GetBookmarkName Event

MoveComplete Event

OpenData Event

OpenDataComplete Event

RecordChangeComplete Event

RecordsetChangeComplete Event

UserAddData Event

UserDeleteRow Event

UserFindData Event

UserReadData Event

UserWriteData Event

WillChangeField Event

WillChangeRecord Event

WillChangeRecordset Event

WillMove Event

WillOpenData Event


ButtonPressed Event

Occurs when a control button is pressed.

Syntax

TData_ButtonPressed (ByVal Button As TrueData60Ctl.TDButtonEnum, Cancel As Boolean)

Remarks

Arguments: Button identifies the button pressed by the end-user, with the following codes:

0 – tdbButtonFirst

1 - tdbButtonPrevious

2 - tdbButtonNext

3 - tdbButtonLast

4 - tdbButtonNextPage

5 - tdbButtonPrevPage

6 - tdbButtonAdd

7 - tdbButtonDelete

8 - tdbButtonUpdate

9 - tdbButtonCancel

10 - tdbButtonBookmarks

11 - tdbButtonFind

12 - tdbButtonQuery

Cancel is a boolean variable. It is True when the event procedure is called. It can be set to False to cancel the standard action associated with the button.

The ButtonPressed event occurs when a TData control’s button is pressed by the end-user, before the button action is performed. If you prefer to execute your own action instead of the standard one, set Cancel = True, as this will cancel the standard action associated with the button.

For more information, see True DataControl buttons.

See Also

TData Control


ButtonStateChanged Event

Occurs when a control button’s enable state changes.

Syntax

TData_ButtonStateChanged ( )

Remarks

Arguments: None

The ButtonStateChanged when a control’s button state changes, when it becomes enabled or disabled.

For more information, see True DataControl buttons.

See Also

TData Control


CalcFields Event

Occurs before calculated field expressions are evaluated.

Syntax

TData_CalcFields ( )

Remarks

Arguments: None

The CalcFields event occurs before calculated expressions are evaluated. You can use this event to calculate field values using complex algorithms that cannot be specified by the CalculatedExpression property of a Field object. Use the collection returned by the Fields property to assign values to such calculated fields.

For more information, see True DataControl Fields.

See Also

TData Control


CalcFieldsComplete Event

Occurs after calculated field expressions have been evaluated.

Syntax

TData_CalcFieldsComplete ( )

Remarks

Arguments: None

The CalcFieldsComplete event occurs immediately after all calculated expressions have been evaluated. It is provided primarily for debugging purposes. By setting a breakpoint in this event, you can examine field values in the Fields collection (returned by the Fields property) and see whether your calculated expressions yielded the intended results.

For more information, see True DataControl Fields.

See Also

TData Control


DataRead Event

Occurs immediately after retrieving a row of values from the data source.

Syntax

TData_DataRead (ByVal Bookmark As Variant, Values As Variant)

Remarks

Arguments: Bookmark indicates the row that was fetched from the data source. It can be ignored in most simple cases.

Values is an array of field values retrieved from the fetched row. It is a one-dimensional array indexed with an integer number from 0 to TData.Fields.Count. Values(n) represents the value of the n-th field in the TData control.

The DataRead event allows the developer to modify field values when they are retrieved from the data source. It can be used for formatting and other similar purposes, when data is stored in a form different from what you want to present to TData and its users. If you modify some field values in the Values array, TData will consider those modified values retrieved from the data source. The original, unmodified values will not appear in TData in any way.

The DataRead event occurs only if the CallDataRead property is set to True. It is False by default, so you have to change that property to True if you intend to use DataRead.

For more information, see Modifying Field Values Retrieving and Saving Them in the Data Source.

See Also

TData Control


DataWrite Event

Occurs immediately before saving changed values to the data source.

Syntax

TData_DataWrite (Bookmark As Variant, Values As Variant, ByVal NewRow As Boolean, ByVal Update As Boolean, Done As Boolean, Cancel As Boolean)

Remarks

Arguments: Bookmark indicates the row that is going to be saved in the data source.

Values is an array of field values being saved. It is a one-dimensional array indexed with an integer number from 0 to TData.Fields.Count. Values(n) represents the modified value of the n-th field in the TData control. If Value(n) is Empty variant, that means that the n-th field is unchanged, its value is not going to be modified in the data source.

NewRow indicates whether this row is a new row that is being added to the data source (NewRow=True) or a row that already exists in the data source is being modified (NewRow=False).

Update indicates whether this row is written to the data source (Update=True, when an existing row is modified or a new row is written to the data source), or to an internal buffer (Update=False, when a field is being modified, before update to the datasource, or when a new row is created but is not yet updated to the data source).

Done is a flag that can be set to True if you want to override the default action, saving of the row in the data source. If you set Done to True in the event procedure, TData does not modify the data source assuming you have already done what is needed in the event procedure. The Done flag can only be set if Update=True. If Update=False, TData is not saving changes in the data source, so it ignores the Done flag, does not allow you to override the action.

Cancel is a flag that can be set to True to indicate an error condition. You can set it to True either to reject the field values presented for update, due to some validation rule violation, or, if you override TData action by setting Done=True, to inform TData that an error has occurred when you tried to save data.

The DataWrite event allows the developer to modify field values before they are stored in the data source. It can be used for two different purposes:

•

Storing field values differently from how they are presented to the user (in conjunction with DataRead). To do that, change values in the Values array to those that you want to be written to the data source. If Update=True, then even if a field’s value has not been changed by the user (the corresponding Value element is Empty), you can set that Value element thus making TData modify that field’s value in the data source.

•

Overriding the default action of saving changes to the database, if some more involved action than just updating a recordset record is needed.

It is important to understand that changes made in DataWrite are not reflected in TData fields and expressions. They are only applied to the values written to the data source, they do not persist in TData control in any way.

For more information, see Modifying Field Values Retrieving and Saving Them in the Data Source.

See Also

TData Control


Error Event

Occurs as a result of an error that takes place when no user code is being executed.

Syntax

TData_Error (ByVal ErrorNumber As Long, Description As String, ByVal Scode As Long, ByVal FieldName As String, ByVal Source As String, ByVal HelpFile As String, ByVal HelpContext As Long, fCancelDisplay As Boolean)

Remarks

Arguments: ErrorNumber is the error code, an integer that identifies the error that occurred.

Description is a string describing the error.

Scode is the status code of the error (usually can be ignored).

FieldName contains the name of the affected field, if the error occured while trying to modify a field value,

Source is a stirng identifying the source of the error. It is either “TData”, meaning that the error is TData-specific (see below), or a string identifying an OLE DB provider.

HelpFile is a string containing the fully qualified path to the help file in which help on this error can be found. This argument can be left empty by the provider, meaning there is no help file.

HelpContext is a Long integer, the context ID identifying a topic within helpfile that provides help for the error. This argument can be set to 0 by the provider, meaning there is no help for this error.

fCancelDisplay is a variable that you can set to True (it is set to False initially) to suppress the standard TDataerror message box.

The Error event is similar to its counterpart in the standard ADO data control (Microsoft ADODC). That is, it occurs as the result of an error that takes place when the TData control is responding to user interaction, but no Visual Basic code is being executed.

Even if your application handles run-time errors in code, errors can still occur when none of your code is executing, such as when the user changes the current record by interacting with a bound control. If a data access error results from such an action, the Error event is fired.

If you set the fCancelDisplay argument to True, the standard True DataControl error message will not be displayed.

If the fCancelDisplay argument retains its default value of False, or you do not code a handler for this event, the standard message associated with the error will be displayed.

Error Codes: The following error codes are specific to True DataControl. For each such error, the ErrorNumber argument contrains the error code, the Source argument contains “TData” string, and the Description argument contains an error description.

2000 | Field constraint violation. FieldName indicates the affected field.
2001 | Record constraint violation.
2002 | Required field is left empty. FieldName indicates the affected field.
2003 | Data type conversion error: data entered by the user in a bound control is invalid with respect to the field’s data type. FieldName indicates the affected field.
2005 | Field is read-only. An attempt has been made to change the value of a read-only field. FieldName indicates the affected field.
2006 | Data type conversion error: the new value assigned to a field programmatically is invalid with respect to the field’s data type. FieldName indicates the affected field.
2008 | An attempt has been made to change TData collections in an event other than WillOpenData.
2009 | An attempt has been made to set SourceRecordset or Array in an event other than OpenData.
2010 | Creation of SourceRecordset failed, due to incorrect data source property settings or an error while creating the recordset by the OLE DB provider.
2011 | An attempt to set QueryMode = True while DataMode is not 0 - DataSource.
2012 | An invalid bookmark is set to the RowBuffer object in the UserReadData event procedure. All bookmarks returned by the programmer in DataMode = 2 – UserEvents should have the same variant data type.
2013 | RetrieveFields method has been called with DataMode other than 0 - DataSource.
2014 | This action is not allowed in TData event procedures.
2015 | An attempt has been made to set SourceConnection in an event other than OpenData.
2016 | An attempt has been made to set the SourceConnection property when SourceRecordset has already been set or created by TData.

Other error codes can occur in data source mode (DataMode = 0 – Data Source), They are data access errors that originate in the underlying SourceRecordset, reported by the OLE DB provider that supports your data connection. You can identify the provider by the value of the Source argument passed to the event procedure.

See Also

TData Control


FieldChangeComplete Event

Occurs after a field value has changed.

Syntax

TData_FieldChangeComplete (ByVal cFields As Long, ByVal Fields As Variant, ByVal pError As ADODB.Error, adStatus As EventStatusEnum)

Remarks

Arguments: cFields is the number of fields that have changed their values. In True DataControl version 8.0, this is always one, but we recommend not assuming this. It is better to write general code that can accommodate changing several fields at once.

Fields is an array of ADO Field objects, which are items of the Recordset.Fields collection. In True DataControl version 8.0, it always contains one element, Fields(0). Fields(0).Name is the name of the field that has changed its value.

pError is an ADO Error object. It describes the error that occurred if the value of adStatus is adStatusErrorsOccurred; otherwise it is not set.

adStatus is an ADO EventStatusEnum value, with two possible values: adStatusOK if the operation that caused the event was successful, or adStatusErrorsOccurred if the operation failed.

The FieldChangeComplete event is a standard ADO Recordset event fired by the TData control’s Recordset. For more information, see Using recordset events. As with any ADO recordset, this event occurs after the value of one or more fields has changed. It is also fired when an operation has attempted to change one or more fields and failed. This case can be detected by the value of the adStatus argument, which is set to adStatusErrorsOccurred if the operation failed.

This event fires after TData has completed all actions necessitated by the field change. For example, suppose that A is a data field and B is a calculated field that depends on the value of A. If the user changes the value of A, the value of B will have been updated by the time the FieldChangeComplete event fires. You can use this event to perform additional processing at that point.

See Also

TData Control


Filter Event

Occurs before filter expressions are evaluated.

Syntax

TData_Filter (Result As Integer)

Remarks

Arguments: Result is a boolean that can be set to False to exclude the current record from the result set.

The Filter event occurs after each record is fetched from the database but before it is tested against any of the TData filter expressions specified at design time. You can use this event to impose complex filter conditions that cannot be specified by filter expressions. See Filters for details.

When this event fires, Result is set to True, indicating that the current record will be included in the result set. Your event handler should examine field values in the Fields collection (returned by the Fields property) to determine whether the record meets your selection criteria. Setting Result to False effectively excludes the record from the Recordset without further evaluation of TData filter expressions.

Notes: You can only exclude records in this event. You cannot explicitly include records that are rejected by the TData filter. At run time, the FilterExpressions property returns the FilterExpressions collection defined at design time.

The Filter event is fired only if the Filtered property of the TData control is True. To enable it, check the box labeled Filtered on the General property page or set the Filtered property in code.

See Also

TData Control


FilterComplete Event

Occurs after filter expressions have been evaluated.

Syntax

TData_FilterComplete (ByVal Result As Integer)

Remarks

Arguments: Result is True if the current record passed the filter condition, False if it did not.

The FilterComplete event occurs for each record after the Filter event and after all TData filter expressions have been tested. It is provided primarily for debugging purposes. To determine which records pass all filter conditions, set a breakpoint on the FilterComplete event. The Result argument will be True if a record passed the filter tests, False otherwise.

See Also

TData Control


GetBookmarkName Event

Occurs when Bookmarks Dialog is being opened. Allows you to specify the current bookmark name.

Syntax

TData_GetBookmarkName (BookmarkName As String)

Remarks

Arguments: BookmarkName is a string variable. It can be set to the name you want to assign to the current row bookmark.

The GetBookmarkName event is fired before opening the Bookmarks Dialog. The purpose of this event is to make bookmark names appear automatically, so the end-user won't have to enter a name for each bookmark manually. If you prefer to leave naming bookmarks to the end-user, don’t implement this event.

Setting the BookmarkName argument to a string makes that string appear as the default bookmark name for the current row. The end-user is still allowed to change this name in the Bookmarks dialog.

Usually, you will find useful to set it to the value of a recordset field that allows the user to identify the record. For example,

Private Sub TData1_GetBookmarkName(BookmarkName As String)

BookmarkName = TData1("LastName")

End Sub

For more information, see Bookmarks Dialog.

See Also

TData Control


MoveComplete Event

Occurs after the current row position has changed.

Syntax

TData_MoveComplete (ByVal adReason As EventReasonEnum, ByVal pError As ADODB.Error, adStatus As EventStatusEnum)

Remarks

Arguments: adReason is an ADO EventReasonEnum value that specifies the reason for this event. Its value can be adRsnMoveFirst, adRsnMoveLast, adRsnMoveNext, adRsnMovePrevious, adRsnMove, or adRsnRequery.

adStatus is an ADO EventStatusEnum status variable. When MoveComplete is called, this parameter is set to adStatusOK if the operation that caused the event was successful, or adStatusErrorsOccurred if the operation failed.

The MoveComplete event is a standard ADO Recordset event fired by the TData control’s Recordset. For more information, see Using recordset events. As with any ADO recordset, this event occurs after a pending operation changes the current position in the recordset. For the TData control, it means that the current row position of the control changes, the control is repositioned to a different row.

The MoveComplete event is also fired when an operation has attempted to change the current row position, and failed. This case can be detected by the value of the adStatus argument, it is set to adStatusErrorsOccurred if the operation failed.

The MoveComplete event may occur due to the following Recordset operations: Open, Move, MoveFirst, MoveLast, MoveNext, MovePrevious, Bookmark, AddNew, Delete, Requery, and Resync.

Note: The WillMove and MoveComplete events also occur for a child recordset (in a recordset hierarchy) when its parent recordset is repositioned. The adReason value is adRsnRequery.

See Also

TData Control


OpenData Event

Occurs at startup and on every refresh. Allows to set the underlying recordset (SourceRecordset property) or XArrayDB (Array property) object.

Syntax

TData_OpenData ()

Remarks

Arguments: None

The OpenData event fires when a TData control begins to populate its recordset, which occurs under the following circumstances:

•

At the start of program execution.

•

When the control is refreshed explicitly via the Refresh method with NoEvents argument set to False.

•

When the control is refreshed implicitly: as a result of asynchronous expression evaluation; repositioning the Master control to a different row; or a change in SourceRecordset.

The OpenData event occurs after WillOpenData, before OpenDataComplete.

In data source mode (DataMode = 0 – DataSource), it gives you an opportunity to set the SourceRecordset property to a desired recordset, or to modify the SourceRecordset created by the TData control. See Data Source Mode for details.

In memory array mode (DataMode = 1 – MemoryArray), it allows to set the Array property to an XArrayDB object, or to re-dimension, populate and modify the standard XArrayDB object created by the TData control. See Memory Array Mode for details.

See Also

TData Control


OpenDataComplete Event

Occurs at startup and on every refresh, after the OpenData event.

Syntax

TData_OpenDataComplete ()

Remarks

Arguments: None

The OpenDataComplete event fires when a TData control begins to populate its recordset, which occurs under the following circumstances:

•

At the start of program execution.

•

When the control is refreshed explicitly via the Refresh method with NoEvents argument set to False.

•

When the control is refreshed implicitly: as a result of asynchronous expression evaluation; repositioning the Master control to a different row; or a change in SourceRecordset.

The OpenDataComplete event occurs when all preparatory actions to populate recordset have been performed, after the OpenData event. The TData control’s Recordset is ready at this point.

See Also

TData Control


RecordChangeComplete Event

Occurs after a record has been added/deleted/updated/restored.

Syntax

TData_RecordChangeComplete (ByVal adReason As EventReasonEnum, ByVal cRecords As Long, ByVal pError As ADODB.Error, adStatus As EventStatusEnum)

Remarks

Arguments: adReason is an ADO EventReasonEnum value that specifies the reason for this event. Its value can be adRsnAddNew, adRsnDelete, adRsnUpdate, adRsnUndoUpdate, adRsnUndoAddNew, adRsnUndoDelete, or adRsnFirstChange.

cRecords is a Long integer: the number of records changed (affected).

pError is an ADO Error object. It describes the error that occurred if the value of adStatus is adStatusErrorsOccurred; otherwise it is not set.

adStatus is an ADO EventStatusEnum status variable. When RecordChangeComplete is called, this parameter is set to adStatusOK if the operation that caused the event was successful, or adStatusErrorsOccurred if the operation failed.

The RecordChangeComplete event is a standard ADO Recordset event fired by the TData control’s Recordset. For more information, see Using recordset events. As with any ADO recordset, this event occurs after one or more records (rows) in the recordset change. It is also fired when an operation has attempted to change one or more records, and failed. This case can be detected by the value of the adStatus argument, it is set to adStatusErrorsOccurred if the operation failed.

The RecordChangeComplete event may occur due to the following Recordset operations: Update, Delete, CancelUpdate, AddNew, UpdateBatch, and CancelBatch.

Notes:

(1) The RecordChangeComplete event is fired for the current row of the TData control (except the case (2) below). You can use this event to set field values or perform any other possible actions on the current recordset row.

(2) When RecordChangeComplete event occurs with adReason=adRsnAddNew (i.e., after a new row has been added to the recordset), the TData control is not yet positioned on the newly added row. If you need to perform some actions requiring certain row position (such as setting TData field values), use the MoveComplete event instead, testing for TData.Recordset.EditMode=adEditAdd.

See Also

TData Control


RecordsetChangeComplete Event

Occurs after the whole recordset has changed.

Syntax

TData_RecordsetChangeComplete (ByVal adReason As EventReasonEnum, ByVal pError As ADODB.Error, adStatus As EventStatusEnum)

Remarks

Arguments: adReason is an ADO EventReasonEnum value. Specifies the reason for this event. Its value can be adRsnReQuery, adRsnReSynch, adRsnClose, adRsnOpen.

pError is an ADO Error object. It describes the error that occurred if the value of adStatus is adStatusErrorsOccurred; otherwise it is not set.

adStatus is an ADO EventStatusEnum status variable. When RecordsetChangeComplete is called, this parameter is set to adStatusOK if the operation that caused the event was successful, adStatusErrorsOccurred if the operation failed, or adStatusCancel if the operation associated with the previously accepted WillChangeRecordset event has been canceled.

The RecordsetChangeComplete event is a standard ADO Recordset event fired by the TData control’s Recordset. For more information, see Using recordset events. As with any ADO recordset, this event occurs after the whole contents of the recordset change due to a pending operation. It is also fired when an operation has attempted to change the recordset, and failed. This case can be detected by the value of the adStatus argument, it is set to adStatusErrorsOccurred if the operation failed.

The RecordsetChangeComplete event may occur due to the following Recordset operations: Requery, Resync, Close, Open, and Filter.

See Also

TData Control


UserAddData Event

Occurs when a new row is added in DataMode = 2 - UserEvents.

Syntax

TData_UserAddData(ByVal RowBuf As TrueData60Ctl.RowBuffer, NewRowBookmark As Variant)

Remarks

Arguments: RowBuf is a RowBuffer object used to transfer new row data to the control.

NewBookmark is a variant that must be set to a unique bookmark for subsequent references to the newly added row.

In user events mode (DataMode set to 2 - User Events), the UserAddData event is fired whenever a new row of data has been added and the user commits the changes by leaving the newly added row or calling Recordset.Update. You do not need to write a handler for this event unless you want to create your own data source. See User Events Mode for details.

The RowBuf argument contains a single row of data to be written to your custom data source. Since only one row of data can be added at a time, the value of its RowCount property will always be 1. The number of columns in a RowBuffer is given by its ColumnCount property.

The Value property of the RowBuf argument contains the field data entered by the user. If the user did not enter the value of a particular field, then the corresponding entry in the Value property will contain an Empty variant. In Visual Basic, the IsEmpty function can be used to test for this condition.

Before returning from this event, NewRowBookmark must be set to the bookmark of the newly added row.

If your event handler is unable to add the new row, you should notify the TData control by setting the NewRowBookmark argument to Null. TData will interpret this as a signal that the row has not been added because of an error condition. If you can qualify the error condition, use the RaiseError method to describe the error. Then TData control's clients, the bound controls, will receive the appropriate error information.

See Also

TData Control


UserDeleteRow Event

Occurs when a row needs to be deleted in DataMode = 2 - UserEvents.

Syntax

TData_UserDeleteRow (Bookmark As Variant)

Remarks

Arguments: Bookmark is a variant that identifies the row to be deleted.

In user events mode (DataMode set to 2 - User Events), the UserDeleteRow event is fired whenever a row of data has been deleted and the deletion is being commited to the data source. You do not need to write a handler for this event unless you want to create your own data source. See User Events Mode for details.

The Bookmark argument specifies the row to be deleted. It is the same variant value that was provided by your UserReadData event code when the row was fetched or by your UserAddData event code when the row was added.

Your event handler should update the data source to account for the deleted row.

If your event handler is unable to delete the specified row, you should notify the TData control by setting the Bookmark argument to Null. TData will interpret this as a signal that the row has not been deleted due to an error condition. If you can qualify the error condition, use the RaiseError method to describe the error. Then TData control's clients, bound controls will receive the appropriate error information.

See Also

TData Control


UserFindData Event

Occurs in DataMode = 2 - UserEvents, when the control needs to find a row based upon a similar filter.

Syntax

TData_UserFindData (ByVal StartLocation As Variant, ByVal ReadPriorRows As Boolean, ByVal Col As Integer, ByVal Value As Variant, ByVal SeekFlags As Integer, NewLocation As Variant)

Remarks

Arguments: StartLocation is a bookmark that specifies the starting row for the search.

ReadPriorRows indicates the direction in which to search for data. If False, you should provide data in the forward direction starting with the row specified by StartLocation. If True, you should provide data in the backward direction, starting with the row specified by StartLocation.

Col is a field (column) index that specifies the field for the search. It is an index in the Fields collection returned by the Fields property.

Value is the value to be searched for.

SeekFlags is a SeekFlagsEnum value that provides additional information about how the search should be performed. It should be one of the following values:

tdbSeekLT (<)

tdbSeekLE (<=)

tdbSeekEQ (=)

tdbSeekGE (>=)

tdbSeekGT (>)

tdbSeekBeginsWith

tdbSeekContains

tdbSeekNE (<>)

These values may optionally be combined (with "+") with either tdbSeekCaseSensitive or tdbSeekCaseInsensitive. If neither tdbSeekCaseSensitive nor tdbSeekCaseInsensitive is used, it's up to the programmer, the implementor of the UserFindData event, to decide on case sensitivity.

The NewLocation argument is the variable where you should return the bookmark that uniquely identifies the row where the data was found.

In user events mode (DataMode set to 2 - User Events), the UserFindData event is fired when a search must be performed on your data source. You do not need to write a handler for this event unless you want to create your own data source. See User Events Mode for details.

Even in user events mode, implementing the UserFundData event is optional. It allows you to facilitate search operations for data source. A search operation is performed, for example, when your user calls Recordset.Find. If you don’t implement the UserFindData event, True DataControl will perform an exhaustive search over the data source, record by record. If you know that some of the data source fields allow quicker searching (for example, if they are indexed), you can implement the UserFindData event to improve the search. It is possible (and common) to implement the UserFindData event for certain fields and skip it (set the NewLocation argument to Empty variant) for other fields that are not searchable.

The NewLocation argument is passed to the event procedure as Empty variant You must find the first row meeting the search condition (field value matches the search value with respect to the comparison operation, SeekFlags argument) and return the found row bookmark in the NewLocation argument. If you performed the search and reached the end of your data without finding a row meeting the condition, set the NewLocation argument to Null. Setting NewLocation to Empty variant will make True DataControl perform an exhaustive search.

See Also

TData Control


UserReadData Event

Occurs when the control requires data in DataMode = 2 - UserEvents.

Syntax

TData_UserReadData (ByVal RowBuf As TrueData60Ctl.RowBuffer, ByVal StartLocation As Variant, ByVal Offset As Long, ApproximatePosition As Long)

Remarks

Arguments: RowBuf is a RowBuffer object used to transfer row data to the control.

StartLocation is a bookmark that, together with Offset, specifies the starting row for data transfer. A StartLocation of Null indicates a request for data from BOF or EOF. For example, if StartLocation is Null and Offset is 2 (or -2), then you should retrieve data starting from the second (or second to last) row.

Offset specifies the relative position (from StartLocation) of the first row of data to be transferred. A positive number indicates a forward relative position; a negative number indicates a backward relative position.

ApproximatePosition is a variable that optionally receives the ordinal position of the first row of data to be transferred. This information is used by the TData control to service client requests for approximate row position information, usually used by bound controls for their scrollbar functionality. If you choose to set the ApproximatePosition, you must also maintain the TData control’s ApproxCount property. If ApproximatePosition = -1 is passed to the event procedure, it means that the programmer can skip setting the ApproximatePosition, which is optional anyway. Even if the programmer supplies a value, TData control will ignore it. Also, the programmer can let TData know that ApproxiamtePosition is unknown, setting it to -1 in the event procedure.

In user events mode (DataMode set to 2 - User Events), the UserReadData event is fired whenever the TData control requests data from your application. You do not need to write a handler for this event unless you want to create your own data source. See User Events Mode for details.

Before returning from the UserReadData event, you must fill the Bookmark array of RowBuf with unique row identifiers (bookmarks), and the Value array with the actual data. For example, if Offset is 1 (or -1), then you must fill in RowBuf, starting from the row that follows (or precedes) StartLocation.

The RowBuf argument acts like a two-dimensional array of variants corresponding to the fields in the rows being fetched. By populating its Value property with the appropriate data, your event procedure transfers rows from your data source to the TData control.

Use the row buffer's RowCount property to determine how many rows of data TData is requesting. Use its ColumnCount property to determine the number of columns to be populated, if any. If ColumnCount is zero, TData is requesting only bookmarks; if ColumnCount is nonzero, TData is requesting RowCount rows of data and their corresponding bookmarks.

The ColumnIndex property specifies the Fields index (in the collection returned by the Fields property) that corresponds to a row buffer column index; you must fill in the Value property array with field data according to the field index specified by the ColumnIndex property array.

The RowBuf argument is also used to store a set of variant bookmarks that uniquely identify rows in your data source. The format of these bookmarks is determined solely by your application. For example, they may be primary key fields, row numbers, or array indexes, depending upon the nature of your data source.

Your event procedure supplies bookmarks to the TData control by populating the row buffer's Bookmark property for each row returned. Keep in mind that the bookmarks you provide in the UserReadData event may be subsequently passed to the UserWriteData and UserDeleteRow events.

It is not necessary to fill the row buffer completely, and it is in fact acceptable to return no rows at all. The row buffer's RowCount property can be set to indicate that fewer rows were returned than requested. TData interprets this to mean that there are no more rows to retrieve in the indicated direction. Thus, it is only necessary to fill the row buffer completely if there are enough valid rows to be retrieved.

See Also

TData Control


UserWriteData Event

Occurs when a row needs to be modified in DataMode = 2 - UserEvents.

Syntax

TData_WriteData (ByVal RowBuf As TrueData60Ctl.RowBuffer, WriteLocation As Variant)

Remarks

Arguments: RowBuf is a RowBuffer object used to transfer modified row data from the TDatacontrol to your custom data source.

WriteLocation is a variant bookmark that uniquely identifies the row to be updated.

In user events mode (DataMode set to 2 - User Events), the UserWriteData event is fired whenever a row of data has been modified and the user commits the changes by leaving the modified row or calling Recordset.Update. You do not need to write a handler for this event unless you want to create your own data source. See User Events Mode for details.

The RowBuf argument contains a single row of data to be written (updated) to your custom data source. Since only one row of data can be updated at a time, the value of its RowCount property will always be 1. The number of columns in a RowBuffer is given by its ColumnCount property.

The WriteLocation argument contains a bookmark supplied by your application in either the UserReadData or UserAddData event.

The Value property of the RowBuf argument contains the field data modified by the user. If the user did not modify a particular field, then the corresponding entry in the Value property will contain an Empty variant. In Visual Basic, the IsEmpty function can be used to test for this condition.

If your event handler is unable to modify the specified row, you should notify the TData control by setting the WriteLocation argument to Null. The TData control will interpret this as a signal that the row has not been updated due to an error condition. If you can qualify the error condition, use the RaiseError method to describe the error. Then the TData control's clients, the bound controls, will receive the appropriate error information.

See Also

TData Control


WillChangeField Event

Occurs before a field value changes.

Syntax

TData_WillChangeField (ByVal cFields As Long, ByVal Fields As Variant, NewValues As Variant, adStatus As EventStatusEnum)

Remarks

Arguments: cFields is the number of fields that are about to change. In True DataControl version 8.0, this is always one, but we recommend you not make this assumption. It is better to write general code that can accommodate changing several fields at once.

Fields is an array of ADO Field objects, items of the Recordset.Fields collection. In True DataControl version 8.0, it always contains one element, Fields(0). Fields(0).Name is the name of the field that is about to change.

NewValues is an array of values that are about to be assigned to the fields. It has the same dimension as the Fields array, that is, in True DataControl version 8.0, it always has one element, NewValues(0). Your code in this event is allowed to not only validate, but also modify the values in NewValues, thus changing the value entered by the user (for example, convert it to uppercase).

adStatus is an ADO EventStatusEnum value, with two possible values: adStatusOK and adStatusCancel. You should set the adStatus argument to adStatusCancel to reject new field values.

The WillChangeField event occurs when a new value is assigned to a TData field as a result of code execution or end-user interaction with a bound control. You can use this event to impose complex field validation rules that cannot be specified as field constraint expressions, see Validation and Constraints. You can also use this event to modify the values entered by the user.

The event is similar to the standard ADO WillChangeField event, but it has an additional argument, NewValues. The standard ADO event is quite useless, because one always needs to know the values that are about to be assigned to fields.

When this event fires, adStatus is adStatusOK, indicating that the new field values are valid. Your event handler should examine the NewValues array to determine whether the new values meet your acceptance criteria. If they do not, you should take an appropriate action (such as displaying an error message) and set the adStatus argument to adStatusCancel. This prevents the field change. If you permit the change, you can also adjust the value, modify it according to some formatting or other rules, for example, convert it to uppercase.

For more information, see Validation and Constraints and Modifying Field Values Retrieving and Saving Them in the Data Source.

See Also

TData Control


WillChangeRecord Event

Occurs before the current row position changes.

Syntax

TData_WillChangeRecord (ByVal adReason As EventReasonEnum, ByVal cRecords As Long, adStatus As EventStatusEnum)

Remarks

Arguments: adReason is an ADO EventReasonEnum value that specifies the reason for this event. Its value can be adRsnAddNew, adRsnDelete, adRsnUpdate, adRsnUndoUpdate, adRsnUndoAddNew, adRsnUndoDelete, or adRsnFirstChange.

cRecords is always 1.

adStatus is an ADO EventStatusEnum status variable. When WillChangeRecord is called, this parameter is set to adStatusOK ,or to adStatusCantDeny, the latter means that this event cannot request cancellation of the pending operation. Before WillChangeRecord returns, set this parameter to adStatusCancel to request cancellation of the operation that caused this event.

The WillChangeRecord event is a standard ADO Recordset event fired by the TData control’s Recordset. For more information, see Using recordset events. As with any ADO recordset, this event occurs before one or more records (rows) in the recordset change.

The WillChangeRecord event may occur due to the following Recordset operations: Update, Delete, CancelUpdate, AddNew, UpdateBatch, and CancelBatch.

See Also

TData Control


WillChangeRecordset Event

Occurs before the whole contents of the recordset change due to a pending operation.

Syntax

TData_WillChangeRecordset (ByVal adReason As EventReasonEnum, adStatus As EventStatusEnum)

Remarks

Arguments: adReason is an ADO EventReasonEnum value. Specifies the reason for this event. Its value can be adRsnReQuery, adRsnReSynch, adRsnClose, adRsnOpen.

adStatus is an ADO EventStatusEnum status variable. When WillChangeRecordset is called, this parameter is set to adStatusOK ,or to adStatusCantDeny, the latter means that this event cannot request cancellation of the pending operation. Before WillChangeRecordset returns, set this parameter to adStatusCancel to request cancellation of the operation that caused this event.

The WillChangeRecordset event is a standard ADO Recordset event fired by the TDatacontrol’s Recordset. For more information, see Using recordset events. As with any ADO recordset, this event occurs before the whole contents of the recordset change due to a pending operation.

The WillChangeRecordset event may occur due to the following Recordset operations: Requery, Resync, Close, Open, and Filter.

See Also

TData Control


WillMove Event

Occurs before the current row position changes.

Syntax

TData_WillMove (ByVal adReason As EventReasonEnum, adStatus As EventStatusEnum)

Remarks

Arguments: adReason is an ADO EventReasonEnum value. Specifies the reason for this event. Its value can be adRsnMoveFirst, adRsnMoveLast, adRsnMoveNext, adRsnMovePrevious, adRsnMove or adRsnRequery.

adStatus is an ADO EventStatusEnum status variable. When WillMove is called, this parameter is set to adStatusOK ,or to adStatusCantDeny, the latter means that this event cannot request cancellation of the pending operation. Before WillMove returns, set this parameter to adStatusCancel to request cancellation of the operation that caused this event.

The WillMove event is a standard ADO Recordset fired by the TData control’s Recordset. For more information, see Using recordset events. As with any ADO recordset, this event occurs before a pending operation changes the current position in the recordset. For TData control, it means that the current row position of the control changes, the control is being repositioned to a different row.

The WillMove event may occur due to the following Recordset operations: Open, Move, MoveFirst, MoveLast, MoveNext, MovePrevious, Bookmark, AddNew, Delete, Requery, and Resync.

The WillMove and MoveComplete events also occur for a child recordset (in a recordset hierarchy) when its parent recordset is repositioned. The adReason value is adRsnRequery.

See Also

TData Control


WillOpenData Event

Occurs at startup and on every refresh, before the OpenData event.

Syntax

TData_WillOpenData ( )

Remarks

Arguments: None

The WillOpenData event fires before a TData control begins to populate its recordset, which occurs under the following circumstances:

•

At the start of program execution.

•

When the control is refreshed explicitly via the Refresh method with NoEvents argument set to False.

•

When the control is refreshed implicitly: as a result of asynchronous expression evaluation; repositioning the Master control to a different row; or a change in SourceRecordset.

The WillOpenData event occurs before OpenData. It gives the programmer an opportunity to change Fields and other collections. For more information, see Modifying True DataControl collections from code. Use the Fields property to access the Fields collection.

The WillOpenData event can also be used to set parameter values that cannot be specified at design time. See Parameters in expressions for more information.


TDataLite Control All Members

TDataLite Control Properties

Appearance | Enables/disables 3-D display effects for the control.
Array | Specifies an XArrayDB object as the control's data source.
BackColor | Sets/returns the background color.
BOFAction | Action taken on reaching BOF (begin of file).
ButtonAdd | Determines if the Add button is visible.
ButtonBookmark | Determines if the Bookmarks button is visible.
ButtonCancel | Determines if the Cancel button is visible.
ButtonDelete | Determines if the Delete button is visible.
ButtonFind | Determines if the Find button is visible.
ButtonFirst | Determines if the First and Last buttons are visible.
ButtonNext | Determines if the Previous and Next buttons are visible.
ButtonPage | Determines if the Previous Page and Next Page buttons are visible.
ButtonQuery | Determines if the Query button is visible.
ButtonUpdate | Determines if the Update button is visible.
CallDataRead | Specifies if the DataRead event is fired.
CallDataWrite | Specifies if the DataWrite event is fired.
Caption | Text displayed in the middle section of the control.
ChangeInProgress | If True, prevents automatic refresh while making batch changes.
ConfirmCancel | Determines whether to show confirmation message box when the Cancel button is pressed.
ConfirmDelete | Determines whether to show confirmation message box when the Delete button is pressed.
Constraints | Contains a collection of constraint objects.
ConvertEmptyToNull | Specifies if empty string values should be converted to Null on save.
ConvertNullToEmpty | Specifies if Null values of string fields should be converted to empty strings on retrieval.
DataMember | Qualifies the DataSource property setting.
DataMode | Specifies the type of data storage on which the control operates.
DataSource | Sets/returns the source of underlying data in DataMode = 0 – DataSource.
Enabled | Enables/disables user interaction.
EOFAction | Action taken on reaching EOF (end of file).
ErrorMsgCaption | Overrides default message box caption for run-time errors.
Fields | Contains a collection of field objects.
Filtered | Enables/disables filtering.
FilterExpressions | Contains a collection of filter expression objects.
Font | Specifies the font used to display the caption text.
ForeColor | Sets/returns the foreground color.
LockType | Sets/returns the type of locking (concurrency) to use.
ManualUpdate | If True, SourceRecordset changes are not automatically saved to the database on Update.
MouseIcon | Sets a custom mouse icon.
MousePointer | The type of mouse pointer displayed when over the control.
NamedBookmarks | Contains a collection of named bookmark objects, for Bookmarks button dialog.
PageSize | Sets/returns the number of records in a page.
Parameters | Contains a collection of parameter objects.
Pivot | This property enables Pivot mode.
PivotColumnDimension | Together with PivotRowDimensions and PivotMeasure, this property constitutes the end-user query
PivotConnectionString | Specifies connection to an OLAP server or an off-line OLAP cube file.
PivotCubeName | Specifies the name of a cube in a cube file or on an OLAP server, see PivotConnectionString.
PivotFieldsAllLevels | In pivot mode, TData control exposes a hierarchical recordset. Each hierarchy level corresponds to a row dimension, the depth of the hierarchy equals the number of fields in PivotRowDimensions.
PivotMeasure | Constitutes the end-user query, determines the data retrieved from the decision cube and exposed in the TData hierarchical recordset.
PivotQuery | Returns a string, the text of a multidimensional query (MDX) that is currently active.
PivotRowDimensions | Determines the data retrieved from the decision cube and exposed in the TData hierarchical recordset.
PooledConnectionCount | Returns the number of connections in the pool shared by all TData controls.
PropertyExpressions | Contains a collection of property expression objects.
QueryFilter | Returns the Filter string that can be applied to an ADO recordset, composed from user-supplied data in query mode.
QueryMode | If True, the control is in query mode.
Recordset | Returns the ADO recordset object representing control's data.
RefreshOnSrcChange | Determines whether SourceRecordset changes trigger refresh.
ResyncAfterUpdate | Determines whether to call SourceRecordset.Resync immediately after SourceRecordset.Update.
Tooltips | Determines if the button tooltips are enabled.
Xtab | If True, the control is used in crosstab mode.
XTabColKey | For crosstab mode, comma-delimited list of key fields defining crosstab columns.
XTabCollate | For crosstab mode with multiple crosstab fields, if set to True, makes all columns for one field appear after all columns for another.
XTabRowKey | For crosstab mode, comma-delimited list of primary key fields defining crosstab rows.
XTabSeparateFields | For crosstab mode, if set to True, exposes crosstab columns as independent fields at design time.

TDataLite Control Methods

ArrayIndexToBookmark | Converts array index to bookmark in memory array mode
BookmarkToArrayIndex | Converts bookmark to array index in memory array mode
ButtonEnabled | Returns the enabled state of a control button
Drag | Begins, ends, or cancels a drag operation of the control
EnableButton | Sets the enabled state of a button
Move | Moves the position of the control on the form
PivotOpen | In pivot mode, opens pivot query.
PressButton | Invokes the action of a control’s button
Refresh | Refetches all data
RetrieveFields | Retrieves field layout from the source recordset
SetButtonPicture | Changes the picture on a button
SetUIString | Changes a string shown to the end-user
ShowWhatsThis | Displays the appropriate help topic for the control
ZOrder | Places the control at the front or back of the z-order

TDataLite Control Events

ButtonPressed | Occurs when a control button is pressed.
ButtonStateChanged | Occurs when a control button's enable state changes.
CalcFields | Occurs before calculated field expressions are evaluated.
CalcFieldsComplete | Occurs after calculated field expressions have been evaluated.
DataRead | Occurs immediately after retrieving a row of values from the data source.
DataWrite | Occurs immediately before saving changed values to the data source.
Error | Occurs as a result of an error that takes place when no user code is being executed.
FieldChangeComplete | Occurs after a field value has changed.
Filter | Occurs before filter expressions are evaluated.
FilterComplete | Occurs after filter expressions have been evaluated.
GetBookmarkName | Occurs when Bookmarks Dialog is being opened. Allows you to specify the current bookmark name.
MoveComplete | Occurs after the current row position has changed.
OpenData | Occurs at startup and on every refresh. Allows to set the underlying recordset (SourceRecordset property) or XArrayDB (Array property) object.
OpenDataComplete | Occurs at startup and on every refresh, after the OpenData event.
RecordChangeComplete | Occurs after a record has been added/deleted/updated/restored.
RecordsetChangeComplete | Occurs after the whole recordset has changed.
WillChangeField | Occurs before a field value changes.
WillChangeRecord | Occurs before the current row position changes.
WillChangeRecordSet | Occurs before the whole contents of the recordset change due to a pending operation.
WillMove | Occurs before the current row position changes.
WillOpenData | Occurs at startup and on every refresh, before the OpenData event.


TDataLite Control Properties

Appearance Property (TDataLite)

Array Property (TDataLite)

BackColor Property (TDataLite)

BOFAction Property (TDataLite)

ButtonAdd Property (TDataLite)

ButtonBookmark Property (TDataLite)

ButtonCancel Property (TDataLite)

ButtonDelete Property (TDataLite)

ButtonFind Property (TDataLite)

ButtonFirst Property (TDataLite)

ButtonNext Property (TDataLite)

ButtonPage Property (TDataLite)

ButtonQuery Property (TDataLite)

ButtonUpdate Property (TDataLite)

CallDataRead Property (TDataLite)

CallDataWrite Property (TDataLite)

Caption Property (TDataLite)

ChangeInProgress Property (TDataLite)

ConfirmCancel Property (TDataLite)

ConfirmDelete Property (TDataLite)

Constraints Property (TDataLite)

ConvertEmptyToNull Property (TDataLite)

ConvertNullToEmpty Property (TDataLite)

DataMember Property (TDataLite)

DataMode Property (TDataLite)

DataSource Property (TDataLite)

Enabled Property (TDataLite)

EOFAction Property (TDataLite)

ErrorMsgCaption Property (TDataLite)

Fields Property (TDataLite)

Filtered Property (TDataLite)

FilterExpressions Property (TDataLite)

Font Property (TDataLite)

ForeColor Property (TDataLite)

LockType Property (TDataLite)

ManualUpdate Property (TDataLite)

MouseIcon Property (TDataLite)

MousePointer Property (TDataLite)

NamedBookmarks Property (TDataLite)

PageSize Property (TDataLite)

Parameters Property (TDataLite)

Pivot Property (TDataLite)

PivotColumnDimension Property (TDataLite)

PivotConnectionString Property (TDataLite)

PivotCubeName Property (TDataLite)

PivotFieldsAllLevels Property (TDataLite)

PivotMeasure Property (TDataLite)

PivotQuery Property (TDataLite)

PivotRowDimensions Property (TDataLite)

PooledConnectionCount Property (TDataLite)

PropertyExpressions Property (TDataLite)

QueryFilter Property (TDataLite)

QueryMode Property (TDataLite)

Recordset Property (TDataLite)

RefreshOnSrcChange Property (TDataLite)

ResyncAfterUpdate Property (TDataLite)

Tooltips Property (TDataLite)

XTab Property (TDataLite)

XTabColKey Property (TDataLite)

XTabCollate Property (TDataLite)

XTabRowKey Property (TDataLite)

XTabSeparateFields Property (TDataLite)


Appearance Property (TDataLite)

See Appearance Property.


Array Property (TDataLite)

See Array Property.


BackColor Property (TDataLite)

See BackColor Property.


BOFAction Property (TDataLite)

See BOFAction Property.


ButtonAdd Property (TDataLite)

See ButtonAdd Property.


ButtonBookmark Property (TDataLite)

See ButtonBookmark Property.


ButtonCancel Property (TDataLite)

See ButtonCancel Property.


ButtonDelete Property (TDataLite)

See ButtonDelete Property.


ButtonFind Property (TDataLite)

See ButtonFind Property.


ButtonFirst Property (TDataLite)

See ButtonFirst Property.


ButtonNext Property (TDataLite)

See ButtonNext Property.


ButtonPage Property (TDataLite)

See ButtonPage Property.


ButtonQuery Property (TDataLite)

See ButtonQuery Property.


ButtonUpdate Property (TDataLite)

See ButtonUpdate Property.


CallDataRead Property (TDataLite)

See CallDataRead Property.


CallDataWrite Property (TDataLite)

See CallDataWrite Property.


Caption Property (TDataLite)

See Caption Property.


ChangeInProgress Property (TDataLite)

See ChangeInProgress Property.


ConfirmCancel Property (TDataLite)

See ConfirmCancel Property.


ConfirmDelete Property (TDataLite)

See ConfirmDelete Property.


Constraints Property (TDataLite)

See Constraints Property.


ConvertEmptyToNull Property (TDataLite)

See ConvertEmptyToNull Property.


ConvertNullToEmpty Property (TDataLite)

See ConvertNullToEmpty Property.


DataMember Property (TDataLite)

See DataMember Property.


DataMode Property (TDataLite)

See DataMode Property.


DataSource Property (TDataLite)

See DataSource Property.


Enabled Property (TDataLite)

See Enabled Property.


EOFAction Property (TDataLite)

See EOFAction Property.


ErrorMsgCaption Property (TDataLite)

See ErrorMsgCaption Property.


Fields Property (TDataLite)

See Fields Property.


Filtered Property (TDataLite)

See Filtered Property.


FilterExpressions Property (TDataLite)

See FilterExpressions Property.


Font Property (TDataLite)

See Font Property.


ForeColor Property (TDataLite)

See ForeColor Property.


LockType Property (TDataLite)

See LockType Property.


ManualUpdate Property (TDataLite)

See ManualUpdate Property.


MouseIcon Property (TDataLite)

See MouseIcon Property.


MousePointer Property (TDataLite)

See MousePointer Property.


NamedBookmarks Property (TDataLite)

See NamedBookmarks Property.


PageSize Property (TDataLite)

See PageSize Property.


Parameters Property (TDataLite)

See Parameters Property.

TDataLite Control


Pivot Property (TDataLite)

This property enables Pivot mode.

Syntax

TData.Pivot = boolean

Remarks

Read/Write at design time. Read-only at run time. Property applies to TData and TDataLite control, starting from version 7.0.

This property enables Pivot mode. See OLAP: Decision Support, Pivot Table for more information.

See Also

TDataLite Control


PivotColumnDimension Property (TDataLite)

Together with PivotRowDimensions and PivotMeasure, it constitutes the end-user query, determines the data retrieved from the decision cube and exposed in the TData hierarchical recordset.

Syntax

TData.PivotColumnDimension = string

Remarks

This property applies to Pivot mode.

Read/Write at run time time. Unavailable at design time. Property applies to TData and TDataLite control, starting from version 7.0.

Before calling PivotOpen, this property must be set to the name of a dimension field. That dimension will be used for columns: every value of that dimension will generate a column. This way, columns form a crosstab representation of the chosen dimension field.

Unlike PivotRowDimensions, this property does not accept lists of fields, it must be set to the name of a single field.

For more information, see OLAP: Decision Support, Pivot Table.

See Also

TDataLite Control


PivotConnectionString Property (TDataLite)

Specifies connection to an OLAP server or an off-line OLAP cube file.

Syntax

TData.PivotConnectionString = string

Remarks

Read/Write at run time time and design time. Property applies to TData and TDataLite control, starting from version 7.0.

This property applies to Pivot mode. It accepts any OLAP data connection valid for ADOMD.Catalog object, see Microsoft ADO MD documentation for details. It can be a live on-line connection to an OLAP server, or a connection to an off-line cube file. For example, you can prepare a cube file in Microsoft Excel 2000, with PivotTable and PivotChart Wizard, see Tutorial 10 - OLAP - Decision Support, Pivot Table.

Example: TData1.PivotConnectionString = “Provider=msolap;DATA SOURCE=C:\OLAPCubes\orders.cub”

For more information, see OLAP: Decision Support, Pivot Table.

See Also

TDataLite Control


PivotCubeName Property (TDataLite)

Specifies the name of a cube in a cube file or on an OLAP server, see PivotConnectionString.

Syntax

TData.PivotCubeName = string

Remarks

Read/Write at run time time and design time. Property applies to TData and TDataLite control, starting from version 7.0.

This property applies to Pivot mode. There can be multiple cubes in a single OLAP data connection, so this property is needed to select one of them. The default cube name produced by Microsoft Excel is “OCWCube”.

For more information, see OLAP: Decision Support, Pivot Table.

See Also

TDataLite Control


PivotFieldsAllLevels Property (TDataLite)

In pivot mode, TData control exposes a hierarchical recordset. Each hierarchy level corresponds to a row dimension, the depth of the hierarchy equals the number of fields in PivotRowDimensions.

Syntax

TData.PivotFieldsAllLevels = boolean

Remarks

Read/Write at design time. Read-only at run time. Property applies to TData and TDataLite control, starting from version 7.0.

This property applies to Pivot mode. If this property is set to False, every level except the last (deepest) one, contains only one field, the row dimension field of that level. The last (terminal) level contains contains the last row dimension field and all crosstab fields generated by the column dimension field. This field structure is most suitable for displaying the hierarchical recordset in TreeView-like bound controls.

If this property is set to True (default), every level contains all fields: all row dimension fields and all crosstab fields. On non-terminal levels (all levels but last), fields belonging to lower levels of the hierarchy contain totals, aggregated values. This structure is more suitable for displaying the hierarchical recordset in a bound grid where all rows contain all the fields.

Using Pivot mode with ComponentOne True DBGrid 8.0 (preferred choice for TData pivot mode), set this property to True. Using other, third-party bound controls, set this property in accordance with those controls’ requirements, in most cases – to False.

For more information, see OLAP: Decision Support, Pivot Table.

See Also

TDataLite Control


PivotMeasure Property (TDataLite)

Constitutes the end-user query, determines the data retrieved from the decision cube and exposed in the TData hierarchical recordset.

Syntax

TData.PivotMeasure = string

Remarks

Read/Write at run time time. Unavailable at design time. Property applies to TData and TDataLite control, starting from version 7.0.

This property applies to Pivot mode. Together with PivotRowDimensions and PivotColumnDimension, it constitutes the end-user query, determines the data retrieved from the decision cube and exposed in the TData hierarchical recordset.

Before calling PivotOpen, this property must be set to the name of a measure field. Values of this measure are shown in the cells of the resulting hierarchical crosstab.

For more information, see OLAP: Decision Support, Pivot Table.

See Also

TDataLite Control


PivotQuery Property (TDataLite)

Returns a string, the text of a multidimensional query (MDX) that is currently active.

Syntax

TData.PivotQuery

Remarks

Read-only at run time. Unavailable at design time. Property applies to TData and TDataLite control, starting from version 7.0.

This property applies to Pivot mode. It returns a string, the text of a multidimensional query (MDX) that is currently active. The query can be generated automaticaly, if you set PivotRowDimensions/PivotColumnDimension/PivotMeasure and call PivotOpen, or it can be explicitly passed to PivotOpen as a parameter. In both cases, after PivotOpen call, the PivotQuery property returns the current query text. It is mostly needed for debugging purposes.

For more information, see OLAP: Decision Support, Pivot Table.

See Also

TDataLite Control


PivotRowDimensions Property (TDataLite)

Determines the data retrieved from the decision cube and exposed in the TData hierarchical recordset.

Syntax

TData.PivotRowDimensions = string

Remarks

Read/Write at run time time. Unavailable at design time.
Property applies to TData and TDataLite control, starting from version 7.0.

This property applies to Pivot mode. Together with PivotColumnDimension and PivotMeasure, it constitutes the end-user query, determines the data retrieved from the decision cube and exposed in the TData hierarchical recordset.

Before calling PivotOpen, this property must be set to a comma-delimited list of dimension field names. Dimensions specified in this property will be used for crosstab rows. They form a hierarchy in the specified order.

For more information, see OLAP: Decision Support, Pivot Table.

See Also

TDataLite Control


PooledConnectionCount Property (TDataLite)

See PooledConnectionCount Property.


PropertyExpressions Property (TDataLite)

See PropertyExpressions Property.


QueryFilter Property (TDataLite)

See QueryFilter Property.


QueryMode Property (TDataLite)

See QueryMode Property.


Recordset Property (TDataLite)

See Recordset Property.


RefreshOnSrcChange Property (TDataLite)

See RefreshOnSrcChange Property.


ResyncAfterUpdate Property (TDataLite)

See ResyncAfterUpdate Property.


Tooltips Property (TDataLite)

See Tooltips Property.


XTab Property (TDataLite)

See XTab Property.


XTabColKey Property (TDataLite)

See XTabColKey Property.


XTabCollate Property (TDataLite)

See XTabCollate Property.


XTabRowKey Property (TDataLite)

See XTabRowKey Property.


XTabSeparateFields Property (TDataLite)

See XTabSeparateFields Property.


TData Control Methods

ArrayIndexToBookmark Method (TDataLite)

BookmarkToArrayIndex Method (TDataLite)

ButtonEnabled Method (TDataLite)

Drag Method (TDataLite)

EnableButton Method (TDataLite)

Move Method (TDataLite)

PivotOpen Method (TDataLite)

PressButton Method (TDataLite)

Refresh Method (TDataLite)

RetrieveFields Method (TDataLite)

SetButtonPicture Method (TDataLite)

SetUIString Method (TDataLite)

ShowWhatsThis Method (TDataLite)

ZOrder Method (TDataLite)


ArrayIndexToBookmark Method (TDataLite)

See ArrayIndexToBookmark Method.


BookmarkToArrayIndex Method (TDataLite)

See ArrayIndexToBookmark Method.


ButtonEnabled Method (TDataLite)

See ButtonEnabled Method.


Drag Method (TDataLite)

See Drag Method.


EnableButton Method (TDataLite)

See EnableButton Method.


Move Method (TDataLite)

See Move Method.


PivotOpen Method (TDataLite)

In pivot mode, opens pivot query.

Syntax

TData.PivotOpen [Query]

Remarks

Method applies to TData and TDataLite control, starting from version 7.0.

Arguments: Query is an optional string argument. If it is specified, it determines a multidimensional query (MDX). If it is omitted or empty, the query is generated automatically based on the values of PivotRowDimensions /PivotColumnDimension /PivotMeasure properties.

Return Value: None

This method applies to Pivot mode. It is called to generate the end-user query, execute it and fill the resulting hierarchical crosstab recordset. Normally, the query is generated automatically based on the values of PivotRowDimensions /PivotColumnDimension /PivotMeasure properties. As an advanced option, the full text of a query can be specified explicitly in the optional Query argument. In both cases, the resulting query text can be retrieved using the PivotQuery property.

For more information, see OLAP: Decision Support, Pivot Table.

See Also

TDataLite Control


PressButton Method (TDataLite)

See PressButton Method.


Refresh Method (TDataLite)

See Refresh Method.


RetrieveFields Method (TDataLite)

See RetrieveFields Method.


SetButtonPicture Method (TDataLite)

See SetButtonPicture Method.


SetUIString Method (TDataLite)

See SetUIString Method.


ShowWhatsThis Method (TDataLite)

See ShowWhatsThis Method.


ZOrder Method (TDataLite)

See ZOrder Method.


TData Control Events

ButtonPressed Event (TDataLite)

ButtonStateChanged Event (TDataLite)

CalcFields Event (TDataLite)

CalcFieldsComplete Event (TDataLite)

DataRead Event (TDataLite)

DataWrite Event (TDataLite)

Error Event (TDataLite)

FieldChangeComplete Event (TDataLite)

Filter Event (TDataLite)

FilterComplete Event (TDataLite)

GetBookmarkName Event (TDataLite)

MoveComplete Event (TDataLite)

OpenData Event (TDataLite)

OpenDataComplete Event (TDataLite)

RecordChangeComplete Event (TDataLite)

RecordsetChangeComplete Event (TDataLite)

WillChangeField Event (TDataLite)

WillChangeRecord Event (TDataLite)

WillChangeRecordset Event (TDataLite)

WillMove Event (TDataLite)

WillOpenData Event (TDataLite)


ButtonPressed Event (TDataLite)

See ButtonPressed Event.


ButtonStateChanged Event (TDataLite)

See ButtonStateChanged Event.


CalcFields Event (TDataLite)

See CalcFields Event.


CalcFieldsComplete Event (TDataLite)

See CalcFieldsComplete Event.


DataRead Event (TDataLite)

See DataRead Event.


DataWrite Event (TDataLite)

See DataWrite Event.


Error Event (TDataLite)

See Error Event.


FieldChangeComplete Event (TDataLite)

See FieldChangeComplete Event.


Filter Event (TDataLite)

See Filter Event.


FilterComplete Event (TDataLite)

See FilterComplete Event.


GetBookmarkName Event (TDataLite)

See GetBookmarkName Event.


MoveComplete Event (TDataLite)

See MoveComplete Event.


OpenData Event (TDataLite)

See OpenData Event.


OpenDataComplete Event (TDataLite)

See OpenDataComplete Event.


RecordChangeComplete Event (TDataLite)

See RecordChangeComplete Event.


RecordsetChangeComplete Event (TDataLite)

See RecordsetChangeComplete Event.


WillChangeField Event (TDataLite)

See WillChangeField Event.


WillChangeRecord Event (TDataLite)

See WillChangeRecord Event.


WillChangeRecordset Event (TDataLite)

See WillChangeRecordset Event.


WillMove Event (TDataLite)

See WillMove Event.


WillOpenData Event (TDataLite)

See WillOpenData Event.


Constant Reference

AutoRefresh Constants

BOFAction Constants

ComparisonOperation Constants

DataMode Constants

DataType Constants

EOFAction Constants

FieldKind Constants

LinkType Constants

ModificationMode Constants

Orientation Constants

QueryMode Constants

SeekFlag Constants

TDButtonEnabledEnum Constants

TDButtonEnum Constants

TDStringEnum Constants


VBScript Reference

In the True DataControl Expression Editor, you can use the Operators and Function and Constants combo boxes to make different sets of VBScript functions and operators available for building expressions. This reference provides a brief description of each function and operator, organized by category.

For more information on using VBScript, consult any available reference guide, such as the VBScript Reference in the Microsoft MSDN Library.

True DataControl's expression language adds two functions to the standard VBScript function set: IIF and Format. Both functions are supported by Visual Basic, but not by standard VBScript. True DataControl makes them available for your convenience.

General Category

Numeric Category

String Category

Logical Category

Date/Time Category

Conversion Category

Format Category


General Category

Functions

Field

Returns the value of a field

IIF

Returns one of two parts, depending on the evaluation of an expression

IsEmpty

Returns a boolean value indicating whether a variable has been initialized

IsNull

Returns a boolean value indicating whether an expression contains no valid data

Operators

<

Less than

<=

Less than or equal to

<>

Not equal to

=

Equal to

>

Greater than

>=

Greater than or equal to


Numeric Category

Functions

Abs

Returns the absolute value of a number

Atn

Returns the arctangent of a number

Cos

Returns the cosine of an angle

Exp

Returns e (the base of natural logarithms) raised to a power

Fix

Returns the integer portion of a number, rounding up if negative

Int

Returns the integer portion of a number, rounding down if negative

Log

Returns the natural logarithm of a number

Rnd

Returns a random number

Round

Returns a number rounded to a specified number of decimal places

Sgn

Returns an integer indicating the sign of a number

Sin

Returns the sine of an angle

Sqr

Returns the square root of a number

Tan

Returns the tangent of an angle

Operators

-

Used to find the difference between two numbers or to negate a numeric expression

*

Used to multiply two numbers

/

Used to divide two numbers and return a floating point result

\

Used to divide two numbers and return an integer result

^

Used to raise a number to the power of an exponent

+

Used to sum two numbers

Mod

Used to divide two numbers and return only the remainder


String Category

Functions

Asc

Returns the ANSI character code corresponding to the first letter in a string

Chr

Returns the character associated with the specified ANSI character code

InStr

Returns the position of the first occurrence of one string within another

InStrRev

Returns the position of an occurrence of one string within another, from the end of string

LCase

Returns a string that has been converted to lowercase

Left

Returns a specified number of characters from the left side of a string

Len

Returns the number of characters in a string

LTrim

Returns a copy of a string without leading spaces

Mid

Returns a specified number of characters from a string

Replace

Returns a string in which a specified substring has been replaced with another substring a specified number of times

Right

Returns a specified number of characters from the right side of a string

RTrim

Returns a copy of a string without trailing spaces

Space

Returns a string consisting of the specified number of spaces

StrComp

Returns a value indicating the result of a string comparison

String

Returns a repeating character string of the length specified

StrReverse

Returns a string in which the character order of a specified string is reversed

UCase

Returns a string that has been converted to uppercase

Operators

&

Used to force string concatenation of two expressions


Logical Category

Operators

And

Used to perform a logical conjunction on two expressions

Eqv

Used to perform a logical equivalence on two expressions

Imp

Used to perform a logical implication on two expressions

Not

Used to perform a logical negation on an expression

Or

Used to perform a logical disjunction on two expressions

Xor

Used to perform a logical exclusion on two expressions


Date/Time Category

Functions

Date

Returns the current system date

DateAdd

Returns a date to which a specified time interval has been added

DateDiff

Returns the number of intervals between two dates

DatePart

Returns the specified part of a given date

DateSerial

Returns a Variant of subtype Date for a specified year, month, and day

DateValue

Returns a Variant of subtype Date

Day

Returns a whole number between 1 and 31, inclusive, representing the day of the month

Hour

Returns a whole number between 0 and 23, inclusive, representing the hour of the day

Minute

Returns a whole number between 0 and 59, inclusive, representing the minute of the hour

Month

Returns a whole number between 1 and 12, inclusive, representing the month of the year

MonthName

Returns a string indicating the specified month

Now

Returns the current date and time according to the setting of your computer's system date and time

Second

Returns a whole number between 0 and 59, inclusive, representing the second of the minute

Time

Returns a Variant of subtype Date indicating the current system time

TimeSerial

Returns a Variant of subtype Date containing the time for a specific hour, minute, and second

TimeValue

Returns a Variant of subtype Date containing the time

Weekday

Returns a whole number representing the day of the week

WeekdayName

Returns a string indicating the specified day of the week

Year

Returns a whole number representing the year


Conversion Category

Functions

CBool

Returns an expression that has been converted to a Variant of subtype Boolean

CByte

Returns an expression that has been converted to a Variant of subtype Byte

CCur

Returns an expression that has been converted to a Variant of subtype Currency

CDate

Returns an expression that has been converted to a Variant of subtype Date

CDbl

Returns an expression that has been converted to a Variant of subtype Double

CInt

Returns an expression that has been converted to a Variant of subtype Integer

CLng

Returns an expression that has been converted to a Variant of subtype Long

CSng

Returns an expression that has been converted to a Variant of subtype Single

CStr

Returns an expression that has been converted to a Variant of subtype String

IsDate

Returns a boolean value indicating whether an expression can be converted to a date

IsNumeric

Returns a boolean value indicating whether an expression can be evaluated as a number


Format Category

Functions

Format

Returns a value formatted according to instructions contained in a format expression

FormatCurrency

Returns an value formatted as a currency value using the currency symbol defined in the system control panel

FormatDateTime

Returns an value formatted as a date or time

FormatNumber

Returns an value formatted as a number

FormatPercent

Returns a value formatted as a percentage (multiplied by 100) with a trailing % character

Hex

Returns a string representing the hexadecimal value of a number

Oct

Returns a string representing the octal value of a number


XArrayDB Reference


XArrayDB Object Properties

Count

Returns the number of elements for a given dimension

DefaultColumnType

Sets/returns the default data type for the specified column

LowerBound

Returns the lower bound for a given dimension

Notify

Controls notification of OLEDBSimpleProviderListener objects

Precision

Sets/returns the floating point precision value

UpperBound

Returns the upper bound for a given dimension

Value

Sets/returns the value of an individual array element


XArrayDB Object Methods

AboutBox

Displays a dialog box with information about the array object

AppendColumns

Appends new columns to an array object

AppendRows

Appends new rows to an array object

Clear

De-allocates all data associated with an array object

Delete

Deletes an index from a given dimension

DeleteColumns

Deletes a range of columns from an array object

DeleteRows

Deletes a range of rows from an array object

Find

Searches for a given value within an array column

Get

Returns the value of an array element

Insert

Inserts a new index into a given dimension

InsertColumns

Inserts new columns into an array object

InsertRows

Inserts new rows into an array object

LoadRows

Loads a VB array into an XArrayDB object

QuickSort

Uses the quicksort method to sort an array

ReDim

Sets the dimensions of an array object while preserving its data

Set

Assigns a value to an array element


XArrayDB Object Constants

XCOMP

Description

Run Time

1 - Equal

XCOMP_EQ

2 - Less Than

XCOMP_LT

3 - Less Than or Equal To

XCOMP_LE

4 - Greater Than

XCOMP_GT

5 - Greater Than or Equal To

XCOMP_GE

6 - Not Equal To

XCOMP_NE

The XCOMP constants are used to specify a comparison operator for the Find method.

XORDER

Description

Run Time

0 - Ascending

XORDER_ASCEND

1 - Descending

XORDER_DESCEND

The XORDER constants are used to specify a search direction for the Find method and a sort order for the QuickSort method.

XTYPE

Description

Run Time

0 - Default

XTYPE_DEFAULT

1 - Boolean

XTYPE_BOOLEAN

2 - Byte

XTYPE_BYTE

3 - Currency

XTYPE_CURRENCY

4 - Date

XTYPE_DATE

5 - Double

XTYPE_DOUBLE

6 - Integer

XTYPE_INTEGER

7 - Long

XTYPE_LONG

8 - Single

XTYPE_SINGLE

9 - String

XTYPE_STRING

10 - Case-sensitive Find or QuickSort

XTYPE_STRINGCASESENSITIVE

11 - Numeric Find or QuickSort

XTYPE_NUMBER

The XTYPE constants are used to specify the data type of a column for the Find and QuickSort methods and the DefaultColumnType property.

AboutBox Method (XArrayDB)

AppendColumns Method (XArrayDB)

AppendRows Method (XArrayDB)

Clear Method (XArrayDB)

Count Property (XArrayDB)

DefaultColumnType Property (XArrayDB)

Delete Method (XArrayDB)

DeleteColumns Method (XArrayDB)

DeleteRows Method (XArrayDB)

Find Method (XArrayDB)

Get Method (XArrayDB)

Insert Method (XArrayDB)

InsertColumns Method (XArrayDB)

InsertRows Method (XArrayDB)

LoadRows Method (XArrayDB)

LowerBound Property (XArrayDB)

Notify Property (XArrayDB)

Precision Property (XArrayDB)

QuickSort Method (XArrayDB)

ReDim Method (XArrayDB)

Set Method (XArrayDB)

UpperBound Property (XArrayDB)

Value Property (XArrayDB)


AboutBox Method (XArrayDB)

Syntax

XArrayDB.AboutBox

Method applies to XArrayDB object.

Arguments

None

Return Value

None

Description

This method displays the version number and copyright notice for XArrayDB.


AppendColumns Method (XArrayDB)

Syntax

XArrayDB.AppendColumns ([count])

Method applies to XArrayDB object.

Arguments

count is an optional long integer specifying the number of columns to be appended. If omitted, this argument defaults to 1.

Return Value

A long integer specifying the number of columns successfully appended.

Description

This method appends count columns to an XArrayDB object and returns the number of columns successfully appended. This method is provided for convenience; the following statements are equivalent:

MyArray.AppendColumns n

MyArray.InsertColumns MyArray.UpperBound(2) + 1, n


AppendRows Method (XArrayDB)

Syntax

XArrayDB.AppendRows ([count])

Method applies to XArrayDB object.

Arguments

count is an optional long integer specifying the number of rows to be appended. If omitted, this argument defaults to 1.

Return Value

A long integer specifying the number of rows successfully appended.

Description

This method appends count rows to an XArrayDB object and returns the number of rows successfully appended. This method is provided for convenience; the following statements are equivalent:

MyArray.AppendRows n

MyArray.InsertRows MyArray.UpperBound(1) + 1, n


AutoRefresh Constants

Applies To

AutoRefresh property

Values

Design Time

Run Time

0 - None

tdbNoRefresh

1 - Immediate

tdbImmediate

2 - When Idle (default)

tdbWhenIdle


BOFAction Constants

Applies To

BOFAction property

Values

Design Time

Run Time

0 - MoveFirst

adDoMoveFirst

1 - StayBOF

adStayBOF


Clear Method (XArrayDB)

Syntax

XArrayDB.Clear

Method applies to XArrayDB object.

Arguments

None

Return Value

None

Description

This method deallocates all data associated with an XArrayDB object while preserving its dimensions. After the Clear method executes, all of the array elements contain empty variants, and both of the following Visual Basic expressions evaluate to True for any element:

IsEmpty(element)

VarType(element) = 0


ComparisonOperation Constants

Applies To

ComparisonOperation property, QueryOperation property.

Values

Design Time

Run Time

0 - <

tdbLessThan

1 - <=

tdbLessThanOrEqual

2 - =

tdbEqual

3 - >=

tdbGreaterThanOrEqual

4 - >

tdbGreaterThan

5 - starts with

tdbStartsWith

6 - contains

tdbContains


Count Property (XArrayDB)

Syntax

XArrayDB.Count (nDim)

Read-only at run time. Not available at design time.
Property applies to XArrayDB object.

Arguments

nDim is a one-based integer specifying an array dimension.

Description

This property returns a long integer that specifies the number of elements contained in a given dimension of an XArrayDB object. The value returned is always equal to:

MyArray.UpperBound(nDim) - MyArray.LowerBound(nDim) + 1

The nDim argument should be 1 for rows and 2 for columns. A trappable error occurs if an invalid dimension is specified.

Example

The following example uses one-based row indexes (the first dimension) and zero-based column indexes (the second dimension):

MyArray.ReDim 1, 100, 0, 5

Dim N As Long

N = MyArray.Count(1) ' returns 100

N = MyArray.Count(2) ' returns 6


DataMode Constants

Applies To

DataMode property.

Values

Design Time

Run Time

0 - DataSource

tdbModeDataSource

1 - MemoryArray

tdbModeMemoryArray

2 - UserEvents

tdbModeUserEvents


DataType Constants

Applies To

Type (Field) property, Type (Parameter) property

Values

Design Time

Run Time

11 – Boolean

tdbTypeBoolean

16 – Byte

tdbTypeByte

6 – Currency

tdbTypeCurrency

7 – Date

tdbTypeDate

5 – Double

tdbTypeDouble

2 – Integer

tdbTypeInteger

3 – Long

tdbTypeLong

4 – Single

tdbTypeSingle

8 – String

tdbTypeString

12 – Variant

tdbTypeVariant


DefaultColumnType Property (XArrayDB)

Syntax

XArrayDB.DefaultColumnType (column)

Read-only at run time. Not available at design time.
Property applies to XArrayDB object.

Arguments

column is a long integer specifying the index of the column whose default data type is being set or returned.

Values

Description

Run Time

0 - Default

XTYPE_DEFAULT

1 - Boolean

XTYPE_BOOLEAN

2 - Byte

XTYPE_BYTE

3 - Currency

XTYPE_CURRENCY

4 - Date

XTYPE_DATE

5 - Double

XTYPE_DOUBLE

6 - Integer

XTYPE_INTEGER

7 - Long

XTYPE_LONG

8 - Single

XTYPE_SINGLE

9 - String

XTYPE_STRING

Description

This property sets or returns the default data type of a column in an XArrayDB object. By default, this property returns 0, which means that the column's data values are not automatically translated to a specific data type.

When using XArrayDB as an OLEDBSimpleProvider data source, you can set the DefaultColumnType property so that bound controls can determine the data type of individual columns.

You can also use this property to specify the default data type for a column when using the Find and QuickSort methods.


DeleteColumns Method (XArrayDB)

Syntax

XArrayDB.DeleteColumns (index, [count])

Method applies to XArrayDB object.

Arguments

index is a long integer specifying the index of the first column to be deleted.

count is an optional long integer specifying the number of columns to be deleted. If omitted, this argument defaults to 1.

Return Value

A long integer specifying the number of columns successfully deleted.

Description

This method deletes count columns from an XArrayDB object starting at column index and returns the number of columns successfully deleted.

Example

The following example initializes an XArrayDB object with 10 rows and 6 columns, then removes the fourth and fifth columns:

MyArray.ReDim 1, 10, 1, 6

Dim i, j As Integer

For i = 1 To 10

For j = 1 To 6

MyArray(i, j) = "Row " & i & ", Col " & j

Next j

Next i

Debug.Print MyArray(1, 4) ' prints Row 1, Col 4

Debug.Print MyArray(1, 5) ' prints Row 1, Col 5

' remove two columns starting at index 4

Dim result As Long

result = MyArray.DeleteColumns(4, 2)

Debug.Print result ' prints 2

Debug.Print MyArray.Count(2) ' prints 4

Debug.Print MyArray(1, 4) ' prints Row 1, Col 6

' the next line now gives a "Subscript out of range" error

Debug.Print MyArray(1, 5)


Delete Method (XArrayDB)

Syntax

XArrayDB.Delete nDim, index

Method applies to XArrayDB object.

Arguments

nDim is a one-based integer specifying an array dimension.

index is a long integer specifying an element position within the dimension nDim.

Return Value

None

Description

This method deletes the element at position index from the dimension specified by nDim while preserving data and shifting the indexes of the remaining elements appropriately.

The nDim argument should be 1 for rows and 2 for columns. A trappable error occurs if an invalid dimension is specified.

Note

This method is provided for backward compatibility with the XArray object. Both of the following statements delete the row whose index is n.

MyArray.Delete 1, n

MyArray.DeleteRows n

Similarly, both of the following statements delete the column whose index is n:

MyArray.Delete 2, n

MyArray.DeleteColumns n

Unlike Delete, the DeleteRows and DeleteColumns methods support the deletion of multiple contiguous elements.


DeleteRows Method (XArrayDB)

Syntax

XArrayDB.DeleteRows (index, [count])

Method applies to XArrayDB object.

Arguments

index is a long integer specifying the index of the first row to be deleted.

count is an optional long integer specifying the number of rows to be deleted. If omitted, this argument defaults to 1.

Return Value

A long integer specifying the number of rows successfully deleted.

Description

This method deletes count rows from an XArrayDB object starting at row index and returns the number of rows successfully deleted.

Example

The following example initializes an XArrayDB object with 10 rows and 6 columns, then removes the first three rows:

MyArray.ReDim 1, 10, 1, 6

Dim i, j As Integer

For i = 1 To 10

For j = 1 To 6

MyArray(i, j) = "Row " & i & ", Col " & j

Next j

Next i

Debug.Print MyArray(1, 1) ' prints Row 1, Col 1

Debug.Print MyArray(2, 1) ' prints Row 2, Col 1

Debug.Print MyArray(8, 1) ' prints Row 8, Col 1

' remove three rows starting at index 1

Dim result As Long

result = MyArray.DeleteRows(1, 3)

Debug.Print result ' prints 3

Debug.Print MyArray.Count(1) ' prints 7

Debug.Print MyArray(1, 1) ' prints Row 4, Col 1

Debug.Print MyArray(2, 1) ' prints Row 5, Col 1

' the next line now gives a "Subscript out of range" error

Debug.Print MyArray(8, 1)


Displaying Query Results


EOFAction Constants

Applies To

EOFAction property

Values

Design Time

Run Time

0 - MoveLast

adDoMoveLast

1 - StayEOF

adStayEOF

2 - AddNew

adDoAddNew


Field Comparison Operation

It is possible to specify that a comparison operation different from "=" (equality) must be used for a certain field in generating the query filter condition.

The equality operation (default) can be replaced with any of the following comparison operations:

=, >, >=, <, <=, starts with, contains.

The operation is determined by the field’s QueryOperation property, which is available in the Fields property page.

For string fields, you may find the starts with operation especially useful; it allows the user to enter only the beginning of a long name. Sometimes, it might be preferrable to use the contains operation, meaning that the search value is contained somewhere in the string data value.

For numeric and date fields, it is often necessary to use inequality comparisons: less than (<), less than or equal (<=), greater than (>), greater than or equal (>=). These are especially useful when you need to enable your users to specify an interval of values. For more information, see Using multiple query fields for a single result field.


Field Function

Syntax

Field(string)

Arguments

string is the name of a TData field.

Description

The Field function returns the value of a field, see True DataControl Fields. It must be used for fields with names containing spaces and other non-identifier characters. It is not necessary for fields whose names are proper identifiers (starts with a letter and contain only letters, digits and underscores), such fields can be referenced in expressions directly.


FieldKind Constants

Applies To

FieldKind property

Values

Design Time

Run Time

0 - Data

tdbDataField

1 - Calculated

tdbCalculatedField

2 - Linked

tdbLinkedField


Field Visibility

You may find it necessary to vary field visibility when switching between query and results modes.

It is always possible to change the collection returned by the Fields property explicitly in code, in the WillOpenData event that occurs before QueryMode changes. Once this is done, you can do anything you want, for example, set a field's Visible property.

But in most cases, it is sufficient to specify that a certain field should appear only in query mode, only in result mode, or in both modes. This can be done easily with the field’s QueryMode property, which is accessible on the Fields property page. Its possible values are:

0 – Both

Field appears in both modes

1 – Query only

Field appears only in query mode

2 – DataSource only

Field appears only in result mode


Find Method (XArrayDB)

Syntax

XArrayDB.Find (row, column, value, [order], [comparison], [type])

Method applies to XArrayDB object.

Arguments

row is a long integer specifying the starting row of the search.

column is a long integer specifying the column to be searched.

value is a variant specifying the value to search for.

order is an XORDER constant that specifies the direction of the search. If omitted, XORDER_ASCEND is assumed.

comparison is an XCOMP constant that specifies the kind of comparion to be performed. If omitted, XCOMP_EQ is assumed.

type is an XTYPE constant that specifies the data type used to coerce column values during comparison. If omitted, XTYPE_DEFAULT is assumed, which means that the data type of the value argument is used.

Return Value

A long integer corresponding to the index of the next row that contains a matching value. If no match is found, the value returned is one less than the lower bound for rows specified in the previous call to the ReDim method.

Description

The Find method searches for a specfied value within a column of an XArrayDB object, starting at a particular row. If a match is found, this method returns the corresponding row index; otherwise, the value returned is equal to:

LowerBound(1) - 1

Example

The following example demonstrates the use of the Find method on a single-column XArrayDB object containing long integers:

MyArray.ReDim 1, 4, 1, 1

MyArray(1, 1) = 198

MyArray(2, 1) = 150

MyArray(3, 1) = 200

MyArray(4, 1) = 250

' search for the value 200

Debug.Print MyArray.Find(1, 1, 200) ' prints 3

' search for a value less than 200

Debug.Print MyArray.Find(1, 1, 200, , XCOMP_LT) ' prints 1


Format Function

Syntax

Format(expression[, format[, firstdayofweek[, firstweekofyear]]])

Arguments

expression is any valid expression.

format (optional) is a valid named or user-defined format expression.

firstdayofweek (optional) is a constant that specifies the first day of the week.

firstweekofyear (optional) is a constant that specifies the first week of the year.

Description

The Format function is equivalent to its Visual Basic counterpart. See Visual Basic documentation for details.

Note

The Format function is accessible only if the TData control is used in Visual Basic. It is inaccessible in other environments, for example on a web page. Using it in True DataControl expressions in non-Visual Basic containers will generate error.


Get Method (XArrayDB)

Syntax

XArrayDB.Get row, column, var

Method applies to XArrayDB object.

Arguments

row and column are long integer indexes identifying a particular array element.

var is a variable that receives a variant value from the specified array element.

Return Value

None

Description

The Get method provides an alternate way of retrieving a value from an XArrayDB element. You can use this method in scripting engines that do not properly resolve the default Value property of XArrayDB.

The var argument receives the variant value of the XArrayDB element specified by the row and column indexes.

Example

The three statements following the variable declaration are all equivalent:

Dim var As Variant

MyArray.Get x, y, var

var = MyArray.Value(x, y)

var = MyArray(x, y)


IIF Function

Syntax

IIF(condition, truepart, falsepart)

Arguments

condition is a boolean expression that determines which expression is evaluated.

truepart is evaluated if condition is True.

falsepart is evaluated if condition is False.

Description

The IIF function is equivalent to its Visual Basic counterpart. That is, it returns the result of one of two expressions depending upon the value of a boolean condition. If the condition (first argument) is True, the function returns the value of the second argument; otherwise, it returns the value of the third argument.


InsertColumns Method (XArrayDB)

Syntax

XArrayDB.InsertColumns (index, [count])

Method applies to XArrayDB object.

Arguments

index is a long integer specifying the index of the first column to be inserted.

count is an optional long integer specifying the number of columns to be inserted. If omitted, this argument defaults to 1.

Return Value

A long integer specifying the number of columns successfully inserted.

Description

This method inserts count columns into an XArrayDB object starting at column index and returns the number of columns successfully inserted.

Example

The following example initializes an XArrayDB object with 10 rows and 6 columns, then inserts a new column before the fourth column:

MyArray.ReDim 1, 10, 1, 6

Dim i, j As Integer

For i = 1 To 10

For j = 1 To 6

MyArray(i, j) = "Row " & i & ", Col " & j

Next j

Next i

Debug.Print MyArray(1, 4) ' prints Row 1, Col 4

Debug.Print MyArray(1, 5) ' prints Row 1, Col 5

' insert a new column at index 4

Dim result As Long

result = MyArray.InsertColumns(4)

Debug.Print result ' prints 1

Debug.Print MyArray.Count(2) ' prints 7

Debug.Print IsEmpty(MyArray(1, 4)) ' prints True

Debug.Print MyArray(1, 5) ' prints Row 1, Col 4

Debug.Print MyArray(1, 6) ' prints Row 1, Col 5


Insert Method (XArrayDB)

Syntax

XArrayDB.Insert nDim, index

Method applies to XArrayDB object.

Arguments

nDim is a one-based integer specifying an array dimension.

index is a long integer specifying an element position within the dimension nDim.

Return Value

None

Description

This method inserts a new element at position index into the dimension specified by nDim while preserving data and shifting the indexes of the existing elements appropriately.

The nDim argument should be 1 for rows and 2 for columns. A trappable error occurs if an invalid dimension is specified.

If index is greater than the value of the UpperBound property for dimension nDim, then UpperBound is adjusted to the new index.

Note

This method is provided for backward compatibility with the XArray object. Both of the following statements insert a new row at index position n.

MyArray.Insert 1, n

MyArray.InsertRows n

Similarly, both of the following statements insert a new column at index position n:

MyArray.Insert 2, n

MyArray.InsertColumns n

Unlike Insert, the InsertRows and InsertColumns methods support the insertion of multiple contiguous elements.


InsertRows Method (XArrayDB)

Syntax

XArrayDB.InsertRows (index, [count])

Method applies to XArrayDB object.

Arguments

index is a long integer specifying the index of the first row to be inserted.

count is an optional long integer specifying the number of rows to be inserted. If omitted, this argument defaults to 1.

Return Value

A long integer specifying the number of rows successfully inserted.

Description

This method inserts count rows into an XArrayDB object starting at row index and returns the number of rows successfully inserted.

Example

The following example initializes an XArrayDB object with 10 rows and 6 columns, then inserts three new rows before the first row:

MyArray.ReDim 1, 10, 1, 6

Dim i, j As Integer

For i = 1 To 10

For j = 1 To 6

MyArray(i, j) = "Row " & i & ", Col " & j

Next j

Next i

Debug.Print MyArray(1, 1) ' prints Row 1, Col 1

Debug.Print MyArray(2, 1) ' prints Row 2, Col 1

Debug.Print MyArray(10, 1) ' prints Row 10, Col 1

' insert three new rows at index 1

Dim result As Long

result = MyArray.InsertRows(1, 3)

Debug.Print result ' prints 3

Debug.Print MyArray.Count(1) ' prints 13

Debug.Print IsEmpty(MyArray(1, 1)) ' prints True

Debug.Print MyArray(4, 1) ' prints Row 1, Col 1

Debug.Print MyArray(5, 1) ' prints Row 2, Col 1

Debug.Print MyArray(13, 1) ' prints Row 10, Col 1


LinkType Constants

Applies To

LinkType property

Values

Design Time

Run Time

0 - None (default)

tdbLinkNone

1 - Outer

tdbLinkOuter

2 - Inner

tdbLinkInner


LoadRows Method (XArrayDB)

Syntax

XArrayDB.LoadRows array, [transpose]

Method applies to XArrayDB object.

Arguments

array is a variant array containing the data to be loaded.

transpose is an optional boolean argument that determines whether the array data should be transposed.

Return Value

None

Description

This method populates an XArrayDB object from a two-dimensional variant array. Typically, the array is derived from a data provider such as ADO or RDO, but it can also be a standard Visual Basic array.

If the transpose argument is True (default), the array elements are copied in row-major order. If transpose is False, or omitted, the array elements are copied in column-major order. The argument should be False if you are using the GetRows method (of the ADO Recordset), and True if you are using a standard Visual Basic array.

Example

The following example copies ten rows of data from a DAO Recordset to an XArrayDB object in column-major order, then associates the XArrayDB object with a TData control. Note that it is not necessary to invoke the ReDim method when using LoadRows:

Dim MyArray As New XArrayDB

Data1.Recordset.MoveFirst

MyArray.LoadRows Data1.Recordset.GetRows(10)

Set TData1.Array = MyArray

TData1.ReBind


LowerBound Property (XArrayDB)

Syntax

XArrayDB.LowerBound (nDim)

Read-only at run time. Not available at design time.
Property applies to XArrayDB object.

Arguments

nDim is a one-based integer specifying an array dimension.

Description

This property returns a long integer that specifies the lower bound index for a given dimension of an XArrayDB object.

The nDim argument should be 1 for rows and 2 for columns. A trappable error occurs if an invalid dimension is specified.

Example

The following example uses one-based row indexes (the first dimension) and zero-based column indexes (the second dimension):

MyArray.ReDim 1, 100, 0, 5

Dim N As Long

N = MyArray.LowerBound(1) ' returns 1

N = MyArray.LowerBound(2) ' returns 0


ModificationMode Constants

Applies To

ModificationMode property

Values

Design Time

Run Time

0 – None

tdbModifModeNone

1 – Immediate

tdbModifModeImmediate

2 – Leaving control (default)

tdbModifModeOnControlExit


Notify Property (XArrayDB)

Syntax

XArrayDB.Notify = boolean

Read-only at run time. Not available at design time.
Property applies to XArrayDB object.

Description

This property sets or returns a boolean that determines whether notifications should be sent to all OLEDBSimpleProviderListener objects associated with an XArrayDB object.

If True (the default), notifications are sent for row deletions, row insertions, and cell value changes.

If False, all notifications are suppressed.

When using XArrayDB as an OLEDBSimpleProvider data source, you can set the Notify property to False to suppress notification during initialization or massive updates, then set it back to True to re-enable listener notifications.


Orientation Constants

Applies To

Orientation property

Values

Design Time

Run Time

0 - Horizontal (default)

tdbHorizontal

1 - Vertical

tdbVertical


Precision Property (XArrayDB)

Syntax

XArrayDB.Precision = double

Read-only at run time. Not available at design time.
Property applies to XArrayDB object.

Description

This property sets or returns a double that determines the precision used for floating point comparisons performed during sorting and searching operations. By default, this property returns 0, and all floating point values stored within an XArrayDB object are compared as is.

You can set the Precision property to a nonzero value to specify a tolerance for floating point values processed by the Find and QuickSort methods. If the difference between two values is less than or equal to the Precision value, then XArrayDB considers them to be equal for comparison purposes.

Example

The following example initializes a single-column XArrayDB object containing double-precision numbers, then uses the Find method to demonstrate the effect of the Precision property:

MyArray.ReDim 1, 4, 1, 1

MyArray(1, 1) = 198#

MyArray(2, 1) = 150#

MyArray(3, 1) = 200#

MyArray(4, 1) = 250#

' find an exact match for 200#

Debug.Print MyArray.Find(1, 1, 200#) ' prints 3

' change the precision to plus or minus 5

MyArray.Precision = 5#

' find values between 195# and 205#

Debug.Print MyArray.Find(1, 1, 200#) ' prints 1


QueryMode Constants

Applies To

QueryMode property

Values

Design Time

Run Time

0 – Both (default)

tdbQueryAndDataSource

1 – Query only

tdbQueryOnly

2 – DataSource only

tdbDataSourceOnly


QuickSort Method (XArrayDB)

Syntax

XArrayDB.QuickSort rowstart, rowend, column1, order1, type1 [, …, column10, order10, type10]

Method applies to XArrayDB object.

Arguments

rowstart is a long integer specifying the first row to be sorted.

rowend is a long integer specifying the last row to be sorted.

column1 through column10 are long integers specifying the indexes of the columns to be sorted, in the order in which they are applied.

order1 through order10 are XORDER constants specifying the sort order of the columns.

type1 through type10 are XTYPE constants specifying the data type used to coerce column values during comparison.

Return Value

None

Description

The QuickSort method sorts a range of rows in an XArrayDB object according to the specified column(s). The optional arguments must be specified in groups of three. That is, if you supply a column argument, you must supply its order and type arguments as well. You must provide at least one argument triplet, otherwise a trappable error will occur.

Example

The following example initializes a single-column XArrayDB object containing date values in a variety of formats, then uses the QuickSort method to reorder the array in ascending order:

MyArray.ReDim 1, 4, 1, 1

MyArray(1, 1) = DateSerial(1998, 2, 11) ' date

MyArray(2, 1) = "January 22, 1998" ' string

MyArray(3, 1) = #10/4/1998# ' date literal

MyArray(4, 1) = CLng(#1/27/1998#) ' long integer

' sort all rows of the array

MyArray.QuickSort 1, 4, 1, XORDER_ASCEND, XTYPE_DATE

' print the results

Debug.Print MyArray(1, 1) ' prints January 22, 1998

Debug.Print MyArray(2, 1) ' prints 35822

Debug.Print MyArray(3, 1) ' prints 2/11/98

Debug.Print MyArray(4, 1) ' prints 10/4/98


ReDim Method (XArrayDB)

Syntax

XArrayDB.ReDim rowLB, rowUB, columnLB, columnUB

Method applies to XArrayDB object.

Arguments

rowLB and rowUB are long integers specifying the lower and upper bounds for row indexes.

columnLB and columnUB are long integers specifying the lower and upper bounds for column indexes.

Return Value

None

Description

This method is used to set or reset the dimensions of an XArrayDB object while preserving any existing data. Since a newly created XArrayDB object does not have any default dimensions, you must use the ReDim method before you can assign or access array elements.

Example

The following example creates and initializes a two-dimensional XArrayDB object. The first dimension has 100 elements, with indexes starting at 1 and ending at 100. The second dimension has 6 elements, with indexes starting at 0 and ending at 5.

Dim MyArray As New XArrayDB

MyArray.ReDim 1, 100, 0, 5


SeekFlag Constants

Applies To

UserFindData event

Values

Design Time

Run Time

0 - <

tdbSeekLT

1 - <=

tdbSeekLE

2 - =

tdbSeekEQ

3 - >=

tdbSeekGE

4 - >

tdbSeekGT

5 - starts with

tdbSeekBeginsWith

6 - contains

tdbSeekContains

7 - <> (not equal)

tdbSeekNE

4096 - case sensitive

tdbSeekCaseSensitive

8192 - case insensitive

tdbSeekCaseInsensitive


Set Method (XArrayDB)

Syntax

XArrayDB.Set row, column, value

Method applies to XArrayDB object.

Arguments

row and column are long integer indexes identifying a particular array element.

value is a variant to be assigned to the specified array element.

Return Value

None

Description

The Set method provides an alternate way of assigning a value to an XArrayDB element. You can use this method in scripting engines that do not properly resolve the default Value property of XArrayDB.

The value argument is the variant value to be assigned to the XArrayDB element specified by the row and column indexes.

Example

The following three statements are equivalent:

MyArray.Set x, y, "Hello"

MyArray.Value(x, y) = "Hello"

MyArray(x, y) = "Hello"


TDButtonEnabledEnum Constants

Applies To

EnableButton method

Values

0 – tdbButtonEnabled
1 – tdbButtonDisabled
2 – tdbButtonEnabledDefault


TDButtonEnum Constants

Applies To

Methods: EnableButton, PressButton, SetButtonPicture.

Event: ButtonPressed.

Values

0 - tdbButtonFirst
1 - tdbButtonPrevious
2 - tdbButtonNext
3 - tdbButtonLast
4 - tdbButtonNextPage
5 - tdbButtonPrevPage
6 - tdbButtonAdd
7 - tdbButtonDelete
8 - tdbButtonUpdate
9 - tdbButtonCancel
10 - tdbButtonBookmarks
11 - tdbButtonFind
12 – tdbButtonQuery


TDStringEnum Constants

Applies To

SetUIString method

Values

0 - tdbStringRestorePromp
1 - tdbStringTooltipFirst
2 - tdbStringTooltipPrevious
3 - tdbStringTooltipNext
4 - tdbStringTooltipLast
5 - 5tdbStringTooltipNextPage
6 - tdbStringTooltipPrevPage
7 - tdbStringTooltipAdd
8 - tdbStringTooltipDelete
9 - tdbStringTooltipUpdate
10 - tdbStringTooltipCancel
11 - tdbStringTooltipBookmarks
12 - tdbStringTooltipFind
13 - tdbStringTooltipQuery
14 - tdbStringConfirmDelete
15 - tdbStringConfirmCancel
16 - tdbStringBookmarksCaption
17 - tdbStringBookmarksNameLabel
18 - tdbStringBookmarksAdd
19 - tdbStringBookmarksDelete
20 - tdbStringBookmarksGoto
21 - tdbStringBookmarksCancel
23 - tdbStringFindCaption
24 - tdbStringFindFieldLabel
25 - tdbStringFindWhatLabel
26 - tdbStringFindMatchLabel
27 - tdbStringFindSearchLabel
28 - tdbStringFindMatchCase
29 - tdbStringFindFirst
30 - tdbStringFindNext
31 – tdbStringFindCancel
32 - tdbStringFindMatchEqual
33 - tdbStringFindMatchGreaterOrEqual
34 - tdbStringFindMatchGreater
35 - tdbStringFindMatchLessOrEqual
36 - tdbStringFindMatchLess
37 - tdbStringFindMatchStartsWith
38 - tdbStringFindMatchContains
39 - tdbStringFindSearchUp
40 - tdbStringFindSearchDown
41 – dbStringFindSearchAll


True DataControl in Query Mode

While in query mode (QueryMode = True), a TData control is disconneted from the database. Its underlying data represent a query, which it stores in a memory array (an XArrayDB object), just as in memory array data mode. See Memory Array Mode for details. The current query data can be accessed via the Array property if needed. Exactly as in memory array mode, it is possible to populate the query data before it is displayed, in the OpenData event.

Only data fields are visible to the user in query mode; calculated and linked fields are hidden. You can further customize a field’s visibility with its QueryMode property, by making some fields appear only in query mode, or only in result mode.


UpperBound Property (XArrayDB)

Syntax

XArrayDB.UpperBound (nDim)

Read-only at run time. Not available at design time.
Property applies to XArrayDB object.

Arguments

nDim is a one-based integer specifying an array dimension.

Description

This property returns a long integer that specifies the upper bound index for a given dimension of an XArrayDB object.

The nDim argument should be 1 for rows and 2 for columns. A trappable error occurs if an invalid dimension is specified.

Example

The following example uses one-based row indexes (the first dimension) and zero-based column indexes (the second dimension):

MyArray.ReDim 1, 100, 0, 5

Dim N As Long

N = MyArray.UpperBound(1) ' returns 100

N = MyArray.UpperBound(2) ' returns 5


Using Multiple Query Fields for a Single Result Field

A common task in creating ad-hoc query forms is to allow the user to specify an interval of field values. True DataControl provides this ability as a particular case of the following general rule:

You can create several data fields connected to the same SourceRecordset field, by setting the DataSourceField property to the name of a SourceRecordset field, for each of them.

At design time, for each such field, create a new field in the Fields property page, select the Data radio button, give the field a Name, and select the desired data source field (the same for each newly created field) from the DataSourceField combo box.

You can specify two TData control fields connected to the same SourceRecordset field: set QueryOperation to ">=" for one of them, and to "<=" for the other.

By binding two controls to these two fields, you enable your user to enter an interval of field values in the query.

Normally, such fields are invisible in result mode, QueryMode = 1 – Query only, but that is up to you, of course.

Example:

If you want to allow end users to specify a range of dates for the OrderDate field, you can do so by creating two new data fields: OrderDateFrom and OrderDateTo, setting the DataSourceField property to OrderDate for both of them. For the OrderDateFrom, field specify QueryOperation = >=, and for OrderDateTo you set QueryOperation = <=. You make them visible only in query mode (QueryMode = 1 – Query only). The original OrderDate field remains in your TData control too, because you want the OrderDate to appear in the result recordset.


Using one TData Control

The same TData control can be used for both entering a query and displaying the query results. Setting QueryMode to False after a query has been entered generates a query condition (i.e., filter) and switches from query mode to result mode, reconnecting to the data source. The generated query filter is applied to the resulting recordset. See Using True DataControl to formulate a query for more information.

To switch between query and result modes, set the QueryMode property in code, or use the Query toggle button on the TData control. The Query toggle button is enabled by the ButtonQuery property.

If you need to reset the query filter, that is, to switch to result mode without any restrictions, with an empty filter, you can so by emptying the underlying XArrayDB object before setting QueryMode =False. You can access the XArrayDB object containing the query with the control’s Array property.


Using True DataControl to Formulate a Query

Query mode is allowed only for a TData control in data source mode, DataMode = 0 - DataSource. Identical TData fields are used in query and result mode, but the function of a data field is different:

In result mode, a data field is used to display a field of data in the resulting recordset. In query mode, the value entered by the end-user in a data field represents a query, or search value, it is used to generate a condition imposed on the resulting recordset.

For a TData control in query mode, the QueryFilter property returns the filter condition generated from the data entered by the end-user.

Each non-empty field value generates a condition of the form:

DataSourceField = value

where DataSourceField is determined by the field’s DataSourceField property, and the value is the field value entered by the end-user in query mode. This can be further generalized by using comparison operations other than "=." For more information, see Field comparison operation.

If there are mutliple non-empty field values in a row, their corresponding conditions are joined with AND. Conditions generated by different rows are joined with OR.

Example:

Suppose the user entered two rows of data in query mode:

ProductName

SupplierID

Chocolade

22

1

Generated query will be:

(ProductName = “Chocolade” AND SupplierID = 22) OR SupplierID = 1


Using Two TData Controls

Another option is to use two different TData controls: one for entering the query and the other for displaying query results.

To do this, both controls must have the same data source properties, i.e., refer to the same SourceRecordset. One of them has TData1. QueryMode =True permanently, whereas the other has TData2.QueryMode = False. Different bound controls are used to represent the data of the query (controls bound to TData1) and the results (controls bound to TData2).

When you need to apply the query to the second TData control, use the QueryFilter property in the following manner:

TData2.SourceRecordset.Filter = TData1.QueryFilter

The QueryFilter property contains the current query (i.e., ADO filter) generated from the data in TData1.

Obviously, you can use QueryFilter to impose the generated filter on any ADO recordset, not necessarily the SourceRecordset of a TData control.


Value Property (XArrayDB)

Syntax

XArrayDB.Value (row, column) = variant

Read/Write at run time. Not available at design time.
Property applies to XArrayDB object.

Arguments

row and column are long integer indexes identifying a particular array element.

Description

The Value property sets or returns the variant value of an individual XArrayDB element. For instance, if x is a valid row index and y is a valid column index, the following statement assigns a string value to an individual element:

MyArray.Value(x, y) = "Hello"

Similarly, the following statement retrieves it:

s$ = MyArray.Value(x, y)

Note that the Value property is the default property for XArrayDB. Therefore, the preceding statements can be shortened to:

MyArray(x, y) = "Hello"

s$ = MyArray(x, y)

Example

Since the elements of an XArrayDB object are true variants, you can arbitrarily mix data types within a row (or column), as in the following example:

MyArray(1, 1) = "Hello" ' string

MyArray(1, 2) = 1.98 ' floating point

MyArray(1, 3) = 250000 ' long integer

MyArray(2, 2) = True ' boolean

MyArray(2, 3) = LoadPicture("xyz.bmp") ' bitmap

Note

Although XArrayDB can be used to store picture data, True DataControl's storage mode (DataMode 4) only accepts string and numeric data, and will not render XArrayDB picture data as an in-cell graphic.


XArrayDB Reference

XArrayDB Object Properties

XArrayDB Object Methods

XArrayDB Object Constants