gint rules for gint version v8i - bentley communities · gint rules for gint version v8i gint v8i...

245
gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

Upload: ngokiet

Post on 06-Apr-2018

316 views

Category:

Documents


9 download

TRANSCRIPT

Page 1: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

gINT Rules for gINT Version V8i gINT V8i User Guide

DAA039590-1/0001

Page 2: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 1 —

The information in this publication is subject to change without notice and does not represent a commitment on the part of Bentley. The software described in this document is furnished under a license agreement or nondisclosure agreement. The software must be used or copied only in accordance with the terms of the agreement.

COPYRIGHT NOTICE

Copyright (c) 2011 Bentley Systems, Incorporated. All rights reserved.

Including software, file formats, and audiovisual displays; may only be used pursuant to applicable software license agreement; contains confidential and proprietary information of Bentley Systems, Incorporated and/or third parties which is protected by copyright and trade secret law and may not be provided or otherwise made available without proper authorization.

RESTRICTED RIGHTS LEGENDS

If this software is acquired for or on behalf of the United States of America, its agencies and/or instrumentalities ("U.S. Government"), it is provided with restricted rights. This software and accompanying documentation are "commercial computer software" and "commercial computer software documentation," respectively, pursuant to 48 C.F.R. 12.212 and 227.7202, and "restricted computer software" pursuant to 48 C.F.R. 52.227-19(a), as applicable. Use, modification, reproduction, release, performance, display or disclosure of this software and accompanying documentation by the U.S. Government are subject to restrictions as set forth in this Agreement and pursuant to 48 C.F.R. 12.212, 52.227-19, 227.7202, and 1852.227-86, as applicable. Contractor/Manufacturer is Bentley Systems, Incorporated, 685 Stockton Drive, Exton, PA 19341-0678.

Unpublished - rights reserved under the Copyright Laws of the United States and International treaties.”

Bentley Systems Inc. Corporate Headquarters 685 Stockton Drive Exton, PA 19341, United States Web Site: http://www.bentley.com/en-US/Products/gINT/ Sales and General Support: http://www.bentley.com/en-US/Corporate/Contact+Us/

Page 3: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 2 —

Contents Introduction .......................................................................................................................................... 10

What are gINT Rules? ............................................................................................................................. 10

Sample gINT Rules Projects ................................................................................................................. 10

What you can do with gINT Rules ...................................................................................................... 10 Introduction .................................................................................................................................................. 10

Data Validation ........................................................................................................................................... 10

Calculations ................................................................................................................................................... 11

Interpretation ............................................................................................................................................... 11

Data Pre-population .................................................................................................................................. 12

Security and Interface Alteration ........................................................................................................ 12

Create your own commands ................................................................................................................... 12

gINT Rules Overview .............................................................................................................................. 13

gINT Rules is Programming ................................................................................................................. 14

The Code Editor ................................................................................................................................... 16 Introduction ............................................................................................................................................... 16

Dialog Box Size and Position ................................................................................................................ 16

The List Window ...................................................................................................................................... 17

The List Window Buttons ........................................................................................................................ 17

The Code Window .................................................................................................................................... 18

Menus and Toolbar .................................................................................................................................... 19

The Code Window Command Buttons ............................................................................................... 20

Running Code in the Code Window ..................................................................................................... 20

The gINT Rules Code Language ...................................................................................................... 22 Introduction ............................................................................................................................................... 22

Architecture................................................................................................................................................ 22

Procedures .................................................................................................................................................. 23

Language Components ........................................................................................................................... 26

Operators ........................................................................................................................................................ 26

Variables ......................................................................................................................................................... 28

Constants ........................................................................................................................................................ 29

Array Variables ............................................................................................................................................ 30

User Defined Types ..................................................................................................................................... 32

Object Variables........................................................................................................................................... 33

Page 4: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 3 —

With…End With ........................................................................................................................................... 34

Line Continuations ..................................................................................................................................... 34

Comments ....................................................................................................................................................... 35

Scope of Objects ........................................................................................................................................ 35

Variables and Constants .......................................................................................................................... 35 External DLL Procedures ......................................................................................................................... 36

Procedures ..................................................................................................................................................... 36

Controlling Execution Flow .................................................................................................................. 36

Call..................................................................................................................................................................... 37

CallByName ................................................................................................................................................... 37

Do…Loop ......................................................................................................................................................... 38

End .................................................................................................................................................................... 39

Exit Sub/Exit Function.............................................................................................................................. 39

For…Each ....................................................................................................................................................... 39

For…Next ........................................................................................................................................................ 40

GoTo .................................................................................................................................................................. 41

If...Else...End If ............................................................................................................................................... 41

Select Case…End Select ............................................................................................................................. 42

Stop ................................................................................................................................................................... 42

The gINTRules Object ........................................................................................................................ 43 Introduction ............................................................................................................................................... 43

gINT Rules Properties ............................................................................................................................ 46

BatchMode ..................................................................................................................................................... 46

CancelChanges ............................................................................................................................................. 46

CancelCommand .......................................................................................................................................... 47

CurrentApplication .................................................................................................................................... 48

CurrentCommand ....................................................................................................................................... 50

CurrentProject.............................................................................................................................................. 52

ErrorMessage ............................................................................................................................................... 52

FieldCaption .................................................................................................................................................. 53

FolderPath ..................................................................................................................................................... 53

PointInsideArea ........................................................................................................................................... 54

ProcedureName ........................................................................................................................................... 55

Success ............................................................................................................................................................. 55

Page 5: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 4 —

SurfaceZValueFromXY .............................................................................................................................. 56

TableCaption................................................................................................................................................. 59

gINTRules Methods ................................................................................................................................. 59

AlignmentCoorFromStaOff ..................................................................................................................... 59

AlignmentStaOffFromCoor ..................................................................................................................... 60 DisplayQueryResults .................................................................................................................................. 62

EndProgram .................................................................................................................................................. 63

ExecuteProgram .......................................................................................................................................... 64

FileDialogFnB ............................................................................................................................................... 66

FolderDialogFnB ......................................................................................................................................... 68

LibraryTableDataGetFnB ........................................................................................................................ 69

LookupListGetDataFnB ............................................................................................................................ 71

PickListFnS .................................................................................................................................................... 72

PointInsideAreaInit .................................................................................................................................... 75

ProjectTableDataGetFnB ........................................................................................................................ 77

ProjectTableFieldExistsFnB ................................................................................................................... 77

RunScript ........................................................................................................................................................ 79

UUID ................................................................................................................................................................. 81

gINTRules.GintConfig Properties ....................................................................................................... 81

ClientID, CompanyAddress, CompanyEMail, CompanyFax, CompanyLocation, CompanyName, CompanyPhone .......................................................................................................... 81

LibraryFile ..................................................................................................................................................... 82

UserName ....................................................................................................................................................... 82

gINTRules.GintConfig Methods ........................................................................................................... 83

HideAppGroup .............................................................................................................................................. 83

HideApplication ........................................................................................................................................... 83

gINTRules.GoogleEarth Object ............................................................................................................ 86

gINTRules.GoogleEarth Properties ................................................................................................... 86

ProgramExists .............................................................................................................................................. 86 gINTRules.GoogleEarth Methods ....................................................................................................... 87

AddFolder ....................................................................................................................................................... 87

AddPointXxxx Methods ............................................................................................................................. 88

AddPointComponentCoor ........................................................................................................................ 89

AddPointSingleFieldDecimalCoor ........................................................................................................ 90

AddPointSingleFieldTextCoor ............................................................................................................... 91

Page 6: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 5 —

AddScreenOverlay ...................................................................................................................................... 91

Execute ............................................................................................................................................................ 92

Initialize .......................................................................................................................................................... 93

gINTRules.GridData Properties .......................................................................................................... 94

CellColor .......................................................................................................................................................... 94 CurrentRow ................................................................................................................................................... 95

DataArray ...................................................................................................................................................... 96

DataValue....................................................................................................................................................... 97

DeletedRecordData .................................................................................................................................... 97

ErrorCol .......................................................................................................................................................... 98

ErrorRow ........................................................................................................................................................ 98

FieldCol ............................................................................................................................................................ 99

FieldName ...................................................................................................................................................... 99

FirstVisibleFieldPs ...................................................................................................................................... 99

ForceSave .................................................................................................................................................... 100

ForeignKeyValues .................................................................................................................................... 100

IsManualEntryMode ............................................................................................................................... 101

ParentGridData ........................................................................................................................................ 101

ParentRecord ............................................................................................................................................. 102

ParentTableErrorField .......................................................................................................................... 102

RefreshParent ............................................................................................................................................ 103

RowSaveFlag .............................................................................................................................................. 103

TableName.................................................................................................................................................. 104

gINTRules.GridData Methods ........................................................................................................... 104

ForceRefresh .............................................................................................................................................. 104

HideField ...................................................................................................................................................... 105

HideGroup ................................................................................................................................................... 106

HideTable .................................................................................................................................................... 106

ReadingsListLoadFnB ............................................................................................................................ 107 gINTRules.SoilClass Object ................................................................................................................ 109

Description .................................................................................................................................................. 109

gINTRules.SoilClass Properties........................................................................................................ 109

gINT Rules Events ............................................................................................................................. 113 Introduction ............................................................................................................................................ 113

Page 7: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 6 —

Table Events ............................................................................................................................................ 114

gINT Rules Procedure on Empty Dataset ...................................................................................... 115

gINT Rules Procedure After Updating Grid .................................................................................. 116

gINT Rules Pre-process on Save......................................................................................................... 116

Native Code Procedure on Save ......................................................................................................... 116 gINT Rules Procedure on Save ........................................................................................................... 116

gINT Rules Procedure on Deletion ................................................................................................... 116

gINT Rules Procedure After Save ...................................................................................................... 117

gINT Rules Procedure Leaving Tab.................................................................................................. 118

System Events ......................................................................................................................................... 118

On Library Open ....................................................................................................................................... 118

Before Command ...................................................................................................................................... 119

On Open Project for Input .................................................................................................................... 120

Special Features ................................................................................................................................ 121 Working with Dialog Boxes ............................................................................................................... 121

Overview ...................................................................................................................................................... 121

Dialog Controls ......................................................................................................................................... 124

Dialog Properties ..................................................................................................................................... 125

The InputBox .......................................................................................................................................... 125

Popup Menus .......................................................................................................................................... 126

Showing Messages ................................................................................................................................ 127

Using Multiple Modules ...................................................................................................................... 131

Running External DLLs ....................................................................................................................... 132

External Object References ............................................................................................................... 133

Running Other Programs ................................................................................................................... 134

Rerunning Code ..................................................................................................................................... 135

Importing Data and Convert Projects............................................................................................ 135

gINT Rules Add-Ins .......................................................................................................................... 137 Description .............................................................................................................................................. 137

The Add-Ins Manager .......................................................................................................................... 138

Sample Usage .......................................................................................................................................... 140

Interaction with Field Rules ......................................................................................................... 142 The Basic Process ............................................................................................................................. 143 Code Samples ..................................................................................................................................... 154

Introduction ............................................................................................................................................ 154

Page 8: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 7 —

Setting Up ................................................................................................................................................. 154

Sample Data ............................................................................................................................................. 154

Overview ...................................................................................................................................................... 154

First Code Iteration ................................................................................................................................. 155

Second Code Iteration: Encapsulating the Percent Calculations ........................................ 161 Third Code Iteration: Encapsulating the check against Hole Depth ................................. 164

Hooking the code to the Save Event ................................................................................................. 168

CPT Data ................................................................................................................................................... 169

Overview ...................................................................................................................................................... 169

Code ............................................................................................................................................................... 170

Hooking the code to the Save Event ................................................................................................. 175

Lithology Data ........................................................................................................................................ 176

Overview ...................................................................................................................................................... 176

Code ............................................................................................................................................................... 176

Hooking the code to the Save Event ................................................................................................. 179

Chemistry Data ....................................................................................................................................... 180

Overview ...................................................................................................................................................... 180

Code ............................................................................................................................................................... 182

Hooking the code to the Save Event ................................................................................................. 187

Creating an Auxiliary Module ........................................................................................................... 187

What To Do if Fields Do Not Exist ................................................................................................... 187

Initializing Common Variables ......................................................................................................... 188

Defining Field Variables as Constants ........................................................................................... 189

Converting to a DLL ......................................................................................................................... 190 Introduction ............................................................................................................................................ 190

Process Summary .................................................................................................................................. 190

Building a VB.NET DLL ........................................................................................................................ 193

Setting up the VB.NET Project ............................................................................................................ 193

Inserting the gINT Rules Code to the .NET Project .................................................................... 203

Rewriting the InitFieldsFnB function .............................................................................................. 206

Rewriting the Hole Depth Warning Dialog................................................................................... 210

Clearing Remaining Errors and Warnings ................................................................................... 212

Late Binding ............................................................................................................................................... 214

Compiling the DLL ................................................................................................................................... 216

Page 9: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 8 —

Obfuscating the the DLL........................................................................................................................ 216

Using the DLL in gINT Rules ............................................................................................................. 216

Special Note to Add-On Developers .................................................................................................. 218

Debugging within the .NET Environment ..................................................................................... 219

Network Trust Issues within the .NET Environment ................................................................ 220 Notes on Redistribution .............................................................. Error! Bookmark not defined. Step by Step for Redistribution ................................................ Error! Bookmark not defined.

Appendices ......................................................................................................................................... 227 Compatibility with Visual Basic ....................................................................................................... 227

Items Available in VBA But Not Supported in gINT Rules ...................................................... 227

Items Available in gINT Rules Not Supported in VBA .............................................................. 228 Naming Conventions and Programming Style ........................................................................... 228

Dynamic Variables .................................................................................................................................. 229

Constants ..................................................................................................................................................... 232

Functions ..................................................................................................................................................... 233

Indentations ............................................................................................................................................... 233

Declarations ............................................................................................................................................... 233

Procedure Argument List ..................................................................................................................... 235

Procedure Headers .................................................................................................................................. 235

String Concatenation ............................................................................................................................. 235

If and IIf ........................................................................................................................................................ 236

Avoid Literal Values ................................................................................................................................ 236

Special Notes ........................................................................................................................................... 237

Creating Records with Extended Keys ............................................................................................ 237

Creating a Table in Code ....................................................................................................................... 237

Clearing Numeric Fields ........................................................................................................................ 238

Considerations for Porting to VB.NET 2005 ............................................................................... 238

Introduction ............................................................................................................................................... 238

Writing your Code Correctly the First Time ................................................................................. 239

What you need to do after Porting the Code ................................................................................ 241

Page 10: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 9 —

Page 11: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 10 —

Introduction

What are gINT Rules?

Database rules are pre-defined processes that occur at certain events. These rules can perform various tasks like data validation. gINT Rules Code allows you to write programs inside of gINT. The language that is used is a derivative of VBA (Microsoft's Visual Basic for Applications). This is programming and you must be a programmer to use this facility.

If you have little or no experience with programming, there are many excellent books and on-line references to teach you. Also, the macro programming language of all Microsoft products (Word, Excel, ACCESS, and so on) uses VBA, so if you have programmed in these products you already know quite a bit; if not, learning the language in gINT will give you a big head start on working in these and many other products.

gINT Rules Code will run under any level of gINT 6 and later. gINT Logs does not have access to the code editor but gINT Logs can execute gINT Rules code modules written under gINT Logs Plus or gINT Professional.

Sample gINT Rules Projects

Two pages on the gINT Software Web site, gINT Rules Sample Code (www.gintsoftware.com/support_gintrules.html) and Specialty Applications (www.gintsoftware.com/support_applications.html), provide fully functional gINT Rules projects. We have found many clients who have never programmed previously start by loading one of these projects which is close to a need they have and then modify it to meet their requirements. From there they have learned to write their own code.

In the next section we outline some of the things you can do with gINT Rules and reference one or more of the above projects on our Web site as examples of those capabilities. We add to these samples regularly so check these pages periodically for new postings.

Note that one of these samples, GRA005, will actually write code procedure skeletons for your own gINT Rules procedures for saving and pre-populating tables.

What you can do with gINT Rules

Introduction

This section gives you some idea of the range of possibilities for gINT Rules. This is not an exhaustive list. Our clients find new uses for gINT Rules all the time. Hopefully this section will show you where you can best start to make use of gINT Rules in your own practice.

Data Validation

gINT provides many automatic validation checks of your data, mainly through native

Page 12: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 11 —

database rules, for example, duplicate records, data inappropriate for a specified data type (text in a numeric field), all child records must have associated parent records, etc. In addition you can add simple rules that do not require programming through the “Required” property of fields, the “Field Rules” property of some field types, and the “Lookup” property of text fields. Search Help for further details of these capabilities. gINT Rules are needed for data validation for rules that cannot be handled by these simple rules.

Data validation is probably the most common usage of gINT Rules. For example:

• RQD must be less than or equal to sample recovery. • Layers must not overlap nor have gaps. • Depth-related data cannot have depth values deeper than the hole depth. • If a soil is a clay the consistency cannot be “very loose”.

So why doesn’t gINT provide these rules automatically? The DOS version did provide many such validations because that version was mainly a fixed database and therefore the program had intelligence concerning the data. However, with the jump to Windows (version 4 of gINT) the data is completely user-definable and therefore gINT has no knowledge concerning the relationships between the data. This jump to user-definable data structures was a great step forward for meeting our clients’ needs but a big step backward in data validation. gINT Rules brings back the validation component and puts it in your hands.

One exception to this lack of data intelligence in gINT is the built-in lab testing facility. The core of this capability is a fixed database and therefore the program has inserted many validation rules for you. You are free to add more through gINT Rules.

gINT Rules samples: See GR001, GR004, and GR012 on the gINT Rules Sample Code page on our Web site.

Calculations • Create your own lab testing screens. • Generate Project Statistics. • Convert from one coordinate system to another. • Calculate water depth below ground from the water depths below top of casing. • Generate soil classifications based on lab results.

gINT Rules samples: See GR001, GR002, GR003, GR007, GR008, GR011, and GR017 on the gINT Rules Sample Code page and CBR Test Results and Concrete Test Results on the Specialty Applications page.

Interpretation • Mark a record if a chemical result beyond the specified exceedence limit. • Generate soil properties based on CPT results.

Page 13: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 12 —

• Estimate the date of drilling completion for a project based on the drilling rates to date.

gINT Rules samples: See GR001, GR006, and GR008 on the gINT Rules Sample Code page.

Data Pre-population • Insert hydrometer time readings for new tests. • Insert default sample top depths and types to the hole depth on new sample data for

each borehole. • Insert dynamic probe depths to the depth of the hole. • Dynamically change the default sieves on a test by test basis. • Insert inclinometer depths for each reading date.

gINT Rules samples: See GR005 on the gINT Rules Sample Code page.

Security and Interface Alteration • Restrict who can modify different tables in Input. • Hide application groups and/or applications based on who is logged in. • Hide groups, tables, and/or fields in the current project based on who is logged in or

the project type.

gINT Rules samples: See GR009, GR014, and GR015 on the gINT Rules Sample Code page.

Create your own commands

The gINT Rules Add-Ins facility allows you to insert commands under an “Add-Ins” menu in both the Input and Library Data applications. These commands look and work just like the built-in commands in gINT. One of the most important benefits is that this facility allows you to encapsulate multiple step processes that would normally require training a person to perform into a simple click of a menu and answering some simple questions. This embeds custom, expert knowledge into your software. Some examples:

• Import CPT data.

• Generate reports filtered on stratigraphic units.

• Generate N value statistics filtered on stratigraphic units.

• Generate fence baselines perpendicular to a centerline at specific centerline locations.

• Find a closed area or areas within multiple closed areas in which a specific X,Y coordinate resides. Useful for CPT interpretation.

• Order your boreholes based on your own, custom sorting algorithm.

Page 14: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 13 —

• Display information from your projects in Google EarthTM.

gINT Rules samples: See GRA001 – GRA008 on the gINT Rules Sample Code page.

gINT Rules Overview

Currently gINT Rules Code is available in the INPUT and DATA DESIGN Library Data applications. Code is written and edited using the gINT Rules gINT Rules Code menu option. You can write code that will be executed on various events in these two applications. In addition, gINT Rules can be run on changing your library and just before any command is executed.

The process is to first write code procedures within a module or modules and then to assign the procedure to the appropriate gINT Rules procedure property of the table or the appropriate system event under gINT Rules System Events.

You can think of "modules" as separate files, which they would be if you were programming in most other programming environments. In gINT the code is stored in the current library. Modules store code procedures and declarations. We will discuss these concepts later in this document.

The code rules dialog box is invoked with the gINT Rules gINT Rules Code menu option (not available under gINT Logs). You will see a standard, gINT list dialog box:

You may have as many modules as desired. In the above example are modules with code procedures for checking project data input for different tables and one for library table input. This dialog box acts like all other list dialog boxes in gINT. You can edit the name and description fields, delete rows, print or export the list (.CSV or .XLS). This list works like all other grid dialog boxes in gINT, that is, nothing is saved until you click the OK button.

Page 15: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 14 —

The only exception is that if you add a new module name, write code, and then save in the Code window, the new record will be saved at that time. Otherwise, saving in the Code window does not save any changes in the List window. Only the OK button will do that.

The properties and methods of the code editor are discussed in detail in the following topic.

Since modules are stored in the library you can share modules between libraries using the UTILITIES Lib Merge/Copy application. You can move to the code window by clicking on the Code tab or double-clicking on the module name.

gINT Rules is Programming

This facility is for programmers. gINT Software does not provide free programming support. We are available for consulting services for writing, or assisting in the development of, custom programs.

Please contact us if you would like a quote on custom development. The only exception to

Page 16: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 15 —

this policy is if you find a bug in the way that gINT Rules behaves. Please report the problem and we will resolve it at no charge as quickly as possible.

We would also appreciate comments on this documentation. If you find sections unclear or would like to see documentation on items that were not covered, please let us know. Finally, we are always open to suggestions, comments, and desired enhancements to the facility.

Page 17: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 16 —

The Code Editor

Introduction

The gINT Rules Code editor provides many features for writing, editing, and debugging code. Features include:

• List of modules defined in the current library. • List of procedures defined in the current module. • Code coloring to easily identify statements, variables, reserved words, etc. • An object browser listing procedures available in external objects and Type

variables. • A visual dialog box editor. • Break points. • Single-step execution. • An immediate, or watch, window for examining values of variables.

To launch the code editor, in Input or DATA DESIGN Library Data, select the gINT Rules gINT Rules Code menu option. The gINT Rules dialog box is in two parts described below.

Dialog Box Size and Position

The dialog box is sizable. To resize, just hover the mouse over an edge until it changes to a double headed arrow, left-click and drag. To move, left-click in the dialog box caption bar (top line with the gINT icon at the left) and drag to any position. When the dialog box is closed its size and position are stored in your SETUP.GSH file. The next time the dialog box is shown it will be displayed at the same size and position.

When the dialog box is up, it is always on top of the current gINT application. You can still click in the gINT screen and perform actions, for example, change data or click on the Save button. When you leave an application that supports the gINT Rules dialog box, the dialog box is automatically closed.

The dialog box may also be minimized. The minimized title bar will initially appear at the lower left corner of the gINT window. It may be dragged to any location to avoid hiding data on the screen. If the dialog box is closed while it is minimized, the next time it is shown it will appear at the location and size it had before it was minimized.

Page 18: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 17 —

The List Window

The List tab shows all modules defined in the current library. The sample below has no modules defined. You supply the name and an optional description for each module. The module names must be unique, that is, no two modules can have the same name. The program automatically updates the Date field whenever the name or description or the underlying code module is changed.

The List Window Buttons

Button Description

OK Saves any pending changes in the Name and Description fields, new records, and deleted records.

Cancel Aborts any pending changes in the Name and Description fields, new records, and deleted records. This is the same as clicking on the form “Close” button (white “X” on red background) at the upper right of the form.

Help Brings up gINT Help.

Print Prints the contents of the grid.

Page 19: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 18 —

Button Description

Export Exports the contents of the grid to either a comma separated values ASCII file (CSV) or an Excel® file.

Procedures Brings up a dialog with the list of all procedures in the module with focus in the grid. For example:

Procedures in module GR005 COMMON PROCEDURES:

DeleteRows

DeleteRowsThatJustHaveDepth

HoleDepthFnD

InitFieldsFnB

InitSampleDataFnL

RecordsetClose

Lock The "Lock" button at the lower left of the gINT Rules List dialog allows you to lock out users from editing gINT Rules Code and procedure assignments in tables. Clicking the button launches a file open dialog. Pick any file that is local to your computer (NOT a network file). You can also create a file by browsing to the desired folder and typing a new file name. This file name is then encrypted and stored in the current library. On opening the library, if the specified file is not found:

The gINT Rules Code, Add-Ins Manager, and System Events menu items disappear from under the gINT Rules main menu in all applications.

The gINT Rules procedure assignment properties under the gINT Rules tab of the table properties dialog are visible but disabled, that is, users can see the assignments but cannot alter them. This applies to all table properties dialogs in both the data entry and design applications.

This facility works exactly like the File:Secure Library menu item in the Utilities:Lib Merge/Copy application. If you lock the library, you can use the same file name used for library locking for gINT Rules locking. Locking the library is not sufficient to lock all gINT Rules editing (the table properties are still editable) so you may wish to lock both.

The Code Window

The Code tab shows the code for the module currently highlighted in the List tab window:

Page 20: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 19 —

The above shows a new module with no code. CTRL+TAB switches between the List and Code windows.

Menus and Toolbar

For documentation on the editor, in the code window please see the Help Editor Help and then click on the IDE link. Note that Help describes a "File" menu which does not exist in gINT Rules. The gINT Rules modules are stored in the gINT library not as separate disk files. The Help menu is for the gINT Rules interface only. The normal gINT Help is brought up with the Help button at the lower right.

Some notes on special handling of some of these menu choices by gINT:

• Edit Tab as Spaces

• View Font

• View Tab Width

gINT stores these values in your SETUP.GSH file and they are therefore specific to you, not the library. These are your personal preferences. By default Tabs as Spaces is True, the Font is 11 point Courier New, and the Tab Width is set to 2 characters.

Page 21: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 20 —

The Code Window Command Buttons

Button Description

Print Print the current module.

Write To File

Write the current module to a disk file.

Save Save the changes in the current module.

Done Close the gINT Rules dialog box. This is the same as clicking on the form “Close” button (white “X” on red background) at the upper right of the form.

Help Brings up gINT Help, as opposed to the Editor and Language Help from the menu.

Running Code in the Code Window

When running gINT Rules in the code window (F5 or clicking on the Start/Resume button in the toolbar), the program needs to know which procedure name to pass to your code. It uses the following logic while looking in the properties of the grid that has focus:

• If there are no data in the current grid, it passes the procedure name in the table properties for gINT Rules on Empty Dataset. If that property has not been specified no procedure name is passed.

• If there are data in the current grid, if there is a property supplied for "Pre-process on Save", that procedure name is passed. Otherwise, if there is a "Procedure on Save", that procedure name is passed. If neither exists, no procedure name is passed.

• If one of the above situations results in no procedure name being passed, or if you wish to set your own procedure name, do the following:

Put a breakpoint on the line that calls the procedure. Usually:

CallByName Me, gINTRules.ProcedureName, vbMethod

You make the line a breakpoint by either putting focus in the line and pressing F9 or clicking in the gray area left of the line.

• Run the code by press the F5 key or clicking the Start/Resume button (right facing triangle in the toolbar).

• Execution will halt on the breakpoint. Click in "ProcedureName" in that line and press SHIFT+F9 or click the Evaluate Expression button in the toolbar. This will open the Immediate Window at the top of the form and print either:

gINTRules.ProcedureName -> "No code procedure name specified for table 'XXXXXXX'."

Page 22: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 21 —

(where 'XXXXXXX' is the table with focus.)

or

gINTRules.ProcedureName -> "XXXXXXX"

(where "XXXXXXX" is the procedure name passed by the program).

• Remove the "->" and all text right of this and supply the procedure name you wish to use following an equal sign. For example:

gINTRules.ProcedureName = "MyProcedure"

and press ENTER.

• Continue execution by press F5 or clicking the Start/Resume button.

This supplied procedure name will remain in effect as long as focus remains in the code editor dialog box.

Page 23: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 22 —

The gINT Rules Code Language

Introduction

gINT Rules uses a derivative of Visual Basic for Applications® (VBA®). If you have worked in another VBA environment, such as macros in Excel, you have a big head start on working with gINT Rules. Detailed description of the language can be found under the Help menu in the Code Editor window. This section presents a general overview.

Architecture

Computer programs are composed of procedures which are grouped in modules. Procedures are where all of the executable code is located (see Procedures topic for details). Modules are separate files and are themselves composed of a Declarations section at the top followed by as many procedure sections as desired:

Option Explicit

Public Declare Function MyFunction Lib "MYDLL.DLL" (pdXyz As Double, _

piAbc As Integer) _

As Double

'Commonly used field names

Public Const gs_HoleDepth As String = "HoleDepth"

Public Const gs_PointID As String = "PointID"

Public gsDataA() As String

'Dialog buttons

Private Const mi_Ok_Button As Integer = -1

Private Const mi_Cancel_Button As Integer = 0

Public Sub Main

End Sub

Public Function MyFunctionFnS(…) _

As String

End Function

etc.

Option Explicit is a special declaration that forces explicit declaration of all variables in the

Page 24: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 23 —

module. This is inserted by default by the gINT Rules editor on creation of a new module and we strongly recommend keeping this option.

The other parts of the above sample declare an external DLL procedure and different variables. These "Private" variables are only available to the current module. Variables can also be declared "Public" in the declarations section and would therefore be available to all procedures in all modules that are running at the same time as this module. See the Scope of Objects topic for further details.

The Sub Main procedure is special. If there is a Sub Main, it is executed automatically when your code is run. Sub Main is the entry point for a module.

Procedures

There are two main types of procedures: Functions and Subroutines. The former returns a value to the caller via the procedure itself and the later does not. All procedures can have parameters passed to them and can modify those passed parameters (called "arguments"). Both types can return modified arguments.

Each subroutine is composed as follows:

Sub Name(arguments)

Code Statements

End Sub

Each function is composed as follows:

Function Name(arguments) _

As Type

Code Statements

End Function

Functions and subroutines do not have to have arguments. In that case, there would still be parentheses after the Name but they would enclose nothing. Following is a simple subroutine that adds the values of two arguments and returns the sum in a third argument:

Sub AddIt(ByVal pdData1 As Double, _

ByVal pdData2 As Double, _

ByRef pdSum As Double)

pdSum = pdData1 + pdData2

End Sub

The calling procedure would use the above subroutine as follows:

Call AddIt(dFirstData, dSecondData, dDataSum)

If dDataSum > …

Page 25: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 24 —

You could also use the following syntax:

AddIt dFirstData, dSecondData, dDataSum

If dDataSum > …

That is, you can leave off the "Call " if you also remove the parentheses around the arguments.

Alternatively we can write the above subroutine as a function which returns the sum directly:

Function AddItFnD(ByVal pdData1 As Double, _

ByVal pdData2 As Double) _

As Double

AddItFnD = pdData1 + pdData2

End Sub

The calling procedure would use the above function as follows:

If AddItFnD(dFirstData, dSecondData) > …

(See the Naming Conventions and Programming Style topic for discussion of the variable naming and code layout). Procedures are exited either through the End Sub or End Function, or you can exit at any location within the procedure with an Exit Sub or Exit Function.

Arguments can be passed by reference (ByRef) and by value (ByVal). If passed ByRef, and if the variable value is changed, it will also be changed in the calling procedure. If passed ByVal, and if the variable is changed, it will not be changed in the calling procedure. The default is ByRef.

Sub AddIt(ByVal pdData1 As Double, _

ByVal pdData2 As Double, _

ByRef pdSum As Double)

In the above, we want to pass back the sum, therefore, pdSum must be ByRef. The other variables are not to be changed by the procedure so they are passed ByVal. One way to look at this is that when passed ByRef, the procedure receiving the argument is working on the same variable that the calling procedure has. With ByVal, the compiler first makes a copy of the variable and the procedure is working with the copy, not the original. Some arguments will be ByVal, regardless of how they are declared. For example:

Page 26: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 25 —

Sub MyProc1(…)

Call MyProc2(dData1 + 5)

End Sub

Sub MyProc2(ByRef pdValue As Double)

Even though pdValue is declared ByRef, since the calling procedure passes a calculation instead of a variable, pdValue is ByVal since a modified result cannot be passed back to a calculation, only to a variable.

Arguments can be optional. They are declared as follows:

Sub MyProcedure(ByVal pdData As Double, _

…, _

Optional ByVal pbMyVariable As Boolean = True, _

Optional ByVal psMyVariable As String = "abc")

Optional parameters must be last and you can have as many as you like. The default values (True and "abc" above) are not required but are strongly recommended. They only take effect if the calling procedure leaves off the argument in the calling statement.

If left off, and the arguments are not passed by the caller, the argument values will default to the un-initialized values of the declared type. In the above example, that would be True and "abc", respectively. You can also have a parameter array declaration which allows you to pass a variable number of arguments:

Sub MyProcedure(ParamArray pvValuesV() As Variant)

Dim iInd As Integer

Dim iValue as Integer

'--------------------

If Not IsMissing(pvValuesV)

For iInd = 0 To UBound(pvValuesV)

iValue = CInt(pvValuesV(iInd))

Next iInd

End If

Page 27: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 26 —

End Sub

By definition, parameter arrays are variants and are always optional. If used, a ParamArray must be the last argument in the list. Because it is optional, it is good practice to check that it exists. If nothing was passed in the ParamArray its LBound will be 0 and its UBound –1. So you could extract the arguments in a loop such as For iInd = LBound(ParamArray) to UBound(ParamArray). This would acquire no data and will not cause any error. Alternatively you could check for UBound < LBound.

The calling procedure may have as many arguments as desired:

Call MyProcedure(iData1, iData2, iData3, …)

There are many functions and subroutines built into the language. Below is a listing of a small number of them:

Abs: Returns the absolute value.

Atn, Cos, Sin, Tan: ArcTanget, Cosine, Sine, and Tangent of angles.

LCase, UCase: Returns the lower/upper case of a text string.

Open, Close, Kill: Various procedures used for manipulating disk files.

See Language Help under the Help menu in the Code window for a full list and descriptions of each.

Property Gets, Lets, and Sets are special forms of functions and subroutines and behave like variables. See Language Help for details.

Language Components

Operators

Operators perform some basic calculation or other calculation. gINT Rules supports the following operators:

Operator Description Example

= Assigns the result of some operations at the left of the = to a variable at the left.

dResult = dData1 + dData2

= Checks that the items on the left of the = are the same as those on the right. Returns True or False.

If dResult = dData1 + dData2 Then…

> Checks that the items on the left of the > are greater than those on the right. Returns True or False.

If dResult > dData1 + dData2 Then…

Page 28: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 27 —

Operator Description Example

>= Checks that the items on the left of the >= are greater than or equal to those on the right. Returns True or False.

If dResult >= dData1 + dData2 Then…

< Checks that the items on the left of the < are less than those on the right. Returns True or False.

If dResult < dData1 + dData2 Then…

<= Checks that the items on the left of the <= are less than or equal to those on the right. Returns True or False.

If dResult <= dData1 + dData2 Then…

<> Checks that the items on the left of the <> are not the same as those on the right. Returns True or False.

If dResult <> dData1 + dData2 Then…

+, -, *, / Standard arithmetic operators: Add, Subtract, Multiply, and Divide.

dResult = (5 + 6 * 8 - 3) / 2

(equals 25)

- Negation. Reverses the sign of the numeric variable.

-dMyNumber + 5 - 32

^ Exponentiation. dResult = 2 ^ 3

(equals 8)

\ Integer Divide. iResult = 5 \ 2 (equals 2)

iResult = 10 \ 3 (equals 3)

Mod Returns the remainder of an integer division.

iResult = 5 Mod 2 (equals 1)

iResult = 10 Mod 2 (equals 0)

Like Returns True if a string contains a specified pattern. Special characters in pattern:

? = Match any single character.

* = Match zero or more characters.

# = Match any digit.

[charlist] = Match any character in the list.

[!charlist] = Match any character not in the list.

If "ABC" Like "*B*" Then…

Is Compares objects. Returns True if the two objects are the same.

If obj1 Is obj2 Then…

Page 29: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 28 —

Operator Description Example

& Concatenates two string variables. Note that "+" can also be used but is not recommended.

"ABC" & "DEF"

results in:

"ABCDEF"

And If the two conditions on either side of the And are True, then the result is True, otherwise False.

If (iA = iB) And (iC = iD) Then…

Or If the either conditions on either side of the Or are True, then the result is True, otherwise False.

If (iA = iB) Or (iC = iD) Then…

Not Negates a condition. If Not (iA = iB) Then…

Same as:

If iA <> iB Then…

And Used as a bit operator. 10 And 3 = 2

Or Used as a bit operator. 10 Or 3 = 11

Not Used as a bit operator. Not 10 = -11

Xor Bit operator. Exclusive Or. 10 Xor 3 = 9

Eqv Bit operator. Compares corresponding bits in two numeric values and returns 1 in that position in the result if the two bits are the same, 0 otherwise.

10 Eqv 3 = -10

Same as:

Not (10 Xor 3)

Imp Bit operator. Implication. 10 Imp 3 = -9

Same as:

(Not 10) Or 3

Variables

A variable is a name for a value of some type. Variable names must start with a letter and may contain digits and some other non-alphanumeric characters, but not spaces. There are names that are reserved by the gINT Rules compiler that cannot be used as variables.

In the code editor this will be clear because reserved words are in blue while variable names are in black. Variables are declared to be able to store certain types of values. Following are the available list of types:

Page 30: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 29 —

Type Description

Boolean True or False (-1 or 0)

Byte Unsigned 8-bit (1 byte) value ranging from 0 to 255.

Currency 64-bit (8 byte) floating-point value for storing and accurately manipulating currency data.

Date 64-bit (8 byte) floating-point value storing date and/or time in decimal format. Can represent dates between 1 January 100 and 31 December 9999.

Double 64-bit (8 byte) floating-point value storing up to 15 significant places of precision with values ranging between -10308 and 10308.

Integer 16-bit (2 byte) signed integer ranging from -32,768 to 32,767.

Long 32-bit (4 byte) signed integer ranging from -109 to 109.

Object Reference to an object such as a control on a dialog box or an external object exposed by another program. gINTRules is an object.

PortInt Portable Integer. 16 or 32-bit signed integer value.

Single 32-bit (4 byte) floating-point value storing up to 15 significant places of precision with values ranging between -10308 and 10308.

String Text of any number of characters.

Variant Can hold any type of data. Whenever possible, it is recommended that this variable type not be used. It is not supported in some languages and it is always best to use the exact data type that is required.

It is important to declare variables in the appropriate type. For example, you could declare all your variables as variants. First your code will run slower but, more importantly, you will very likely generate bugs that are very difficult to track down because of improper data.

If a variable should be a number then declare it as the appropriate numeric type. The same applies to all variable types. Variables can be declared in a number of ways. See the Scope of Objects topic for details.

Constants

Constants store data that do not change. They are used mainly to make the code more understandable and maintainable. For example, in your calculations you need the conversion between feet and meters, instead of writing:

Page 31: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 30 —

dResult = 0.3048 * dLength

you could have a constant declaration and use it in the calculation:

Const d_Feet_to_Meters As Double = 0.3048

dResult = d_Feet_to_Meters * dLength

The above may not seem like an advantage since we appear to be just substituting a number to remember with a constant name. The advantage for the above example is readability of the code. If you didn't know that 0.3048 is the factor to convert from feet to meters you might be perplexed as to what the statement does. With the constant name there is no question of the statement function. Some constants might also change as you modify your code. If you used a hard coded number, you would have track down everywhere you used the number and change it. With a constant declaration, you would change it in just one place.

Note that the "…As Double…" is not required but is a good general practice. Also, the naming of the variables above is our own convention. See the Naming Conventions and Programming Style topic for details.

Array Variables

Array variables store a list of data. The name of the variable refers to the entire collection of data. Individual items in the list are referenced by their numeric position. Arrays can be of any dimension. Following are some examples:

Dim sDataV(2) As String

sDataV(0) = "ABC"

sDataV(1) = "MNO"

sDataV(2) = "XYZ"

Note that the array was Dim'd to 2 but there are three elements. When a lower bound is not specified, as is the case above, the lower bound is assumed to be 0. So Dim sDataV(2) is the same as Dim sDataV(0 to 2). If "Option Base 1" is used in the declarations section then the unspecified lower bound of array dimensions to 1. You can explicitly set the lower bound to any value as follows:

Dim sDataV(5 to 8) As String

Referring to an element not within the array bounds generates a "Subscript out of range" error. So with the above array Dim'd from 5 to 8, sDataV(2) would generate this error. Only elements 5 to 8 exist in this array. However, we very strongly recommend that you dimension all your arrays with a lower bound of 0. If you port your gINT Rules code to VB.NET, that environment only allows 0-based arrays.

Following is a two dimensional array:

Dim dDataA(0 to 3,0 to 2) As Double

Page 32: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 31 —

dDataA(0,0) = 8

dDataA(0,1) = 15

dDataA(0,2) = 87

dDataA(1,0) = 42

dDataA(1,1) = 5

dDataA(1,2) = 10

dDataA(2,0) = 8

dDataA(2,1) = 7

dDataA(2,2) = 2

dDataA(3,0) = 19

dDataA(3,1) = 15

dDataA(3,2) = 11

You can have an array with higher dimensions as well. If you dimension an array as in the above two examples, the array is fixed in size and cannot be re-dimensioned in code. If you need the array to change in size, you need a dynamic array:

Dim iNumElements As Integer

Dim sDataV() As String

iNumElements = 0

ReDim sDataV(0)

Do

iNumElements = iNumElements + 1

ReDim Preserve sDataV(iNumElements)

sDataV(iNumElements) = sDataCurrent

Loop While bSomeCondition

The first step is to dimension the array with no size in the initial Dim. Then ReDim to a base size. As you add elements you need to "ReDim Preserve" the array to the higher size. Without the "Preserve" reserved word the array will be cleared of existing data.

You can also ReDim to a smaller size as well. Note that the "As String" is not needed after the initial Dim statement. With multi-dimensional arrays, only the last dimension can be changed:

Dim iNumElements As Integer

Dim sDataV() As String

iNumElements = 0

Page 33: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 32 —

ReDim sDataV(1 to 2,0)

Do

iNumElements = iNumElements + 1

ReDim Preserve sDataV(1 to 2, iNumElements)

sDataV(1, iNumElements) = sDataCurrent1

sDataV(2, iNumElements) = sDataCurrent2

Loop While bSomeCondition

You can determine the array bounds with the LBound and UBound functions:

iLowerBound = LBound(sMyArrayV)

iUpperBound = UBound(sMyArrayV)

The above syntax only works for a one dimensional array. For a multi-dimensional array, you must specify the desired index:

iLowerBound = LBound(sMyArrayV, 2)

iUpperBound = UBound(sMyArrayV, 2)

The above statements return the lower and upper bounds of the second dimension of a two dimensional array.

User Defined Types

A common need in programming is to have collections of data lists that have mixed data types. You can define your own types as follows:

Private Type MyType

iData As Integer

sData As String

dData As Double

End Type

Type declarations can only appear in the declarations section of a module. Types can be declared Private (only for use in the current module) or Public (for use in all modules in the project).

You can then declare variables as being of this type:

Dim tMyData As MyType

tMyData.iData = 22

tMyData.sData = "ABC"

tMyData.dData = 3.1415

Page 34: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 33 —

or:

With tMyData

.iData = 22

.sData = "ABC"

.dData = 3.1415

End With

See the With…End With topic for details of this construct.

You can also have arrays composed of user-defined types:

Dim tMyDataV(1 to 5) As MyType

For iInd = 1 to 5

With tMyDataV(iInd)

.iData = …

.sData = "…"

.dData = …

End With

Next iInd

Object Variables

Object variables store references to objects. For example, gINTRules is an object and it has properties and methods (see THE gINTRules OBJECT topic for details). They are accessed like elements in a user-defined type:

With gINTRules

gsDataA = .GridData.DataArray

.GridData.DataArray = gsDataA

.Success = True

End With

The gINTRules object is created for you. You can create your own. Following is an example of creating a recordset of all the data in the parent record for the data being saved:

Dim dsParentData As Recordset

Dim sSql As String

With gINTRules

sSql = "Select * " & _

"From '" & .GridData.ParentRecord.Name & "'"

Page 35: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 34 —

Set dsParentData = .CurrentProject.OpenRecordset(sSql, dbOpenDynaset)

dsParentData.Close

Set dsParentData = Nothing

End With

Object variables must be assigned using the "Set" reserved word. There are many objects available for your use on your computer. For example, Excel, Word, and ACCESS all expose object models that can be manipulated by other programs. See the External Object References topic for details.

With…End With

The With…End With construct executes a series of statements on an object or user-defined type without repeating the variable name:

With MyObject

.Prop1 = "ABC"

.Prop2 = "MNO"

.Prop3 = "XYZ"

End with

is the same as:

MyObject.Prop1 = "ABC"

MyObject.Prop2 = "MNO"

MyObject.Prop3 = "XYZ"

Line Continuations

For readability, it is best to break long lines with a line continuation. This is a space and an underscore at the end of a line:

dResult = 5 * MyFunction1FnD(iData1, dData1) / _

MyFunction2FnD(sData1, nData1)

In long argument lists in procedure declarations and calls, this is particularly useful:

Public Function MyFunctionFnS(ByVal piData1 As Integer, _

ByVal pdData1 As Double, _

ByVal pdData2 As Double, _

ByRef psData1 As String) _

As Double

Page 36: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 35 —

Comments

Comments within your code are very important for readability and maintainability. They can explain what a particular line or section of code does, document who, what, why, and how of a procedure, document dates of code changes, why they were made and by whom.

Comments start with an apostrophe ('). Anything after that character is ignored. An exception would be an apostrophe within quotes. Then it is treated as a text character. Comments can be on their own line or at the end of line:

'This is a comment on its own line.

dResult = dData1 + dData2 'This is a comment at the end of a line

Unlike Visual Basic® and some other languages, comment lines cannot be continued with the line continuation. Each comment line must start with an apostrophe.

Scope of Objects

Variables and Constants

Variables have three levels of visibility to your procedures:

Local

These are only available to the current procedure. All variables declared in a procedure are local to that procedure. No other procedure can access those variables. Local variables are cleared on exit from the procedure unless they are declared Static:

Static xsData As String

Dim sData As String

The value of xsData will persist between calls to the procedure, sData will not.

Module

These are available to all procedures in the current module. These are declared in the declarations section of the module like the following:

Private Const mi_Ok_Button As Integer = -1

Private Const mi_Cancel_Button As Integer = 0

Private Const ms_HoleDepth As String = "HoleDepth"

Private Const ms_PointID As String = "PointID"

Private msDataA() As String

Public

These are available to all loaded modules, that is, the main module and all modules

Page 37: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 36 —

associated to it via '#LibInclude statements (see the USING MULTIPLE MODULES topic for details). These are declared in the declarations section of any of the modules like the following:

Public Const gi_Ok_Button As Integer = -1

Public Const gi_Cancel_Button As Integer = 0

Public Const gs_HoleDepth As String = "HoleDepth"

Public Const gs_PointID As String = "PointID"

Public gsDataA() As String

External DLL Procedures

External DLL procedures (see the Running External DLLs topic) are always declared in the declarations section of a module and are either private to the module and therefore, available to all procedures in the module or public and therefore available to all procedures in all loaded modules:

Private Declare Function MyFunction Lib "MYDLL.DLL" (pdXyz As Double, _

piAbc As Integer) _

As Double

Public Declare Function MyFunction Lib "MYDLL.DLL" (pdXyz As Double, _

piAbc As Integer) _

As Double

If the Private/Public reserved word is omitted, Public is assumed, however, we strongly recommend always using explicit declarations and not relying on defaults.

Procedures

By default, all procedures are public. You can make them private to a module with the Private reserved word:

Private Sub MyProcedure(…)

Sub MyProcedure(…)

Public Sub MyProcedure(…)

The first example makes MyProcedure private to the other procedures in its module. The second and third examples are exactly the same and make MyProcedure available to all procedures in all loaded modules. We strongly recommend declaring procedures explicitly as Public and not relying on the default.

Controlling Execution Flow

Code execute commences at the top each procedure and works its way down to the End

Page 38: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 37 —

Sub or End Function. You can change this progression using a number of structures.

Call

This moves the execution flow to the called procedure:

Call MyProcedure(…)

This can also be written:

MyProcedure …

That is, you can leave off the "Call " if you remove the parentheses around the arguments.

CallByName

This statement calls a procedure based on the name of the procedure. This is a very important statement in gINT Rules Code. The gINTRules object passes your Sub Main procedure the name of the procedure that you have associated with whatever event triggered the call to gINT Rules. This name is stored in the ProcedureName property. You could set up the following:

Select Case gINTRules.ProcedureName

Case "MyProcedure1"

Call MyProcedure1

Case "MyProcedure2"

Call MyProcedure2

End Select

This becomes a maintenance headache since you would have to change the above if you changed procedure names or added new procedures. Instead, you can just write:

CallByName Me, gINTRules.ProcedureName, vbMethod

Following is the syntax of the statement:

Result = CallByName(Object, ProcedureName, CallType[, Arguments()])

Page 39: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 38 —

Where:

Argument Description

Object The name of the object that you want to act upon. In the case of gINT Rules Code this is simply "Me", that is, the current module.

ProcedureName The name of the procedure to be invoked.

CallType Requires a constant representing the type of procedure:

method (subroutine or function) = vbMethod

property let = vbLet

property get = vbGet

property set = vbSet

Arguments This is optional. Here you pass any required arguments to the procedure. This is a variant array so you can pass as many arguments as necessary, each separated by a comma.

Result If the called procedure returns a result (a function) it would be placed into this parameter. If there is no return value then the statement can be written:

CallByName Object, ProcedureName, CallType[, Arguments()]

that is, leave off the "Result = " and remove the parentheses around the argument list. Alternatively, you could write:

Call CallByName(Object, ProcedureName, CallType[, Arguments()])

Note that for a procedure to be called using CallByName it must be Public, even if it resides in the same module as the procedure that issues the CallByName.

Do…Loop Do

Loop

Do loops can be exited with a "While" or "Until" condition on the Do line or the Loop line, or with an Exit Do within the loop:

Do While lPsCsr > 5

Loop

Do Until lPsCsr = 24

Loop

Page 40: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 39 —

Do

Loop While lPsCsr > 5

Do

Loop Until lPsCsr = 24

Do

If lPsCsr = 0 Then

Exit Do

End If

Loop

End

Ends the execution of the program:

If <some condition> Then

End

End If

Exit Sub/Exit Function

Exits from the procedure:

If <some condition> Then

Exit Sub

End If

If <some condition> Then

Exit Function

End If

For…Each

Loops through all elements in a collection object.

Dim bFoundIt As Boolean

Dim fldTemp As Field

Dim sMesg As String

'----------------------

Page 41: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 40 —

With gINTRules.GridData

bFoundIt = False

For Each fldTemp In .ParentRecord.Fields

If fldTemp.Name = "My Field" Then

bFoundIt = True

Exit For

End If

Next fldTemp

Set fldTemp = Nothing

sMesg = IIf(bFoundIt,"Found","Didn't Find") & " My Field"

MsgBox sMesg, vbOkOnly, "Looking for My Field"

End With

The object name is not required in the "Next fldTemp" but it doesn't hurt and it clearly labels this line as the end of which loop. This is very important when you have nested loops.

For…Next

Loops a specified number of times incrementing or decrementing a numeric variable on each loop:

For iInd = 1 to 5

Next iInd

iInd will equal 1 in the first loop, 2 in the second, etc. The default increment per loop is 1 but any value can be used:

For iInd = 1 to 5 Step 2

Next iInd

iInd will equal 1 in the first loop, 3 in the second, and 5 in the third and final loop. Loops can decrement the index value as well:

For iInd = 5 to 1 Step -1

Next iInd

iInd will equal 5 in the first loop, 4 in the second, and so on. It is not necessary to use the full "Next iInd", you could just use "Next" but we recommend the practice of repeating the index variable in the "Next" statement to make the end of the loop clear. This is especially important with nested loops.

Page 42: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 41 —

For Next blocks can be exited before the last loop is run:

For iInd = 1 to 5

If <some condition> Then

Exit For

End If

Next iInd

GoTo

This forces execution to a specified label:

If <some condition> Then

GoTo NextRecord

End If

NextRecord:

Labels are composed of the label name and trailing colon with nothing else on the line, except an optional comment after the colon. GoTo should only be used in rare instances. From readability and maintenance standpoints, GoTos are not ideal. Usually one of the other control structures will do the job better.

If...Else...End If If <condition> Then

<perform some action if condition is True>

End If

is the same as:

If <condition> Then <perform some action if condition is True>

Our preference is that single line If statements not be used, that is, we always use the End If.

If <condition> Then

<perform some action if condition is True>

Else

<perform some action if condition is False>

End If

If <condition1> Then

<perform some action if condition1 is True>

ElseIf <condition2> Then

<perform some action if condition2 is True>

Else

<perform some action neither condition1 or condition2 is True>

End If

Page 43: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 42 —

Select Case…End Select

Compares some value to test values and executes the appropriate statements based on the comparison:

Select Case dResult

Case Is < 4

Case 5, 8

Case 22

Case Is > 22

Case Else

End Select

Stop

This pauses execution. If execution is resumed, it resumes on the next statement. You would use this in debugging code.

If <some condition> Then

Stop

End If

Page 44: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 43 —

The gINTRules Object

Introduction

The gINTRules object is used to communicate between gINT and your code. This object is always available to code modules executed by the gINTRules system. Before execution of a module begins, a new gINTRules object is created. Following is a diagram of the model:

Page 45: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 44 —

To access, for example the TableName property, you would write something like the following in your code:

sCurrentTable = gINTRules.GridData.TableName

You do not have to actually type the full property name. If you type “gINTRules.” the list of its properties, methods, and child objects automatically appear:

Page 46: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 45 —

Typing “gr” brings you to the “GridData” object. Pressing the Tab key pastes “GridData” after the “.”. Then typing another “.” Results in:

Typing a “t” selects “TableName” and a final Tab press completes the property.

Like any object in VBA, you can also use the With…End With block with gINT Rules objects. For example:

gINTRules.GridData.ErrorCol = iPsRQD

gINTRules.GridData.ErrorRow = lRow

is the same as:

With gINTRules.GridData

.ErrorCol = iPsRQD

.ErrorRow = lRow

End With

The model’s objects, properties, and methods are described below.

Page 47: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 46 —

gINT Rules Properties

BatchMode

Description

Returns True if the code execution is in batch mode. This would occur when the user executes the gINT Rules Recalc current table command or is performing an import or is running the Utilties:Convert Projects application. You can use this flag to suppress messages and dialog boxes that you don't want to show during a batch process.

Arguments

None

Data Type

Boolean, Read Only

Sample Usage If gINTRules.BatchMode Then

… some code here …

End If

CancelChanges

Description

If set to True, restores the contents of the current grid back to its configuration on the last save. This is the same as executing the File:Cancel changes menu item. You may wish to do this is the user is not authorized to make modifications in the current table. However, this will only be executed if the gINTRules.Success property is set to False, that is, changes cannot be canceled unless the operation fails.

Arguments

None

Data Type

Boolean, Write only

Sample Usage If <some condition> Then

gINTRules.CancelChanges = True

End if

Page 48: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 47 —

CancelCommand

Description

Forces the current command to be canceled. Only used in code referenced by the gINT Rules System Event, "Before Command." See the CurrentApplication property for a means of dealing with commands that appear in multiple applications.

Arguments

None

Data Type

Boolean, Write only.

Page 49: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 48 —

Sample Usage Public Sub CheckCommandRights

Dim bNoRights As Boolean

'-----------------------

If <code to determine if user is an administrator> Then

'Has rights to all commands

Exit Sub

End If

bNoRights = False

Select Case gINTRules.CurrentCommand

Case gr_Cmd_DataImportText, _

gr_Cmd_DataImportExcel, gr_Cmd_DataImportDB, _

gr_Cmd_DataImportDBBatch, gr_Cmd_DataImportAGS

bNoRights = True

Case gr_Cmd_AppProperties

Select Case gINTRules.CurrentApplication

Case gr_App_Input_Tables, gr_App_DataDesign_ProjectDatabase

bNoRights = True

End Select

End Select

If bNoRights Then

MsgBox "You do not have rights to this command"

gINTRules.CancelCommand = True

End If

End Sub

CurrentApplication

Description

Some commands can be executed in multiple applications and you may wish to allow a particular command to execute in one application but not another. This property allows

Page 50: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 49 —

you to make that choice.

This property returns the current application when running code in the Before Command system event. It is only populated in that event. The value uses the same enumerated list of applications as the HideApplication method of the gINTRules.GintConfig object.

Arguments

None

Data Type

Long, Read only

Page 51: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 50 —

Sample Usage Public Sub CheckCommandRights

Dim bNoRights As Boolean

'-----------------------

If <code to determine if user is an administrator> Then

'Has rights to all commands

Exit Sub

End If

bNoRights = False

Select Case gINTRules.CurrentCommand

Case gr_Cmd_DataImportText, _

gr_Cmd_DataImportExcel, gr_Cmd_DataImportDB, _

gr_Cmd_DataImportDBBatch, gr_Cmd_DataImportAGS

bNoRights = True

Case gr_Cmd_AppProperties

Select Case gINTRules.CurrentApplication

Case gr_App_Input_Tables, gr_App_DataDesign_ProjectDatabase

bNoRights = True

End Select

End Select

If bNoRights Then

MsgBox "You do not have rights to this command"

gINTRules.CancelCommand = True

End If

End Sub

CurrentCommand

Description

This property returns the command identifier for the current command. This is only used in code referenced by the gINT Rules System Event, "Before Command."

Page 52: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 51 —

The currently exposed gINT command identifiers are can be found under the Help Contents menu and then under the “Commands” book, “Summary Table” topic:

The “gINT Rules Constants” column gives the requisite values.

Arguments

None

Data Type

Long, Read only.

Sample Usage Public Sub CheckCommandRights

Dim bNoRights As Boolean

'-----------------------

If <code to determine if user is an administrator> Then

'Has rights to all commands

Exit Sub

End If

bNoRights = False

Select Case gINTRules.CurrentCommand

Case gr_Cmd_DataImportText, _

gr_Cmd_DataImportExcel, gr_Cmd_DataImportDB, _

gr_Cmd_DataImportDBBatch, gr_Cmd_DataImportAGS

bNoRights = True

Case gr_Cmd_AppProperties

Select Case gINTRules.CurrentApplication

Page 53: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 52 —

Case gr_App_Input_Tables, gr_App_DataDesign_ProjectDatabase

bNoRights = True

End Select

End Select

If bNoRights Then

MsgBox "You do not have rights to this command"

gINTRules.CancelCommand = True

End If

End Sub

CurrentProject

Description

This property returns the database source of the current grid's data. DAO methods may be applied to this database object, such as opening and editing recordsets and executing SQL statements.

Arguments

None

Data Type

DAO Database object, Read only

Sample Usage Set dsSampleData = gINTRules.CurrentProject.OpenRecordset(sSql, dbOpenDynaset)

ErrorMessage

Description

The property sets or reads a message for gINT to display on completion of the gINT Rule execution. This message is shown whether Success is returned True or False.

Arguments

None

Data Type

String, Read/Write

Page 54: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 53 —

Sample Usage If dRQD > dRecovery Then

gINTRules.ErrorMessage = “RQD must be less than or equal to Recovery”

… Would probably also set the GridData ErrorCol and ErrorRow here …

Exit Sub

End If

FieldCaption

Description

Given the table and field name, this property returns the field caption property. If there is a caption for the field, it is returned. If not, the field name, with all underscores replaced by spaces, is returned. This matches the algorithm used by the program in the display of field captions in the Input and Library Data applications. This property is quite useful in displaying error messages to the user. You want to display the field caption that they see, not the underlying field name which they don't see on screen. If the table or field names do not exist, nothing is returned.

Arguments

• TableName As String

• FieldName As String

Data Type

String, Read only.

Sample Usage gINTRules.ErrorMessage = _

gINTRules.FieldCaption("ABC", "Field 1") & " must be greater than " & _

gINTRules.FieldCaption("ABC", "Field 2")

FolderPath

Description

The property returns one of the gINT system paths.

Arguments

The property requires one of the following enumerated values as a passed in argument:

• gINT_fpProgram: Program folder.

• gINT_fpProjects: Default projects folder.

Page 55: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 54 —

• gINT_fpDataTemplates: Default data templates folder.

• gINT_fpScripts: Default scripts folder.

• gINT_fpDrawings: Default drawings folder.

• gINT_fpTemp: Default temporary files folder.

Except for the program folder, these folder locations come from the values in the File:System Properties dialog.

Data Type

String, Read only.

Sample Usage sProjectsFolder = gINTRules.FolderPath(gINT_fpProjects)

PointInsideArea

Description

This property returns True or False as to whether a specified X,Y coordinate pair fall inside the area defined by the PointInsideAreaInit method. Therefore, PointInsideAreaInit must be run before using this property.

See the sample gINT Rules add-in project GRA006 on the Web site for a fully functional sample of the use of this property and the PointInsideAreaInit method.

Arguments

• XCoordinate As Double

• YCoordinate As Double

Data Type

Boolean, Read only.

Sample Usage If gINTRules.PointInsideArea(dX, dY) Then

'code to handle if the point falls inside the area.

Else

'code to handle if the point falls outside the area.

End If

Page 56: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 55 —

ProcedureName

Description

Name of the procedure to execute in the module. Provided by gINT if the current data object has a gINT Rules Code procedure specified. In the code module, Sub Main can call this procedure by name. This allows several locations in gINT to be served by the same code module. Specify the module name and the procedure name and gINT will provide execution of the appropriate code.

Arguments

None

Data Type String, Read/Write

Sample Usage Public Sub Main

With gINTRules.GridData

'Put the grid data into a working string data array.

gsDataA = .DataArray

glNumRows = UBound(gsDataA, 2)

CallByName Me, gINTRules.ProcedureName, vbMethod

'Put the modified data array back into the input grid.

.DataArray = gsDataA

'Success is True if there were no errors.

gINTRules.Success = CBool(.ErrorCol = 0)

End With

End Sub

Success

Description

Used to signal gINT that the execution completed with no errors and data in the DataArray can be written to the grid and saved to the database. All code procedures must set this True or data will not be saved.

Arguments

None

Page 57: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 56 —

Data Type Boolean, Read/Write

Sample Usage

The following example says that if the error column was set, then the procedure found a problem and was therefore not successful, otherwise, it was successful.

Public Sub Main

With gINTRules.GridData

'Put the grid data into a working string data array.

gsDataA = .DataArray

glNumRows = UBound(gsDataA, 2)

CallByName Me, gINTRules.ProcedureName, vbMethod

'Put the modified data array back into the input grid.

.DataArray = gsDataA

'Success is True if there were no errors.

gINTRules.Success = CBool(.ErrorCol = 0)

End With

End Sub

SurfaceZValueFromXY

Description

Given the name of a surface stored in the current project, and specified East and North coordinates, returns the interpolated Z value associated with the specified coordinates.

The property raises one of two errors if there is a problem:

• gr_Error_Surface_Unknown: The requested surface does not exist in the current project.

• gr_Error_Surface_XYOutside: The specified coordinates are outside the surface boundaries.

The call to the property must be preceded by an "On Error Resume Next" to trap any raised error.

Page 58: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 57 —

Arguments

• SurfaceName As String: Name of surface that will be searched. This surface must be existing in the Input:Surfaces application for the current project.

• EastCoorindate As Double: East value.

• NorthCoordinate As Double: North Value.

Data Type

Double, Read only.

Page 59: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 58 —

Sample Usage Dim dZ As Double

Dim sSurfaceName As String

'---------------

'Ask user for desired X and Y values.

Begin Dialog UserDialog 280,98 ' %GRID:10,7,1,1

TextBox 100,21,110,14,.txtX

Text 60,21,20,14,"X:",.lblX

Text 60,35,20,14,"Y:",.lblY

TextBox 100,35,110,14,.txtY

OKButton 80,70,90,21

End Dialog

Dim dlgXY As UserDialog

Dialog dlgXY

sSurfaceName = "BEDROCK SURFACE"

On Error Resume Next

dZ = gINTRules.SurfaceZValueFromXY(sSurfaceName, _

CDbl(dlgXY.txtX), _

CDbl(dlgXY.txtY))

Select Case Err.Number

Case 0

MsgBox "Z: " & CStr(dZ)

Case gr_Error_Surface_Unknown

MsgBox "Surface " & sSurfaceName & _

" does not exist in the project."

Case gr_Error_Surface_XYOutside

MsgBox "X = " & dlgXY.txtX & " Y = " & dlgXY.txtY & _

" outside of surface boundaries."

Case Else

'This should never happen.

‘If it does, please report to gINT technical support.

MsgBox "Unknown error " & CStr(Err.Number)

End Select

On Error GoTo 0

Page 60: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 59 —

TableCaption

Description

Given the table name, this property returns the table caption property. If there is a caption for the table, it is returned. If not, the table name, with all underscores replaced by spaces, is returned. This matches the algorithm used by the program in the display of table captions in the Input and Library Data applications. This property is quite useful in displaying error messages to the user. You want to display the field caption that they see, not the underlying field name which they don't see on screen. If the table name does not exist, nothing is returned.

Arguments

• TableName As String

Data Type

String, Read only.

Sample Usage gINTRules.ErrorMessage = _

"Field " & gINTRules.FieldCaption("ABC", "Field 1") & " in table " & _

gINTRules.TableCaption("ABC") & " must be greater than 0."

gINTRules Methods

AlignmentCoorFromStaOff

(Requires licensing for gINT 8.2 or later)

Description

This method calculates the north and east coordinates given the station and offset from a stored alignment.

An error can be raised. Therefore, the code must be set up something like the following:

On Error Resume Next

Call gINTRules. AlignmentCoorFromStaOff(...)

'Handle errors

Select Case Err.Number

Case ...

End Select

On Error GoTo 0

Page 61: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 60 —

The named errors that can return are:

• gr_Error_Alignment_NoTable: Alignment support is not in the current project.

• gr_Error_Alignment_NoSuchAlignment: The specified alignment does not exist.

• gr_Error_Alignment_NoCoordinates: The specified alignment does not have coordinate data.

• gr_Error_Alignment_OutsideAlignment: The specified station/offset is outside of the range of the specified alignment.

See gINT Rules sample GR019 for an example of how this method can be used.

Arguments

Pass in the alignment name, station, offset and the method returns the north and east coordinates.

• AlignmentName As String

• Station As Double

• Offset As Double: Positive left of the alignment (looking toward higher stations) and negative right of the alignment.

• North As Double

• East As Double

Sample Usage Call gINTRules.AlignmentCoorFromStaOff(“My Alignment”, _

1234.56, _

-5.82, _

dNorth, _

dEast)

AlignmentStaOffFromCoor

(Requires licensing for gINT 8.2 or later)

Description

This method calculates the station and offset given the north and and east and a stored alignment.

An error can be raised. Therefore, the code must be set up something like the following:

On Error Resume Next

Call gINTRules. AlignmentStaOffFromCoor(...)

Page 62: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 61 —

'Handle errors

Select Case Err.Number

Case ...

End Select

On Error GoTo 0

The named errors that can return are:

• gr_Error_Alignment_NoTable: Alignment support is not in the current project.

• gr_Error_Alignment_NoSuchAlignment: The specified alignment does not exist.

• gr_Error_Alignment_NoCoordinates: The specified alignment does not have coordinate data.

• gr_Error_Alignment_OutsideAlignment: The specified north/east is outside of the range of the specified alignment.

See gINT Rules sample GR019 for an example of how this method can be used.

Arguments

Pass in the alignment name, station, offset and the method returns the north and east coordinates.

• AlignmentName As String

• North As Double

• East As Double

• Station As Double

• Offset As Double: Positive left of the alignment (looking toward higher stations) and negative right of the alignment.

Sample Usage Call gINTRules. AlignmentStaOffFromCoor(“My Alignment”, _

1234567.89, _

9876543.21, _

dStation, _

dOffset)

Page 63: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 62 —

DisplayQueryResults

Description

This method displays the results of an SQL query to a grid dialog where the results can be printed or exported to a CSV or Excel file. The method can run a specified query against an open database or you can generate a recordset object and the method will display it. This method can only be called from a gINT Rules procedure that was called by an Add-Ins command menu item.

Arguments

All the arguments are optional but the method must have either a query or a database/recordset argument.

• Query As String (optional): A query expression or name of a stored library query (see File:Queries in Input). Not used, and can be left blank, if the DataBaseOrRecordset argument is a recordset.

• QueryName As String (optional): Name that will appears in the caption line of the grid dialog. If left blank:

ο If Query is the name of a library query, that name will be shown.

ο Otherwise, ">Unnamed<" will be shown.

• DataBaseOrRecordset As Database or Recordset (optional): If left blank, the current project database is used. Can specify another open database or a recordset. If the latter, the Query argument is not used.

Return Value

None

Sample Usage

• The following will generate an error. All the arguments are optional but you must have a query expression or a recordset. Call gINTRules.DisplayQueryResults()

• The following will first look for a library query by that name. If not found, it assumes that it is a query expression and will try to run it against the current project database. This would generate an error. Call gINTRules.DisplayQueryResults("XyXyXy")

• The following will run the library query (see File:Queries in Input) by the specified name against the current project. It will use the library query name in the caption of the displayed grid. Call gINTRules.DisplayQueryResults("TOTAL LAYER THICKNESS")

Page 64: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 63 —

• The following is exactly the same as the above: Call gINTRules.DisplayQueryResults("TOTAL LAYER THICKNESS", _

"TOTAL LAYER THICKNESS", _

gINTRules.CurrentProject)

This specifies the grid caption as "TOTAL LAYER THICKNESS" which would be the default with a named library query. It also specifies running the query against the current project, which is also the default.

• The following passes a query expression and the desired grid dialog caption to the method.

sQuery = "Parameters [Desired Graphic] Text; " & _

"Select Sum([GEOL_BASE] - [Depth]) As Thickness " & _

"From [GEOL] " & _

"Where [GEOL_LEG] = [Desired Graphic]"

Call gINTRules.DisplayQueryResults(sQuery, "My Test Query")

• The following runs the query in code and stores the results in a local recordset. That recordset is then passed to the method for display. Note that lack of the first argument which would have held a query expression.

sQuery = "Select Count([PointID]) As [Number of BH], " & _

"Sum([HoleDepth]) As [Total Length Drilling]" & _

"From [POINT]"

Set snTemp = _

gINTRules.CurrentProject.OpenRecordset(sQuery, _

dbOpenSnapshot)

Call gINTRules.DisplayQueryResults(, "Recordset Test", snTemp)

EndProgram

(Requires licensing for gINT 8.2 or later)

Description

This method ends your current gINT session. This can be used with users that are unauthorized to use gINT. Since it executes only when the currently executing gINT Rule is completed, remember to exit your procedure after issuing the call to this method.

Arguments

None

Page 65: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 64 —

Return Value

None

Sample Usage If <some condition> Then

Call gINTRules.EndProgram

Exit Sub

End If

ExecuteProgram

Description

This method is a version of the "Shell" function built into the code language. It launches a program and optionally passes a file name to that program. The advantage of this method over the “Shell” function is that it does not require the application name and location, you can just pass a file name and, if there is an associated application, this method will open that file in that application.

The method will throw one of the following named errors:

• gr_Error_ExePrgm_NoData: Both the FileName and Application arguments were not supplied.

• gr_Error_ExePrgm_NoExt: The Application argument was not supplied and the FileName parameter had no extension.

• gr_Error_ExePrgm_NoAssocApp: The Application argument was not supplied and no application could be found that was associated with the extension of the FileName parameter.

If another error was generated that is not in the list it will be a Windows error and will be returned as-is.

To trap these errors, surround the method in an On Error ... block. For example:

On Error Resume Next

gINTRules.ExecuteProgram ...

If Err.Number Then

...You can now take different actions depending on the error that was returned.

End if

On Error GoTo 0

Page 66: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 65 —

Arguments

• FileName As String: File name with full path.

• Application As String: Full path and file name of the program to be executed. If this is not supplied, a search is made of the application associated with the extension of the FileName argument

• WindowStyle As Integer: One of the following constants (if a value is not supplied, the default is vbMinimizedFocus):

ο vbHide: Window is hidden and focus is passed to the hidden window.

ο vbNormalFocus: Window has focus and is restored to its original size and position.

ο vbMinimizedFocus: Window is displayed as an icon with focus.

ο vbMaximizedFocus: Window is maximized with focus.

ο vbNormalNoFocus: Window is restored to its most recent size and position. The currently active window remains active.

ο vbMinimizedNoFocus: Window is displayed as an icon. The currently active window remains active.

All the arguments are optional, but at least the FileName or Application must be supplied. If both are missing, an error is raised.

Return Value

None

Sample Usage

Note that the following show all the arguments in quotes. This is required for literal values. Most likely string variables will be passed. These are not to be quoted, nor can the quotes be embedded in the values for the variables.

gINTRules.ExecuteProgram _

"c:\temp\myfile.pdf", _

"C:\Program Files\Adobe\Acrobat 6.0\Acrobat\Acrobat.exe"

This would open "c:\temp\myfile.pdf" with Adobe Acrobat version 6. Alternatively, the following would do the same thing:

gINTRules.ExecuteProgram "c:\temp\myfile.pdf"

If no program file name is supplied, the program queries the operating system for the application associated with the file extension (PDF, in this case).

gINTRules.ExecuteProgram _

"C:\Program Files\Adobe\Acrobat 6.0\Acrobat\Acrobat.exe"

Page 67: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 66 —

This would just launch Adobe Acrobat. No file would be viewed.

FileDialogFnB

Description

Allows creation of file open and save dialogs.

Arguments

• DialogTitle As String: Title show in the caption line of the dialog form.

• Filter As String: The "files of type" list in the format: Label of 1st type|extensions separated by semi-colons|Label of 2nd type|extensions...

Examples:

Excel format|*.xls

This would show "Excel format" in the "Files of Type" list at the bottom of the dialog and would shown only files with the extension of "DXF".

ASCII formats|*.csv;*.txt|All Files|*.*

This was show "ASCII formats" and "All Files" in the "Files of Type" list at the bottom of the dialog. When "ASCII formats" are selected, the dialog will show all files with the extension CSV and TXT. When "All Files" is selected, all files will be shown regardless of their extensions.

• DftExtension As String: Default extension. Give only the characters, not the asterisk or period. For example "dxf" not "*.dxf" or ".dxf".

• InitFolder As String: Initial folder to show. If not supplied and the FileSpec argument has a full path, that path will become the initial folder.

• FileSpec As String: Name of file with or without full path to show on the dialog opening.

• Flags As FileFlags: Standard Windows common dialog file flags. These can be added together, for example, cdlOFNOverwritePrompt + cdlOFNHideReadOnly. Typing a space while in this argument in writing the function will cause the list of choices to appear.

ο cdlOFNAllowMultiselect: Specifies that the File Name list box allows multiple selections.The user can select more than one file at run time by pressing the SHIFT key and using the UP ARROW and DOWN ARROW keys to select the desired files. When this is done, the FileName property returns a string containing the names of all selected files. The names in the string are delimited

Page 68: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 67 —

by spaces.

ο cdlOFNCreatePrompt: Specifies that the dialog box prompts the user to create a file that doesn't currently exist. This flag automatically sets the cdlOFNPathMustExist and cdlOFNFileMustExist flags.

ο cdlOFNExtensionDifferent: Indicates that the extension of the returned filename is different from the extension specified by the DefaultExt property. This flag isn't set if the DefaultExt property is Null, if the extensions match, or if the file has no extension. This flag value can be checked upon closing the dialog box.

ο cdlOFNFileMustExist: Specifies that the user can enter only names of existing files in the File Name text box. If this flag is set and the user enters an invalid filename, a warning is displayed. This flag automatically sets the cdlOFNPathMustExist flag.

ο cdlOFNHideReadOnly: Hides the Read Only check box.

ο cdlOFNNoChangeDir: Forces the dialog box to set the current directory to what it was when the dialog box was opened.

ο cdlOFNNoReadOnlyReturn: Specifies that the returned file won't have the Read Only attribute set and won't be in a write-protected directory.

ο cdlOFNNoValidate: Specifies that the common dialog box allows invalid characters in the returned filename.

ο cdlOFNOverwritePrompt: Causes the Save As dialog box to generate a message box if the selected file already exists. The user must confirm whether to overwrite the file.

ο cdlOFNPathMustExist: Specifies that the user can enter only valid paths. If this flag is set and the user enters an invalid path, a warning message is displayed.

ο cdlOFNReadOnly: Causes the Read Only check box to be initially checked when the dialog box is created. This flag also indicates the state of the Read Only check box when the dialog box is closed.

ο cdlOFNShareAware: Specifies that sharing violation errors will be ignored.

ο cdlOFNHelpButton: Causes the dialog box to display the Help button.

• Action As FileAction: gINT_faShowOpen (to open a file or files) or gINT_faShowSave (to save a file).

• FilesSelectedList As String: For file open dialogs, this returns the selected file or files. If there are multiple files returned, they each have the full file path and are separated by a carriage return/line feed combination (vbCrLf).

Page 69: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 68 —

Return Value

True if the file dialog was canceled or failed for any reason.

Sample Usage If gINTRules.FileDialogFnB( _

"Import CPT files", _

"ACME Files|*.cpt|AAAAA Drilling Files|*.cpd", _

"cpt", _

"g:\data\cpts", _

"", _

cdlOFNFileMustExist + cdlOFNAllowMultiselect, _

gINT_faShowOpen, _

sFiles) _

Then

'User canceled the dialog or there was some error.

Exit Sub

Else

'Perform import operations on the file or files

‘returned in the sFiles variable.

End If

FolderDialogFnB

(Requires licensing for gINT 8.2 or later)

Description

This method exposes the internal gINT folder browser. This is used throughout gINT when the program requires the selection of a folder (e.g., File:System Properties, Data templates, Projects, Scripts, etc.).

Arguments

• DialogTitle As String: Title that appears at the top of the dialog.

• InitFolder As String: The initial folder that shall be displayed on opening the dialog.

• Filter As String: See the FileDialogFnB method documentation.

• Flags As FileFlags: See the FileDialogFnB method documentation.

• FolderSelected As String: The folder that the user selected.

Page 70: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 69 —

Return Value

Returns True if the file dialog was canceled or failed for any reason. Failure can occur with incorrect or invalid arguments.

Sample Usage If gINTRules.FolderDialogFnB("Test", _

"c:\temp", _

"gINT Projects|*.gpj", _

cdlOFNCreatePrompt, _

sFolder) _

Then

MsgBox "User canceled the dialog or there was an error."

Else

MsgBox "Folder choosen = " & sFolder

End If

LibraryTableDataGetFnB

Description

Obtains data from a library table.

Arguments

• TableName As String: Library table to access.

• Key As String: Record Key to access.

• FieldName As String: Field from which to extract data.

• StringValue As String: Returned string version of requested field data.

• NumericValue As Double (optional): Returned Numeric value of requested field data.

Return Value

Returns True if failed to obtain data for any reason, that is, table not found, field not found, record not found. Note that an empty field will return a success flag (False).

Page 71: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 70 —

Sample Usage If gINTRules.LibraryTableDataGetFnB("MY LIB TABLE", _

“ABC”, _

"Data Field", _

sDataValue, _

dDataValue) _

Then

‘Code to execute if function fails.

End if

The above would return the contents of the field called “Data Field”, in both string and numeric formats, from the library table called “MY LIB TABLE” where the record key is equal to “ABC”.

By default the gINTRules.LibraryTableDataGetFnB method assumes that the second argument is the value of the library table key field for the record which you wish to extract data from a specified field other than the key field. If you need to search on another field in the library table, or need to query on more complex criteria than just the key field equal some value, you can write a full filter expression. This must be in the format of a "Where" clause in an SQL expression.

For example, let's say you have a library table called CONVERTSYMBOLS that maps between your gINT material symbol names and those in files that you import and export to. You write a gINT Rule to convert imported symbols to their equivalent gINT names and another rule that converts your gINT symbol names to another set of names before you export. The table could be made up as follows:

gINT Name Other Name

CL CLAY

GM GARVELST

MH SILTHP

SC SANDCL

The "gINT Name" is the key field in this table.

Page 72: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 71 —

In the procedure that converts from the gINT Name to the Other Name, the function call is straight forward:

If gINTRules.LibraryTableDataGetFnB("CONVERTSYMBOLS", _

sSymbolName, _

"Other Name", _

sNewName) _

Then

...

End if

The above will lookup the "Other Name" value where the "gINT Name" is equal to the contents of the "sSymbolName" variable.

In the procedure that converts the Other Name to the gINT Name, you just can't pass the name of the symbol to the procedure. The name in this case will be the other name. If you did so the function would try to find a gINT Name equal to the current Other Name. That will only work if the gINT and Other names are the same. In this situation you want to look up the gINT Name where the Other Name is equal to the current symbol name:

If gINTRules.LibraryTableDataGetFnB( _

"CONVERTSYMBOLS", _

"[Other Name] = '" & sSymbolName & "'", _

"Other Name", _

sNewName) _

Then

...

End if

You can create as complex a condition as you wish. The only requirement is that an equal sign (=) must appear somewhere in the argument.

LookupListGetDataFnB

Description

This method returns the value(s) and description(s) of a gINT Lookup List.

Arguments

The Lookup Name argument is the input to the method. The Lookup Value Array and Lookup Description Array arguments are for the result output.

• Lookup Name, String: The name of a lookup list.

• Lookup Values, String Array (output): Array of Values in the lookup list.

Page 73: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 72 —

• Lookup Descriptions, String Array (output): Array of Descriptions for the values in the list.

Return Value

The method returns True if it successfully retrieves the Lookup List values, otherwise it returns False.

Sample Usage

The following will return two string arrays containing the Values and Descriptions for Lookup List "LLTableName".

Dim bResult as Boolean

Dim sLookupValueV() As String

Dim sLookupDescriptionV() As String

'----------------------

ReDim sLookupValueV(0)

ReDim sLookupDescriptionV(0)

bResult = gINTRules.LookupListGetDataFnB("LLTableName", _

sLookupValueV, _

sLookupDescriptionV)

PickListFnS

Description

This method checks brings up a user-defined list of items that can be selected by the gINT Rule user and the selection list returned to the calling procedure.

Page 74: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 73 —

Arguments

• ListSeparator As String: Separator used to delimit the list items. For example, if the list is: B-1,B-4,B-22, the separator is a comma (","). If a blank separator is passed in, the method terminates with a return value of blank.

• DataList As String: The list of data items to display. If no items are passed in, the method terminates with a return value of blank.

• FormCaption As String: The caption for the pick list form.

• FieldCaption As String: The caption for the data column.

• MultiSelect As Boolean: True to allow the end-user to select more than one item, False for single selection only.

• Canceled As Boolean: Returned by the method as True if the end-user clicked the Cancel button, False otherwise.

Return Value

The list of items selected. If more than one, the list is passed back using the ListSeparator to delimit the returned values.

Page 75: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 74 —

Sample Usage

(See also the GRA003 gINT Rules Add-In project on www.gintsoftware.com/support_gintrules.html.)

Show the list of all boreholes in the project for the end-user to select one or more boreholes for later manipulation

Const s_ListSeparator As String = ","

Dim bCanceled As Boolean

Dim sPointIDCaption As String

Dim sPointIDList As String

Dim sSql As String

Dim snPointIDs As Recordset

'--------------------------

sSql = "Select PointID " & _

"From POINT " & _

"Order By PointID"

Set snPointIDs = _

gINTRules.CurrentProject.OpenRecordset(sSql, dbOpenSnapshot)

sPointIDList = ""

Do Until snPointIDs.EOF

sPointIDList = sPointIDList & s_ListSeparator & snPointIDs(0)

snPointIDs.MoveNext

Loop

RecordsetClose snPointIDs

sPointIDList = Mid$(sPointIDList, Len(s_ListSeparator) + 1)

If Len(sPointIDList) = 0 Then

gINTRules.ErrorMessage = "There are no boreholes in this project."

Exit Sub

End If

gINTRules.ProjectTableFieldExistsFnB "POINT", "PointID", sPointIDCaption

sPointIDList = gINTRules.PickListFnS(s_ListSeparator, _

sPointIDList, _

Page 76: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 75 —

"Boreholes to scan", _

sPointIDCaption, _

True, _

bCanceled)

If bCanceled Then

Exit Sub

End If

Change the "True" argument to "False" to only allow a single item selection instead of multiple.

PointInsideAreaInit

Description

This method initializes an area that will then be used by the PointInsideArea property to determine if a specified X,Y point is inside the area. Areas are defined by a two dimensional array that must be dimensioned (0 to 1, 0 to # vertices - 1) or (1, # vertices - 1) (0 is the default lower bound). The 0th position of the first dimension holds the X value of the vertex, the 2nd holds the Y value. The second dimension holds the vertex number. The area must have at least 4 vertices, and must close (1st and last vertex coordinates must be the same).

The property raises one of seven errors if there is a problem:

• gr_Error_AreaArray_Min4Vertices: Must have at least 4 vertices.

• gr_Error_AreaArray_NotDimmed: The array is not dimensioned.

• gr_Error_AreaArray_LBound1NE0: The lower bound of the first dimension is not 0.

• gr_Error_AreaArray_UBound1NE1: The upper bound of the first dimension is not 1.

• gr_Error_AreaArray_LBound2NE0: The lower bound of the second dimension is not 0.

• gr_Error_AreaArray_NotClosed: The area does not close (1st and last coordinates not equal).

• gr_Error_AreaArray_RegionCreateFailed: Could not create region. Could have duplicated vertices. If not, this should not happen. Please forward arrays that generate this error to gINT Software.

The call to the property must be preceded by an "On Error Resume Next" to trap any raised error.

Page 77: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 76 —

Arguments

AreaArray() as Double: The X,Y pairs that define each vertex of the area.

Return Value

None

Sample Usage

See the sample gINT Rules add-in project GRA006 on the Web site for a fully functional sample of the use of this method and the PointInsideArea property.

The call to the method needs to be preceeded with "On Error Resume Next" as shown below. The procedure "throws" an error if there was a problem.

Dim dArea1A(0 To 1, 0 To 4) As Double

dArea1A(0,0) = 4.3

dArea1A(1,0) = 7.2

dArea1A(0,1) = 4.9

dArea1A(1,1) = 8.1

dArea1A(0,2) = 6.7

dArea1A(1,2) = 7.5

dArea1A(0,3) = 5.5

dArea1A(1,3) = 6.9

dArea1A(0,4) = 4.3

dArea1A(1,4) = 7.2

On Error Resume Next

gINTRules.PointInsideAreaInit dAreaA()

Select Case Err.Number

Case gr_Error_AreaArray_Min4Vertices

sMsg = "Area array must have at least 4 vertices."

Case gr_Error_AreaArray_NotDimmed, _

gr_Error_AreaArray_LBound1NE0, _

gr_Error_AreaArray_UBound1NE1, _

gr_Error_AreaArray_LBound2NE0

sMsg = "Area array must be dimmed as (0 to 1, 0 to # vertices - 1)"

Case gr_Error_AreaArray_NotClosed

sMsg = "Area array must close, that is, first and last point must have the same coordinates."

Case gr_Error_AreaArray_RegionCreateFailed

sMsg = "Could not create region. " & _

"May have duplicated internal vertices."

Page 78: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 77 —

Case Else

sMsg = Err.Description

End Select

On Error GoTo 0

If Len(sMsg) > 0 Then

Error message of some kind

Exit Sub

End If

ProjectTableDataGetFnB

Description

Obtains data from the current project table.

Arguments

• FieldName As String: Field in the PROJECT table from which data is to be retrieved.

• StringValue As String: Returned string version of requested field data.

• NumericValue As Double (optional): Returned Numeric value of requested field data.

Return Value

Returns True if the function failed to obtain data for any reason, that is, table not found, field not found, record not found. Note that an empty field will return a success flag (False).

Sample Usage If gINTRules.ProjectTableDataGetFnB(“My Field Name”, _

sFieldStringValue, _

dFieldNumericValue) _

Then

‘Function failed.

‘Give some message and perform the appropriate actions.

End if

ProjectTableFieldExistsFnB

Description

This method checks if a table or field exists in the current project and, optionally, returns the caption for the specified table or field. If there is no caption, it returns the name of the

Page 79: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 78 —

table or field.

Arguments

• TableName As String: Name of the table in the project to be queried.

• FieldName As String (Optional): If not supplied, the existence of the specified table will be checked, otherwise the existence of the specified field in the specified table will be checked.

• Caption As String (Optional): If only the table is supplied, returns the caption for that table. If the field is provided, the caption for the field is returned. If there is no caption, the name is returned.

Return Value

True if the table or field exists in the current project, False otherwise.

Sample Usage

• Check for table existence and return table caption: sTable = "MY TABLE"

If Not gINTRules.ProjectTableFieldExistsFnB(sTable, , sCaption) Then

gINTRules.ErrorMessage = "Table " & sTable & " does not exist."

Exit Sub

End if

If the table did exist, its caption (or name if there was no caption) would be returned in the sCaption variable.

• Check for field existence and return field caption: sTable = "MY TABLE"

sField = "My Field"

If Not gINTRules.ProjectTableFieldExistsFnB(sTable, sField, sCaption) Then

gINTRules.ErrorMessage = "Field " & sField & " in table " & _

sTable & " does not exist."

Exit Sub

End if

If the field did exist, its caption (or name if there was no caption) would be returned in the sCaption variable.

• Check for table existence only: sTable = "MY TABLE"

If Not gINTRules.ProjectTableFieldExistsFnB(sTable) Then

...

Page 80: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 79 —

• Check for field existence only: sTable = "MY TABLE"

sField = "My Field"

If Not gINTRules.ProjectTableFieldExistsFnB(sTable, sField) Then

...

RunScript

Description

This method runs gINT scripts. Only one script can be invoked from a gINT Rules code execution and it is executed after the code terminates, regardless of where it is run within the procedure. This property can only be set from within gINT Rules code that was invoked from a command in the Add-Ins menu or in a gINT Rules Procedure on Library Open. At the end of the script execution, the program deletes the temporary script file that it creates.

See the “Script to gINT Rules Code” command in gINT Help for a method of generating a base script in code. See the How-to Guide topic under "General" called "Batch output through Add-In scripts" for a sample of the usage of this command.

Arguments

• Script As String: Full script specification or the name of a script with its full path.

• DeleteScript as Boolean: True to delete the script file when the script is completed, False not to delete the script file.

Return Value

None

Page 81: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 80 —

Sample Usage

See the sample project GRA001 for an example of the use of this facility.

The following will preview any number of boreholes from any selected project to a user selected log form.

Const s_Parm_Form As String = "<<Log Form Name>>"

Const s_Parm_PointIDs As String = "<<Requested Boreholes>>"

Const s_Parm_Project As String = "<<Project Path and Name>>"

Const s_Script_Base As String = "**Operation" & vbCrLf & _

"Output" & vbCrLf & _

"**Command" & vbCrLf & _

"PREVIEW" & vbCrLf & _

"**Properties" & vbCrLf & _

"Type=Log" & vbCrLf & _

"Name=" & s_Parm_Form & vbCrLf & _

"**Spec" & vbCrLf & _

"Project=" & s_Parm_Project & vbCrLf & _

"Range=" & s_Parm_PointIDs

Dim sForm As String

Dim sPointIDs As String

Dim sProject As String

Dim sScript As String

'----------------------

'Code to query the operator for the form, project,

‘and list of points to preview.

'This would assign values to the variables sForm, sProject,

‘and sPointIDs.

...

...

sScript = s_Script_Base

sScript = Replace(sScript, s_Parm_Form, sForm)

sScript = Replace(sScript, s_Parm_Project, sProject)

sScript = Replace(sScript, s_Parm_PointIDs, sPointIDs)

Call gINTRules.RunScript(sScript, True)

Page 82: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 81 —

The Replace functions would return a script looking something like the following:

**Operation

Output

**Command

PREVIEW

**Properties

Type=Log

Name=MY LOG FORM

**Spec

Project=c:\program files\gint\projects\my project.gpj

Range=B-1,MW-1

UUID

Description

This method returns a "Universally Unique IDentifier." This is used to generate a unique string. Following is a sample:

641f7921-q92c-22e5-b617-554433884321

Each time the property is called, the UUID will change.

Search the Internet for details of this widely used facility.

Arguments

None

Return Value

A UUID as a string.

Sample Usage sUUID = gINTRules.UUID

gINTRules.GintConfig Properties

ClientID, CompanyAddress, CompanyEMail, CompanyFax, CompanyLocation, CompanyName, CompanyPhone

Description

These properties return the data from the Help:Company Information dialog.

Arguments

None

Page 83: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 82 —

Data Type

String, Read only.

Sample Usage With gINTRules.GintConfig

sCompanyInfo = "Client ID: " & .ClientID & vbCrLf & _

"Name: " & .CompanyName & vbCrLf & _

"Address: " & .CompanyAddress & vbCrLf & _

"Location: " & .CompanyLocation & vbCrLf & _

"Phone: " & .CompanyPhone & vbCrLf & _

"Fax: " & .CompanyFax & vbCrLf & _

"E-Mail: " & .CompanyEMail

End With

LibraryFile

Description

This property returns the full path and file name of the current library.

Arguments

None

Data Type

String, Read only.

Sample Usage sLibName = gINTRules.GintConfig.LibraryFile

UserName

Description

Returns the name of the user currently logged onto the network. This is useful for writing security code.

Arguments

None

Data Type

String, Read only

Page 84: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 83 —

Sample Usage

See GR009.

sUserName = gINTRules.GintConfig.UserName

gINTRules.GintConfig Methods

HideAppGroup

Description

This hides the specified gINT application group. This can only be called in a procedure that is called from the gINT Rules system event "On Library Open." This allows you to hide application groups based on the logged in user (see the gINTRules.GintConfig.UserName property). Specific applications can be hidden using the HideApplication method.

Arguments

GroupName As Integer: This argument can only be from the following list:

• gr_AppGroup_Input

• gr_AppGroup_Output

• gr_AppGroup_DataDesign

• gr_AppGroup_ReportDesign

• gr_AppGroup_SymbolDesign

• gr_AppGroup_Drawings

• gr_AppGroup_Utilities

Return Value

None

Sample Usage gINTRules.GintConfig.HideAppGroup gr_AppGroup_ReportDesign

HideApplication

Description

This hides the specified gINT application. This can only be called in a procedure that is called from the gINT Rules system event "On Library Open." This allows you to hide applications based on the logged in user (see the gINTRules.GintConfig.UserName property). Entire application groups can be hidden using the HideAppGroup method.

Page 85: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 84 —

Arguments

Application As Integer: This argument can only be from the following list:

• gr_App_DataDesign_CorrespondenceFiles

• gr_App_DataDesign_LibraryData

• gr_App_DataDesign_LibraryTables

• gr_App_DataDesign_LookupLists

• gr_App_DataDesign_ProjectDatabase

• gr_App_DataDesign_ReadingsLists

• gr_App_DataDesign_UserSystemData

• gr_App_DrawingBlock_DrawingLibrary

• gr_App_DrawingBlock_GeneralDrawings

• gr_App_Drawings_DrawingLibrary

• gr_App_Drawings_GeneralDrawings

• gr_App_Input_Tables Used only on determining the application in procedures run under the Before Command event. If you wish to hide Input, use the appropriate const with the HideAppGroup method.

• gr_App_Input_SiteMap

• gr_App_Input_Surfaces

• gr_App_ReportBlock_Fence

• gr_App_ReportBlock_Graph

• gr_App_ReportBlock_Histogram

• gr_App_ReportBlock_GraphicTable

• gr_App_ReportBlock_GraphicTextDoc

• gr_App_ReportBlock_Log

• gr_App_ReportBlock_SiteMap

• gr_App_ReportDesign_Fence

• gr_App_ReportDesign_Graph

• gr_App_ReportDesign_GraphicTable

• gr_App_ReportDesign_GraphicTextDoc

• gr_App_ReportDesign_Histogram

Page 86: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 85 —

• gr_App_ReportDesign_Log

• gr_App_ReportDesign_SiteMap

• gr_App_ReportDesign_TextDoc

• gr_App_ReportDesign_TextTable

• gr_App_SymbolDesign_BitmapFill

• gr_App_SymbolDesign_BitmapSymbol

• gr_App_SymbolDesign_Color

• gr_App_SymbolDesign_DataMarker

• gr_App_SymbolDesign_DiscreteGraphic

• gr_App_SymbolDesign_FixedCurve

• gr_App_SymbolDesign_General

• gr_App_SymbolDesign_Hatch

• gr_App_SymbolDesign_Material

• gr_App_SymbolDesign_Sampler

• gr_App_SymbolDesign_Tile

• gr_App_SymbolDesign_Well

• gr_App_Utilities_ConvertProjects

• gr_App_Utilities_ExtractZIP

• gr_App_Utilities_MergeCopy

• gr_App_Utilities_PrintObjectLists

• gr_App_Utilities_RepairCompact

Return Value

None

Sample Usage

See GRA007.

gINTRules.GintConfig.HideApplication gr_App_Utilities_MergeCopy

Page 87: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 86 —

gINTRules.GoogleEarth Object

(Requires licensing for gINT 8.2 or later)

The gINTRules.GoogleEarth object is used to display your gINT project data in Google EarthTM. This can be done with no programming using the Additional Modules:Google EarthTM menu. However, this facility can only extract its requisite data from fields in one table. Further, expressions and other logic cannot be used. All specifications must either be hard coded in the specification dialog or be taken from fields in the database. The gINTRules.GoogleEarth object exposes the properties and methods needed so that you can send information to Google Earth using your own criteria.

The process used by the GoogleEarth object is to store the information needed by Google Earth to display your data in a KML (Keyhole Markup Language) file and then optionally launching Google Earth with that file. There are methods in the object to add your data. These data can be PointID information, depth-related data, photos, rock outcrops, etc.

The general process is as follows:

• Call the initialize method to start the process. This establishes the name of the KML file that will be created and the name of the Google Earth folder that will be associated with the first set of point data.

• Call one of the AddPointXxxx methods to add point data.

• Call the Execute method to complete the process.

Optionally, the AddFolder method can be called before adding a group of point data to place that group in its own folder.

See the gINT Rules sample project GRA008 for an example of how this object can be used.

Note that the properties and methods exposed with this object do not cover the full range of what can be done programmatically with Google Earth. It just encapsulates what we feel are the most commonly needed facilities. You can access all the capabilities exposed by Google Earth via their KML file format using your own code. The KML documentation and Developer's Guide can be found at:

http://code.google.com/apis/kml/documentation/

gINTRules.GoogleEarth Properties

ProgramExists

(Requires licensing for gINT 8.2 or later)

Page 88: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 87 —

Description

This property returns True if the Google Earth program is installed on the current computer, False otherwise.

Arguments

None

Data Type

Boolean, Read only.

Sample Usage If Not gINTRules.GoogleEarth.ProgramExists Then

MsgBox "Google Earth is not installed."

Exit Sub

End If

gINTRules.GoogleEarth Methods

AddFolder

(Requires licensing for gINT 8.2 or later)

Description

This method allows adding additional folders in the Google interface for better organization of your displayed objects. For example, your main folder (defined in the Initialize method) could be your project name and you could have subfolders for boreholes, outcrop mappings, and photos. You would first define the folder into which a set of objects would be stored and then use the AddPointxxxx method (described below) to add those objects to your file.

If the parent folder argument is not provided, the new folder will be at the same level in the folder heirarchy as the main folder defined in the Initialize method.

Arguments

NewFolderName As String

ParentFolderName As String (optional)

Sample Usage On Error Resume Next

Call gINTRules.GoogleEarth.AddFolder("Boreholes", sMainFolderName)

If Err.Number <> 0 Then

GoTo ExitHere

Page 89: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 88 —

End If

On Error Goto 0

AddPointXxxx Methods

(Requires licensing for gINT 8.2 or later)

Description

These pass all the information needed to display a point in Google Earth. There are three procedures that can be used to add points for plotting into the KML file. The only difference between them is the format of the latitude and longitude.

• AddPointSingleFieldDecimalCoor: Passes coordinates as decimal degrees.

• AddPointSingleFieldTextCoor: Passes coordiantes as text in the form ##°##'##.##".

• AddPointComponentCoor: Passes coordinates in three arguments each for latitude and longitude - degrees, minutes, and seconds.

If there is an error, these methods put up a message box and throw an error. The error number is generic (-1) so there is nothing to be gained in examining the error number. The information about the error will be contained in the message.

Arguments

With all three methods only the coordinate data are required. They all share the following, optional arguments:

• Elevation As Double: If not supplied, 0 is assumed. This argument is meaningless unless the elevation option in the Initialize method is gr_GE_ElevationRelative or gr_GE_ElevationAbsolute. Values must be in meters. Google Earth will perform the conversion to feet if the option for units is feet.

• Label As String: This is placed next to the PointID icon and would probably be the PointID, but it can be whatever you wish. If not supplied, a label will not be shown.

• LabelColor As Long: This is a Windows' color number as described below. If blank, the Google Earth default label color is used.

• Description As String: This appears in the box that Google Earth brings up when the PointID icon is click on. This can be composed of mulitple paragraphs. Google Earth supports HTML codes in this property. For example, to show an image file, you could just embed:

http://www.gintsoftware.com/downloads/gra008/p1.jpg

Page 90: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 89 —

This will appear a link in the description. Clicking on the link in Google Earth would launch a browser window containing the image. You could also write the above as:

<img src="http://www.gintsoftware.com/downloads/gra008/p1.jpg"/>

This will insert the image directly into the Google Earth popup window.

• Icon As String: The icon can be specified with a URL (Uniform Resource Locator) which is a path to a file on the Internet (e.g, http://maps.google.com/mapfiles/kml/paddle/red-circle.png) or a file on your computer system (e.g., g:\my pictures\google icons\test pit.jpg). The icon file types supported by Google Earth are:

*.jpg *.bmp *.tif *.tga *.png *.jpeg *.tiff *.ppm *.pgm

You can obtain the URLs for all the Google Earth standard icons in the Google Earth program by selecting the Add:Placemark menu item. In the dialog click on the icon button right of the "Name" field. A dialog will appear with the standard icons. Click on any icon and its URL will appear near the top of the dialog. This can be copied and then pasted into the Icon URL property in gINT. You are not restricted to URLs on the Google site. Any publicly accessible location on the Internet can be used.

If no icon is provided, the Google Earth default icon (a push pin) is used.

• IconColor As Long: This is a Windows' color number as described below. If blank, the native color of the image file is used.

Where colors are required, Windows' colors are needed. You can obtain these numbers from the Symbol Design:Colors application or you can use the color constants built into the compiler:

vbBlack (0) vbRed (255) vbGreen (65280) vbYellow (65535) vbBlue (16711680) vbMagenta (16711935) vbCyan (16776960) vbWhite (16777215)

Sample Usage

See the documentation below for the three methods.

AddPointComponentCoor

(Requires licensing for gINT 8.2 or later)

Page 91: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 90 —

Description

This method adds point data with latitude and longitude in three fields each passing degrees, minutes, and seconds. These are the only required arguments.

Arguments

• LatitudeDegrees As Integer

• LatitudeMinutes As Integer

• LatitudeSeconds As Double

• LongitudeDegrees As Integer

• LongitudeMinutes As Integer

• LongitudeSeconds As Double

See the AddPointXxxx Methods topic above for the remaining, optional arguments.

Sample Usage Call gINTRules.GoogleEarth.AddPointComponentCoor( _

iLatDeg, iLatMin, dLatSec, _

iLongDeg, iLongMin, dLongSec, , _

sPointID, lLabelColor, sDesc, _

sIcon, lIconColor)

AddPointSingleFieldDecimalCoor

(Requires licensing for gINT 8.2 or later)

Description

This method adds point data with latitude and longitude in decimal degrees. These are the only required arguments.

Arguments

• Latitude As Double

• Longitude As Double

See the AddPointXxxx Methods topic above for the remaining, optional arguments.

Sample Usage Call gINTRules.GoogleEarth.AddPointSingleFieldDecimalCoor( _

dLatitude, dLongitude, , _

sPointID, lLabelColor, sDesc, _

sIcon, lIconColor)

Page 92: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 91 —

AddPointSingleFieldTextCoor

(Requires licensing for gINT 8.2 or later)

Description

This method adds point data with latitude and longitude in degrees, minutes, seconds format. For example:

38°26'50.84"

These are the only required arguments.

Arguments

• Latitude As String

• Longitude As String

See the AddPointXxxx Methods topic above for the remaining, optional arguments.

Sample Usage Call gINTRules.GoogleEarth.AddPointSingleFieldDecimalCoor( _

sLatitude, sLongitude, , _

sPointID, lLabelColor, sDesc, _

sIcon, lIconColor)

AddScreenOverlay

(Requires licensing for gINT 8.2 or later)

Description

This method adds a graphic to a specific screen location in Google Earth, for example, your company logo.

Arguments

• Name As String: Required. Appears in the "Places" section of Google Earth to identify this object.

• Description As String: Required but can be empty. Appears in the description bubble when the name is clicked in "Places".

• ImageFile As String: Name of the file to place on screen. The file types supported are JPG BMP TIF TGA PNG JPEG TIFF PPM PGM.

• ImageHandlePointX As Double: Required. X value of a point on the image which will be placed at the ScreenX position.

• ImageHandlePointXUnits As grGoogleEarthImageUnits: Required.

Page 93: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 92 —

gr_GE_ImageUnits_Fraction (0 to 1) or gr_GE_ImageUnits_Pixels.

• ImageHandlePointY As Double: Required. Y value of a point on the image which will be placed at the ScreenY position.

• ImageHandlePointYUnits As grGoogleEarthImageUnits: Required. gr_GE_ImageUnits_Fraction (0 to 1) or gr_GE_ImageUnits_Pixels.

• ScreenX As Double: Required. Horizontal position on screen where the ImageHandlePointX will be placed.

• ScreenXUnits As grGoogleEarthImageUnits: Required. gr_GE_ImageUnits_Fraction (0 to 1) or gr_GE_ImageUnits_Pixels.

• ScreenY As Double: Required. Vertical position on screen where the ImageHandlePointY will be placed.

• ScreenYUnits As grGoogleEarthImageUnits: Required. gr_GE_ImageUnits_Fraction (0 to 1) or gr_GE_ImageUnits_Pixels.

Sample Usage Call gINTRules.GoogleEarth.AddScreenOverlay( _

"gINT Logo", _

"www.gintsoftware.com", _

"g:\images\gint_logo.gif", _

1, _

gr_GE_ImageUnits_Fraction, _

0, _

gr_GE_ImageUnits_Fraction, _

0.8, _

gr_GE_ImageUnits_Fraction, _

20, _

gr_GE_ImageUnits_Pixels)

The above would place the lower right corner of the image at a point 80% of the screen width and 20 pixels above the bottom of the screen.

Execute

(Requires licensing for gINT 8.2 or later)

Description

This completes the KML file creation process. It closes and KML file which stores all the information needed to display the data in Google Earth. By default, Google Earth is launched to view the contents of the file. Optionally, you can specify that only the file

Page 94: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 93 —

creation will occur and Google Earth shall not be launched.

When this method launches Google Earth, gINT will continue to run. It launches Google Earth as a separate process.

If there is an error, this method puts up a message box and throws an error. The error number is generic (-1) so there is nothing to be gained in examining the error number. The information about the error will be contained in the message.

Arguments

• LaunchGoogleEarth As Boolean: This argument is optional. It can be True or missing to launch Google Earth to display the file. Pass this argument as False to just create the KML file without launching Google Earth.

Sample Usage Call gINTRules.GoogleEarth.Execute

Initialize

(Requires licensing for gINT 8.2 or later)

Description

This initializes the process by passing in the file name that will be used to store the PointID information and the name of the Google Earth folder under which each PointID will reside in the program. This folder can be found in the "Places" pane of the Google Earth interface. Optionally you can pass the method to be used by Google Earth to render the elevation of each PointID.

If there is an error, this method puts up a message box and throws an error. The error number is generic (-1) so there is nothing to be gained in examining the error number. The information about the error will be contained in the message.

This method must be called before any other procedures in the GoogleEarth object are called, except for the ProgramExists property which can (and should) be called before the Initialize method.

Arguments

• KMLFileName As String: Name of file to create.

• GoogleFolderName As String: Name of first Google Earth folder to create.

• ElevationOption As grGoogleEarthElevationOptions: Method to be used by Google Earth to render the elevation of each displayed object. This is an optional argument with the following values:

ο gr_GE_ElevationClampToGround: Place all PointIDs on the surface.

ο gr_GE_ElevationRelative: The PointID elevations are relative to the earth's

Page 95: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 94 —

surface so an elevation of "5" would be 5 units (units defined in Google Earth) above the ground surface.

ο gr_GE_ElevationAbsolute: The PointID elevation is an absolute elevation.

The default is gr_GE_ElevationClampToGround.

Sample Usage On Error Resume Next

Call gINTRules.GoogleEarth.Initialize(sFileName, sFolderName)

If Err.Number <> 0 Then

Exit Sub

End If

gINTRules.GridData Properties

CellColor

(Requires licensing for gINT 8.2 or later)

Description

This write-only property sets the color of a cell, row, column, or all cells. You can obtain color numbers from the Symbol Design:Colors application. Alternatively, you can use the RGB function (see the Help menu in the Code Window, not gINT Help) or the following, built-in, color constants:

• vbBlack - same as RGB(0,0,0) = 0 • vbRed - same as RGB(255,0,0) = 255 • vbGreen - same as RGB(0,255,0) = 65280 • vbYellow - same as RGB(255,255,0) = 65535 • vbBlue - same as RGB(0,0,255) = 16711680 • vbMagenta - same as RGB(255,0,255) = 16711935 • vbCyan - same as RGB(0,255,255) = 16776960 • vbWhite - same as RGB(255,255,255) = 16777215

To avoid confusion, stay away from shades of yellow (gINT required fields) and gray (gINT read-only columns). Also avoid shades of blue since gINT uses this color for highlighting the cell with focus.

This property can be called as many times as desired within a procedure. Processing of these properties occurs after the rule is completed.

If a cell is colored by setting the column and row and it is part of a row that is set to another color and it is part of a column that is set to another color, cell color wins over row color

Page 96: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 95 —

which wins over column color. All colors win over the native gINT cell coloring (required and read-only fields).

See gINT Rules application GR018 for an example of the usage of this property.

Arguments

• ColumnNumber As Long

• RowNumber As Long

To color a row, set the column argument to -1 (= all columns). To color a column, set the row argument to -1 (= all rows). To color all the cells, set both the column and row arguments to -1.

Sample Usage 'Colors the Benzene cell in row number lRow

gINTRules.GridData.CellColor(iPsBenzene, lRow) = 255

'Colors all cells in row number lRow

gINTRules.GridData.CellColor(-1, lRow) = 255

'Colors all cells in the Benzene column

gINTRules.GridData.CellColor(iPsBenzene, -1) = 255

'Colors all cells in the grid

gINTRules.GridData.CellColor(-1, -1) = 255

CurrentRow

Description

This property returns the row number (1-based) that had focus before the gINT Rules procedure was run. This is useful when writing an Add-In procedure that requires the data from the selected to perform some task.

Arguments

None

Data Type

Long, Read only.

Sample Usage lCurrentRow = gINTRules.GridData.CurrentRow

Page 97: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 96 —

DataArray

Description

Returns or accepts a dynamic string array containing a copy of all data contained in or to be written to the source grid. The array is two-dimensional and in Row major major order (Column, Row). Columns are dimmed 0 to the number of grid columns minus 1. Rows are dimmed 1 to the number data rows.

All tables that are children of the POINT table (most tables in your database) contain fields that gINT provides that are not shown. These contain the "foreign" keys. For example, the standard SV READINGS table that comes with the gINT Lab Testing tables, has a PointID,Depth,Reading keyset.

In the grid you will see the Reading field (usually captioned as "Sieve Size"). The PointID and Depth data associated with the current test are also hidden in the grid. These are the foreign keys, that is, the key fields that define the record in the parent table (SIEVE in this case).

These hidden keys are passed in the DataArray property and you have access to them but we strongly recommend ignoring them. If you need to know the foreign keys, use the ForeignKeyValues property of the GridData object. DO NOT ALTER THE VALUES OF THE HIDDEN FIELDS. Read them but don't write back to them. Data corruption could occur.

Arguments

None

Data Type 2-D array, String, Read/Write

Sample Usage

The entire array can be copied to a variable in your code as:

sMyDataArrayA = gINTRules.GridData.DataArray

You can then read and manipulate the data in the array.

sDataVariable = sMyDataArrayA(Col, Row)

… some manipulation of sDataVariable …

sMyDataArrayA(Col, Row) = sDataVariable

The size of the array can be changed. DO NOT change the number of columns (first dimension), only the number of rows. Rows can be added or removed. To clear the array use:

ReDim sMyDataArrayA(0 To UBound(sMyDataArrayA,1), 1 To lNumRows)

Always dimension the number of columns as above, that is:

Page 98: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 97 —

0 To UBound(sMyDataArrayA,1)

this will ensure that it matches the grid column dimension. To change the number of rows without clearing existing data, use:

ReDim Preserve sMyDataArrayA(0 To UBound(sMyDataArrayA,1), 1 To lNumRows)

Write the new values back to gINT with:

gINTRules.GridData.DataArray = sMyDataArrayA

Individual data values can be read with:

sStringVariable = gINTRules.GridData.DataArray(Col, Row)

However, values can NOT be written back to the array with

gINTRules.GridData.DataArray(Col, Row) = sStringVariable

Instead, use:

gINTRules.GridData.DataValue(Col, Row) = sStringVariable

For manipulation of individual data values without copying the entire array, use the DataValue property, as above, which is read-write.

DataValue

Description

Read or write a value directly from or to the data array.

Data Type

String, Read/Write

Sample Usage With gINTRules.GridData

sValueOne = .DataValue(.FieldCol("FieldOne"), lRow)

End With

With gINTRules.GridData

.DataValue(.FieldCol("FieldOne"), lRow) = sValueOne

End With

DeletedRecordData

This property no longer functions. It returned the value of a field in a deleted record for use in procedures that were called from the “gINT Rules Procedure on Deletion” event. Originally the “gINT Rules Procedure on Deletion” event was only called from the parent grids of split screens and only one record could be deleted at a time. The “gINT Rules Procedure on Deletion” event has since been expanded to be called from any row deletion. See the documentation for the “gINT Rules Procedure on Deletion” for the proper method of

Page 99: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 98 —

determining field values of deleted records.

This property was left in the gINTRules object to maintain compatibility with previous versions. If you attempt to use this property, a message box will appear referring you to this documentation.

ErrorCol

Description

After execution gINT interprets this value as the Error Column. Set it to the array column that represents the field that caused the error. When control returns to gINT, gINT will put focus in the cell represented by ErrorRow and ErrorCol. If the error occurs in the parent record, use the ParentTableErrorField property (see below).

Arguments

None

Data Type

Long, Read/Write

Sample Usage gINTRules.GridData.ErrorCol = lCol

ErrorRow

Description

After execution if Success has not been set True gINT interprets this value as the Error Row. Set it to the array row that represents the record where the error occurred. A value of -1 tells gINT to use the current record in the Parent grid, in a Parent/Child view. Setting the ParentTableErrorField to a valid field name has the effect of setting this property to -1. When control returns to gINT, gINT will put focus in the cell represented by ErrorRow and ErrorCol.

Arguments

None

Data Type

Long, Read/Write

Sample Usage gINTRules.GridData.ErrorRow = lRow

Page 100: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 99 —

FieldCol

Description

This property returns the column number in the grid data array for a specified field name. The return value is 0 if the field name is not found.

Arguments

FieldName As String: Name of the field to locate.

Data Type

Long, Read only

Sample Usage lColFieldOne = gINTRules.GridData.FieldCol("FieldOne")

FieldName

Description

Returns the name of the field at the Column specified.

Arguments

FieldColumnPosition As Long: Column position of the desired field in the data record.

Data Type

String, Read only

Sample Usage sFieldName = gINTRules.GridData.FieldName(lCol)

FirstVisibleFieldPs

Description

This returns the field column position in the grid data array of the first field that is visible in the current grid. For example, in a PointID,Depth table such as a SAMPLE table, there are actually two fields that are not shown, GintRecID (an internally used gINT field) and PointID. Therefore the FirstVisibleFieldPs property will return 3 in this case.

Arguments

None

Data Type

Integer, Read only

Page 101: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 100 —

Sample Usage

See the sample Add-In GRA005 on the gINT Software Web site for a sample usage for this property.

iColFirstVisible = gINTRules.GridData. FirstVisibleFieldPs

ForceSave

Description

If set True by your code, instructs gINT to write every row in the data array back to the database. Normally only rows that are changed (before and after the code module has executed) are saved. The property is also readable so your code can test whether it has already been set true.

Arguments

None

Data Type

Boolean, Read/Write

Sample Usage gINTRules.GridData.ForceSave = True

ForeignKeyValues

Description

Parameter: KeyFieldName or KeyFieldNumber (variant; optional) of the desired key.

If a field name is provided, returns the value.

If an Integer or Long Integer constant or variable is provided, the value at that position is returned.

If no parameter is passed a comma delimited list if all values is returned. If the supplied parameter is not a valid number or string, returns empty.

This property should be used instead of .ParentRecord or .ParentGridData for key field values.

Arguments

None

Data Type

String, Read only

Page 102: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 101 —

Sample Usage sAllKeys = gINTRules.GridData.ForeignKeyValues()

sPointID = gINTRules.GridData.ForeignKeyValues("PointID")

sPointID = gINTRules.GridData.ForeignKeyValues(1)

IsManualEntryMode

Description

If you have written gINT Rules save code that is only triggered if a field value has changed (see GR010), be warned that no field will appear to change during an import. The way import is handled is that first all the data are imported and then the save code is run. The same applies when running the Recalc Current Table command. Therefore, you may wish to run this block of code if a field has changed value or the current data entry mode is not manual entry. To that end, use this property. This returns True if in manual entry mode, False otherwise (import and recalc).

Arguments

None

Data Type

Boolean, Read only

Sample Usage If Not gINTRules.GridData.IsManualEntryMode Then

ParentGridData

Description

Parameter: FieldName (string) of the desired field for which the value is required. You can extract any data field from the parent. This property always has data from the grid. If there is no parent grid it returns empty. The following returns the same result:

sMyData = gINTRules.GridData.ParentRecord.Fields("MyField").Value

However, in the case where you are prepopulating a child grid based on some value in the parent grid, the ParentRecord object does not work. ParentRecord is a recordset and is populated from the database. On prepopulation of a child grid, the parent may not yet be saved and therefore a ParentRecord recordset cannot be created. Even if the parent record is saved, the user may have made changes to the parent data in the grid so the results from the ParentRecord would not be accurate.

Page 103: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 102 —

Arguments

None

Data Type

String, Read only

Sample Usage sMyData = gINTRules.GridData.ParentGridData("MyField")

ParentRecord

Description

Recordset of the parent record corresponding to the dataset in the current grid. This reads data from the database and writes data back. The parent record is only populated by the program after the data are saved.

Arguments

None

Data Type

Single record DAO Dynaset, Read/Write

Sample Usage With gINTRules.GridData.ParentRecord

.Edit

.Fields("FieldOne").Value = lNumber

.Update

End With

ParentTableErrorField

Description

If your code encounters a problem with the Parent record and returns Success = False, this tells gINT which field to highlight in the parent record. Setting this property has the same effect as setting ErrorCol to the array column containing the field and setting ErrorRow to -1.

Arguments

None

Data Type

String, Read/Write

Page 104: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 103 —

Sample Usage gINTRules.GridData.ParentTableErrorField = "FieldOne"

The following could be used if part of your code wishes to determine whether previous code has set a value for this property:

sFieldNameVariable = gINTRules.GridData.ParentTableErrorField

RefreshParent

Description

If set True, instructs gINT to reload the Parent grid after saving all data.

Arguments

None

Data Type

Boolean, Read/Write

Sample Usage gINTRules.GridData.RefreshParent = True

RowSaveFlag

Description

This property sets or returns whether a row will be saved or not. gINT will save a row if it is newly added since the previous save or has been modified since the last save. Setting the property to True can changes the property to force a save when none was pending but setting the property to False leaves the property unchanged, that is, you cannot force a row that is new or changed to not be saved.

If what you wish to do with this property is force the saving of all rows in the grid, whether gINT has them marked for save or not, you can do this by using the ForceSave property of gINTRules.GridData.

Arguments

Row As Long: Row number that is being queried or modified.

Data Type

Boolean, Read/Write

Sample Usage If gINTRules.GridData.RowSaveFlag(lRow) Then

‘Code when the row has changed or is new.

Page 105: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 104 —

Else

‘Code when the row is unchanged.

gINTRules.GridData.RowSaveFlag(lRow) = True

End if

TableName

Description

This property returns the name of the table from which the current data array was populated.

Arguments

None

Data Type

String, Read only

Sample Usage sTableName = gINTRules.GridData.TableName

gINTRules.GridData Methods

ForceRefresh

Description

This method is used in conjunction with Add-Ins. It forces the retrieval of the data from the database into the grid for the current recordset. You would only need this if the Add-In made changes to the data in the database and then you needed to refresh the grid with the updated data. If you write such an Add-In, make sure the "Save Reqd" property is marked. If you are working on the data in the database, you need to ensure that any changes have been saved. You would reference the method at the end of your Add-In procedure.

If there are pending changes or the method is called in a non-Add-In procedure, it is ignored.

Arguments

None

Return Value

None

Sample Usage gINTRules.GridData.ForceRefresh

Page 106: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 105 —

HideField

Description

This method hides or unhides a specified field in a specified table in the current project. You may wish to do so based on the currently logged in user (see the UserName property of the gINTRules.Config object) or the project type (see GR015 for a sample of this).

This method only works when executed in the table event “gINT Rules Procedure Leaving Tab” or the system event “On Open Project for Input”.

The hiding mechanism used by the method is different than marking the "Do not display" property of the field. In that case the field is hidden to everyone that opens the project. The HideField method hides the field for the current instance of gINT only. If you wrote a rule that hides certain field based on the user, one user would see certain field and another would see others, even if they both had the same project opened at the same time.

Another difference between the HideField method and the "Do no display" property of fields is that, while in Input, the Table Show or Hide Fields dialog will not show the hidden fields, that is, the user will not be able to override your code.

If you specify a field or table name that does not exist in the current project, no action is made and no error will be generated.

Arguments

• TableName As String

• FieldName As String

• Hide As Boolean (optional; default is True)

Return Value

None

Sample Usage

See GR015 for a functional example of the use of this method.

The following two lines are equivalent and would hide the specified field:

gINTRules.GridData.HideField MyTableName, MyFieldName

gINTRules.GridData.HideField MyTableName, MyFieldName, True

The following will show (unhide) the specified field:

gINTRules.GridData.HideField MyTableName, MyFieldName, False

Page 107: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 106 —

HideGroup

Description

This method hides or unhides a specified table group in the current project. You may wish to do so based on the currently logged in user (see the UserName property of the gINTRules.Config object) or the project type (see GR015 for a sample of this).

This method only works when executed in the table event “gINT Rules Procedure Leaving Tab” or the system event “On Open Project for Input”.

While in Input, if any groups are hidden, the Table Group Sequence command will be disabled.

If you specify a group name that does not exist in the current project, no action is made and no error will be generated.

Arguments

• GroupName As String

• Hide As Boolean (optional; default is True)

Return Value

None

Sample Usage

See GR015 for a functional example of the use of this method.

The following two lines are equivalent and would hide the specified group:

gINTRules.GridData.HideGroup MyGroupName

gINTRules.GridData.HideGroup MyGroupName, True

The following will show (unhide) the specified group:

gINTRules.GridData.HideGroup MyGroupName, False

HideTable

Description

This method hides or unhides a specified table in the current project. You may wish to do so based on the currently logged in user (see the UserName property of the gINTRules.Config object) or the project type (see GR015 for a sample of this).

This method only works when executed in the table event “gINT Rules Procedure Leaving Tab” or the system event “On Open Project for Input”.

The hiding mechanism used by the method is different than marking the "Hide" property of

Page 108: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 107 —

the table. In that case the table is hidden to everyone that opens the project. The HideTable method hides the table for the current instance of gINT only. If you wrote a rule that hides certain tables based on the user, one user would see certain tables and another would see others, even if they both had the same project opened at the same time.

Another difference between the HideTable method and the "Hide" property of tables is that, while in Input, the Table List dialog will not show the hidden tables, that is, the user will not be able to override your code.

If you specify a table name that does not exist in the current project, no action is made and no error will be generated.

Arguments

• TableName As String

• Hide As Boolean (optional; default is True)

Return Value

None

Sample Usage

See GR015 for a functional example of the use of this method.

The following two lines are equivalent and would hide the specified table:

gINTRules.GridData.HideTable MyTableName

gINTRules.GridData.HideTable MyTableName, True

The following will show (unhide) the specified table:

gINTRules.GridData.HideTable MyTableName, False

ReadingsListLoadFnB

Description

This populates the current grid with the contents of the specified readings list (Data Design Readings Lists application). The data in the readings list "Reading" field are inserted into the field name specified by the "ReadingsField" argument. Optionally you can also populate a field specified by the "NameField" argument with the contents of the Name field of the readings list.

By default, the program will compact the grid on save by removing all records where there exists data in just the "ReadingField" and "NameField". Set to "CompactOnSave" argument to "False" if you do not want the grid compacted.

Page 109: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 108 —

Arguments

• ListName As String: Name of readings list from the Data Design:Readings List application to load.

• ReadingsField As String: Name of field in the current grid in which to load the contents of the "Readings" field in the specified readings list.

• NameField As String (optional): Name of field in the current grid in which to load the contents of the "Name" field in the specified readings list.

• CompactOnSave As Boolean (optional; default = True): On save, remove rows where just the ReadingsField and NameField have data.

Return Value

Returns True if failed to obtain data for any reason, that is, list not found, either of the specified fields not found, data not found in the specified list.

Sample Usage

See the code procedure (SieveInitialize) for the SV READINGS table in the GR005 gINT Rules sample code on the Web site (www.gintsoftware.com/support_gintrules.html) for an example of the use of this method.

With gINTRules.GridData

sSieveSet = .ParentGridData(s_Field_SieveSet)

sSieveSet = IIf(Len(sSieveSet), sSieveSet, s_SieveSetDefault)

If .ReadingsListLoadFnB(sSieveSet, _

s_Field_SieveSize, _

s_Field_SieveName, _

True) _

Then

MsgBox "Unable to load Readings List '" & _

sSieveSet & "'." & vbCrLf & _

"Either it doesn't exist or is empty." & vbCrLf & _

"Check Data Design:Readings Lists for a valid list."

End If

End With

Page 110: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 109 —

gINTRules.SoilClass Object

(Requires licensing for gINT 8.2 or later)

Description

The SoilClass object of gINTRules exposes the all gINT internal soil classification functions that are available in reports. This allows you to generate classifications during data entry either for display within the database or for other, internal, calculations or validations.

This object acts on the stored project data, not the data in the grid. Therefore, this object will only accurately generate the classifications in an Add-In (make sure to mark the Save Required property of the Add-In), gINT Rules procedure After Save, and gINT Rules procedure Leaving Tab. If using this object in split screen tabs, insert the reference to your procedure in the gINT Rules Procedure After Save in the child table properties dialog, not the parent. This is very important since all the data in the dataset are not fully stored until the child table completes its save procedure.

The process is to set a series of write-only properties of the object which tell the program:

• where the data required for the classification reside,

• which classification method you require,

• the identifying data for the specimen that requires classification.

Once these properties are set, you then request the classification.

See gINT Help under Functions for descriptions of each of the supported functions and the details of the arguments for each of the properties and for which properties are needed.

See gINT Rule GR017 on the Web site for a sample project that uses both the gINT standard lab testing tables and the AGS structure.

gINTRules.SoilClass Properties

(Requires licensing for gINT 8.2 or later)

Following are the write-only properties that need to be set:

• ParticleSizeTable: String, Required

• ParticleSizeField: String, Required

• PercentFinerField: String, Required

• ParticleSizeTable2ndary: String, Optional depending on the function

• ParticleSizeField2ndary: String, Optional depending on the function

Page 111: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 110 —

• PercentFinerField2ndary: String, Optional depending on the function

• AtterbergTable: String, Optional depending on the function

• PlasticLimitField: String, Optional depending on the function

• LiquidLimitField: String, Optional depending on the function

• OrganicTable: String, Optional depending on the function

• OrganicField: String, Optional depending on the function

• CITable: String, Optional depending on the function (ASTM classifications to include the Canadian "CI" classification)

• CIField: String, Optional depending on the function

• GradingOverrideTable: String, Optional depending on the function (BSI classifications only)

• GradingOverrideField: String, Optional depending on the function

• KeyValues: String, Required, comma delimited list of key fields

• ClassificationMethod: Integer, Required, Uses the following enumerated constants which correspond to each of the classification functions available in report design.

gr_SC_AASHTOGroupIndex gr_SC_AASHTOGroupIndex95 gr_SC_AASHTOSymbol gr_SC_ACE_FrostClass gr_SC_ASTMDesc gr_SC_ASTMFullDesc gr_SC_ASTMName gr_SC_ASTMSymbol gr_SC_BSIDesc gr_SC_BSIFullDesc gr_SC_BSIName gr_SC_BSISymbol gr_SC_ILDOH_Textural_Class gr_SC_MNDOT_Textural_Class gr_SC_OHDOT_Group_Index gr_SC_OHDOTSymbol gr_SC_USDA_Textural_Class

Once all the appropriate properties are set, the classification is returned with the following read-only property:

• Classification

The secondary particle size properties are for table structures where the particle size data is split between two tables, e.g., SV READINGS and HYD READINGS. It is only necessary to include the hydrometer readings for some of the classification methods (see gINT Help). However, it does no harm to include them for classifications that do not require them.

For the Atterberg limits, organic, CI, and Grading Override properties, you can leave the

Page 112: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 111 —

Table property blank and insert either expressions or literal values in the Field property. If expressions are used, they must be the same syntax as you would use in a report, e.g.:

.LiquidLimitField = "<<FirstData(<<ATTERBERG.Liquid_Limit>>,0)>>"

Sample Usage

Following is an example using the standard gINT lab testing tables:

With gINTRules.SoilClass

.ParticleSizeTable = "SV READINGS"

.ParticleSizeField = "Reading"

.PercentFinerField = "Percent_Finer"

.ParticleSizeTable2ndary = "HYD READINGS"

.ParticleSizeField2ndary = "Particle_Size"

.PercentFinerField2ndary = "Percent_Finer"

.AtterbergTable = "ATTERBERG"

.PlasticLimitField = "Plastic_Limit"

.LiquidLimitField = "Liquid_Limit"

.OrganicTable = "ATTERBERG"

.OrganicField = "Organic"

sPointID = gINTRules.GridData.ParentRecord("PointID")

sDepth = gINTRules.GridData.ParentRecord("Depth")

.KeyValues = sPointID & "," & sDepth

.ClassificationMethod = gr_SC_ASTMSymbol

sClassASTM = .Classification

End With

Page 113: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 112 —

The following example uses the gINT standard AGS table structure:

With gINTRules.SoilClass

.ParticleSizeTable = "GRAD"

.ParticleSizeField = "Reading"

.PercentFinerField = "GRAD_PERP"

.AtterbergTable = "CLSS"

.PlasticLimitField = "CLSS_PL"

.LiquidLimitField = "CLSS_LL"

.OrganicTable = "CLSS"

.OrganicField = "Organic"

.GradingOverrideTable = "CLSS"

.GradingOverrideField = "BSI_Grading_Override"

sPointID = gINTRules.GridData.ParentRecord("PointID")

sSampDepth = gINTRules.GridData.ParentRecord("SAMP_Depth")

sSampRef = gINTRules.GridData.ParentRecord("SAMP_REF")

sSampType = gINTRules.GridData.ParentRecord("SAMP_TYPE")

sSpecDepth = gINTRules.GridData.ParentRecord("Depth")

sSpecRef = gINTRules.GridData.ParentRecord("SPEC_REF")

.KeyValues = sPointID & "," & _

sSampDepth & "," & sSampRef & "," & sSampType & "," & _

sSpecDepth & "," & sSpecRef

.ClassificationMethod = gr_SC_BSISymbol

sClassBSI = .Classification

End With

Page 114: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 113 —

gINT Rules Events

Introduction

gINT Rules procedures are called from “events”, that is, gINT monitors certain occurrences and allows you to specify a procedure that is to be run when that event occurs. Currently there are two sets of events where gINT Rules can be run: Table events and System events. A third type of “event” is so different than these two categories that we have created a section for it. See the “gINT Rules Add-Ins” documentation.

In all the event properties described below, you assign a procedure to the property by clicking the browse button right of the property:

Modules without a Public Sub Main will not appear in the list where the procedure can be specified. They contain only auxiliary procedures, not procedures that can be called directly from gINT.

Page 115: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 114 —

Table Events

The gINT Rules procedure or procedures associated with a table are specified in the table properties dialog box for both project tables and library tables. These property dialogs can be brought up and edited in INPUT, DATA DESIGN Project Database, DATA DESIGN Library Tables, and DATA DESIGN Library Data. You will find the properties under the "gINT Rules" tab:

Except for the PROJECT table, and tables created with the Project key set, you will always see these properties (the “on Deletion” event is missing from Project-level tables).

Page 116: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 115 —

With tables that were supplied by gINT Software that have their own built-in code procedure (lab testing tables in Input and Library Data) you will see two other properties under this tab, "Native Code Procedure on Save" and "gINT Rules Pre-process on Save":

gINT Rules Procedure on Empty Dataset

The procedure assigned to the "gINT Rules Procedure on Empty Dataset" property is only executed on entering a dataset of a table that has not yet been populated. You could write a procedure associated with this condition that preloads the data grid.

Code assigned to this property executes when the empty grid gets focus. For main grids this means the code is fired when the screen is first displayed, as the grid is given focus when it is shown. For child grids, however, focus is not granted unless there is some data in the parent record. The parent records do not have to be saved, but the grid row has to exist as evidenced by the addition of an empty row under the newly populated row.

This means that if you have specified code to pre-populate the child grid, you fill in any fields in the parent that may be needed for your code to decide how to proceed when adding the child data. For example, in a particle size distribution split screen, the parent might contain a lookup list that specified which sieve set was used. On setting focus in the child grid your pre-population code reads that field and provides the appropriate sieve sizes.

See GR005 on the gINT Software Web site (www.gintsoftware.com/support_gintrules.html) for examples that use this property.

After running a gINT Rules Empty Dataset procedure, if rows have been added, the change

Page 117: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 116 —

flag will be set according to the programmer's setting of gINTRules.GridData.ForceSave. By default the change flag is not set so that if you leave without making any changes the added rows are not saved. Generally this is what you want to do but there are rare cases when you want the save to occur. In that case add the statement:

gINTRules.GridData.ForceSave = True

gINT Rules Procedure After Updating Grid

This event is fired after the grid has been loaded or reloaded and after a save (follows the AfterSave event). The purpose of this event is to allow the configuration of the grid by coloring rows, columns, or cells, or possibly hiding columns (for example), or showing a message based on data values. Data changes in this event are ignored.

See gINT Rules application GR018 for an example of the usage of this property.

gINT Rules Pre-process on Save

Procedures specified in the "gINT Rules Pre-process on Save" are executed before the native code and the "gINT Rules Procedure on Save" is executed after the native code. If you remove records from the data array, those records are deleted whether you pass back a success or failure flag. Therefore, if records should not be deleted unless there is complete success, perform the deletion step last in the procedure.

Native Code Procedure on Save

The "Native Code Procedure on Save" is gINT's built-in code. The property is disabled, you cannot modify it. It is shown only to make clear the execution order.

gINT Rules Procedure on Save

The procedure assigned to the "gINT Rules Procedure on Save" is executed on saving the data. This is the most commonly used of the gINT Rules table properties.

gINT Rules Procedure on Deletion

The “gINT Rules Procedure on Deletion” event is fired on the deletion of a row or rows. If a procedure is assigned to this event, it will be called and the actual deletion will not occur unless the procedure approves it. When the procedure designated for this event is run, gINT loads the gINTRules.GridData.DataArray property with the data from the rows that are selected for deletion. The gINT Rules code can check this data to determine whether all rows are ok to delete, and can show a message box. If the gINTRules.Success property is returned as “True”, the selected rows will be deleted from the grid. If .Success is returned as “False”, the deletions are cancelled.

This event is particularily useful for deletion of rows in the parent grid of a split screen grid. In this case, the Save event is not fired, but the deletion of the rows in the parent, and all associated children, is registered in the database immediately. The “on Deletion” event

Page 118: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 117 —

gives the opportunity to prevent this under conditions dictated by user-defined rules based on the data being deleted.

Procedures called from this event are run once for every deleted row. Further, only rows that correspond to records that were previously saved in the database are passed, that is, if a user added a row and deleted it before saving that row will not be passed to your procedure.

You can inspect the values of any of the fields in the current deleted row by using the usual methods of inspecting the gINTRules.GridData.DataArray values or, more commonly, writing the DataArray to a new data array. Following is a sample procedure that prevents row deletions if the field “Locked” (a boolean field) is True:

Public Sub SampleDeletionCheck

Dim iPsDepth As Integer

Dim iPsLocked As Integer

'-----------------------

With gINTRules.GridData

iPsLocked = .FieldCol("Locked")

iPsDepth = .FieldCol("Depth")

'Only one row is passed in at a time and its row

'number is always 1.

If CBool(.DataArray(iPsLocked, 1)) Then

gINTRules.Success = False 'Prevent the deletion

gINTRules.ErrorMessage = "The sample at depth " & _

.DataArray(iPsDepth, 1) & _

" is locked for editing."

Else

gINTRules.Success = True 'Allow the deletion

End If

End With

End Sub

gINT Rules Procedure After Save

The "gINT Rules Procedure After Save" will run gINT Rules code after data has been successfully saved to the database. The DataArray is not saved to the database after the procedure has run, and the ErrorCol, ErrorRow, and Success values are ignored. If an ErrorMessage is supplied it will be shown.

The intent of this event is to avoid writing redundant procedures under certain conditions.

Page 119: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 118 —

The general case is where you need to update values in one table from results from one or more other tables. For example, you are storing liquidity index in the ATTERBERG table. This index requires both the natural moisture content and the Atterberg Limits. Without this event, in the ATTERBERG table you would need to read the natural moisture content from the WC DENSITY table with an SQL and then the Atterberg Limits from the gINTRules.GridData.DataArray property, that is, from the current grid. In the WC DENSITY table you would obtain the natural moisture content from the DataArray and run an SQL to obtain the Atterberg Limits. These two different procedures do the same thing. With the After Save event, you would write one procedure that obtains all data via SQLs and then reference that one procedure in the After Save property of both tables.

gINT Rules Procedure Leaving Tab

The "gINT Rules Procedure Leaving Tab" executes specified code once per table. This is done on leaving the tab, if any change had been made to any of the datasets, or on import after the entire table has been processed. This is useful in a situation where another table is populated from data from one or more tables and is rebuilt completely based on the total data in the table. Without this property, the "gINT Rules Procedure After Save" property would need to be used and the code would run after each data set is executed. This is redundant in this situation.

System Events

The gINT Rules System Events menu item in the INPUT and DATA DESIGN Library Data applications brings up the following dialog:

All system event procedures references, that is, the data in the System Events dialog, are stored in the current library, along with the code. If the gINT Rules are locked using the "Lock" button on the List tab of the gINT Rules code dialog, the System Event menu is hidden.

On Library Open

Each time a library is opened in a gINT session, whether on first startup or on changing the Library property of the System Properties dialog or executing the Change Library command, this event is triggered. You can write an associated procedure that could:

Page 120: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 119 —

• Verify that the current library is the correct one.

• Check security settings to ensure that the person is authorized to work with this library.

• Turn off selected applications or application groups depending on the person using the library.

The latter example would use the HideAppGroup and HideApplication methods of gINTRules. See GR014 for an example of this usage.

Before Command

The "Before Command" event allows you to specify a gINT Rule that is to be run before any command is executed in gINT. This allows control over which commands can be executed. This is usually based on the current user (see the gINTRules.GintConfig.UserName property).

Sample usage:

Public Sub CheckCommandRights

If <code To determine If user Is an administrator> Then

'Has rights to all commands

Exit Sub

End If

Select Case gINTRules.CurrentCommand

Case gr_Cmd_DataImportText, gr_Cmd_DataImportExcel, _

gr_Cmd_DataImportDB, gr_Cmd_DataImportDBBatch, _

gr_Cmd_DataImportAGS

MsgBox "You do not have rights to this command"

gINTRules.CancelCommand = True

Exit Sub

End Select

End Sub

A full list of all the command constants can be found under the the gINT Rules book under Help Help Contents anywhere in the program.

A special note on gr_Cmd_AppProperties, this command launches all application dialogs. These are the main property dialogs in all applications that have properties. For example, the Log Properties dialog in the Report Design:Logs application or the current table properties dialog in Input.

Page 121: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 120 —

On Open Project for Input

This event fires after a project is opened internally by gINT and has been checked for validity but before displaying the project in Input. This event can be used to:

Prevent unauthorized personnel from opening the project 'Code to determine if the currently logged in user has

'rights to open the project in Input

'See the UserName property of the gINTRules.Config object.

If <user does not have rights> Then

gINTRules.CancelCommand = True

Exit Sub

End If

Hide or show tables in the project

See documentation on the HideTable method of the gINTRules.GridData object. The criteria for hiding or showing a table could be based on either the currently logged in user or the project type. See GR015 for an example of the latter.

Page 122: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 121 —

Special Features

Working with Dialog Boxes

Overview

Dialog boxes are used to communicate with the user and to present options from which the user can select. In languages like Visual Basic and C++, the dialog boxes are stored as controls on forms. In gINT Rules the dialog boxes are stored as specifications within the code:

Begin Dialog UserDialog 380,210,"Dialog Example" ' %GRID:10,7,1,1

Text 10,14,60,14,"Data 1:",.lblData1

TextBox 90,14,270,14,.txtData1

Text 10,35,70,14,"Data 2:",.lblData2

TextBox 90,35,270,14,.txtData2

GroupBox 10,56,350,112,"Frame Example",.fraExample

OptionGroup .Group1

OptionButton 60,77,220,14,"Option 1",.opt1

OptionButton 60,105,220,14,"Option 2",.opt2

OptionButton 60,133,220,14,"Option 3",.opt3

OKButton 80,182,90,21

CancelButton 200,182,90,21

End Dialog

The above code corresponds to the following dialog:

You could certainly type a dialog box specification, but it is much better to use the built-in

Page 123: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 122 —

dialog box editor. Following is the above dialog in the dialog editor:

To use the editor, select the Edit UserDialog from within the code window:

Dialog boxes are composed of components (also known as "controls"). The available controls are shown as buttons at the left of the editor. To place a control, click on the desired button and then left-click on the main dialog box form and then drag the mouse to

Page 124: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 123 —

set the desired control size. You edit the properties of any placed control by:

• Double clicking on the control with the left mouse button.

• Right click on the control.

• Putting focus on the control and then clicking the properties button at the upper left of the editor.

Each dialog box must contain an OK Button, a Cancel Button, or both. After completing

your dialog box design, click the Save and Exit button . This will insert the code specification for the dialog box into the code. To edit the dialog box after it was created, place the cursor anywhere between the Begin Dialog and End Dialog statements and select the Edit UserDialog menu option. On saving your changes, the updated specification replaces the previous one in your code.

To show the dialog box, use the following code AFTER the dialog box specification:

Dim dlgMyDialog As UserDialog

<some initialization code such as setting the contents of text boxes>

iResult = Dialog(dlgMyDialog)

The UserDialog object can be named whatever you wish (dlgMyDialog in the example above). There can be multiple dialogs in a procedure but to do so each must have a unique name.

The Dialog function returns a number corresponding to the button that the user clicked:

• -1 = OK Button

• 0 = Cancel Button

• 1 - ? = User-defined push button control that was clicked.

Controls can be initialized before launching the dialog box and then their values retrieved after the dialog box is closed. To set or access the values of dialog box controls, use the following syntax:

DialogName.ControlName

For example, the following sets the text within a dialog text box control:

dlgMyDialog.txtMyTextbox = "Hello World"

The following retrieves the contents of the above text control:

sMyText = dlgMyDialog.txtMyTextbox

In the case of option buttons, their values cannot be accessed directly. The value of an OptionGroup contains the number of the selected option button with 0 being the first button.

Page 125: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 124 —

Dialog Controls

Following are descriptions of the available controls. The property descriptions follow.

Control Description Available Properties

Underlying dialog box form

Container for all the controls Dialog Function, Caption, Centered

GroupBox Container used to group related controls. Field, Caption

Text Label control. Not editable by the user. Field, Caption

TextBox An editable text box. User modifiable. Field, Type

CheckBox A three-state check box: checked (-1), unchecked (0), and disabled (1).

Field, Caption, Type

OptionButton Works within a group of option buttons, each button representing one choice. Only one button within a group can be selected at any one time.

Field, Caption, Option Group

ComboBox A list of choices with the selected choice displayed in a text box at the top of the list.

Field, Array of Items, Type

ListBox A list of choices. Field, Array of Items,

Type

DropListBox A list of choices that is visible only when opened by the user.

Field, Array of Items, Type

Picture Holds a bitmap image which is imported into the control.

Field, Caption, Type

OkButton Command button that returns "-1" from the dialog box when clicked.

Field

CancelButton Command button that returns "0" from the dialog box when clicked.

Field

PushButton Command button that returns "1" to number of buttons from the dialog box when clicked.

Field

Page 126: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 125 —

Dialog Properties

Property Description

Array of Items Name of a string array variable that contains text to display in a list. This must be set before the dialog box is invoked.

Caption Text displayed by the control.

Comment Internal documentation. Appears as a comment in the dialog box specification code.

Dialog Function Name of a function that is called when certain events occur during the running of the dialog box. You can design such a function to control a dialog box and retrieve its data. To define a dialog box function:

Bring up the dialog box form properties (double click on the underlying main form).

Supply a function name in the Dialog Function property.

On saving the dialog box you will have the option to have the program insert a skeleton function. Search for "DialogFunc" in Help within the code window for additional details.

Field Name Name of the control. This name is used to access and set control properties.

Option Group The field name used to refer to a group of option buttons. Only one button within a group can be marked.

Quoted When quoted, the caption property of a control is the literal text to display. When not quoted, it gives the name of the variable that contains the text to display for the caption.

Type This varies with the control. See the Type list in the control design.

The InputBox

Instead of creating a dialog to obtain user input, you can use the InputBox dialog for single data items:

Page 127: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 126 —

The above was created with the following code:

sData = InputBox("Name of Diagram", "Supply Diagram Name", "My Diagram")

The syntax of the InputBox function is as follows:

InputBox(Prompt[, Title][, Default][, XPos, YPos])

Argument Required Description

Prompt Yes String requesting the desired information.

Title No Appears in the caption bar of the dialog.

Default No Initial value in the data entry control.

XPos No Offset in pixels of the left edge of the dialog from the left of the screen. The dialog is centered if the positions are not specified.

YPos No Offset in pixels of the top edge of the dialog from the top of the screen. The dialog is centered if the positions are not specified.

The InputBox function returns the contents of the text box control. If the user clicks the Cancel button, the function returns an empty string.

Popup Menus

Another method of obtain single choices from the user is to show a popup menu:

The above was created with the following code:

Dim iChoice As Integer

Dim sItemsV(0 To 2) As String

‘---------------------------

Page 128: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 127 —

sItemsV(0) = "Item A"

sItemsV(1) = "Item B"

sItemsV(2) = "Item C"

iChoice = ShowPopupMenu(sItemsV())

When the user clicks on the desired menu selection, the ShowPopupMenu function returns the item number selected. In the above example, if the user clicked on “Item B”, the function would return 1 into the iChoice variable. If the user clicks outside the menu or presses the Esc key, the function returns -1.

While the menu is shown, pressing the up or down arrow keys moves through the selections. Once a selection is highlighted in this way, pressing the Enter key selects that item.

The syntax of the ShowPopupMenu function is as follows:

ShowPopupMenu(MenuItems( )[, Popup Style][, XPos, YPos])

Argument Required Description

MenuItems Yes 0-Based string vector with the menu labels.

Popup Style

No vbPopupLeftTopAlign - Align menu left edge at XPos and top at YPos. (default)

vbPopupUseLeftButton - User can select menu choices with the left mouse button only. (default)

vbPopupUseRightButton - User can select menu choices with the left or right mouse button.

vbPopupRightAlign - Align menu with right edge at the XPos.

vbPopupCenterAlign - Align menu center at the XPos.

vbPopupVCenterAlign - Align menu center at the YPos.

vbPopupBottomAlign - Align menu bottom at the YPos.

XPos No Offset in pixels of the left edge of the menu from the left of the screen. The menu is placed at the mouse location positions are not specified.

YPos No Offset in pixels of the top edge of the menu from the top of the screen. The menu is placed at the mouse location positions are not specified.

Showing Messages

You could use the User Dialog facility to show messages to the user but the MsgBox function can also be used. This is much faster and easier than building a dialog for this class

Page 129: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 128 —

of form. The general syntax to use it as a subroutine is:

MsgBox Message[,Button][,Title]

When you wish to examine the return value of the function, that is, react to the button the user clicked, the arguments must be in parentheses:

If MsgBox(Message[,Button][,Title]) Then

End if

Following is a very simple message box:

It was generated with the following statement:

MsgBox "This is a message",vbOkOnly,"This is a title"

The Button and Title arguments are optional. If not specified, the OK button is shown (same as vbOkOnly), and the title "Sax Basic" (the name of the language compiler) is shown for the title.

Page 130: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 129 —

Following are the choices for buttons:

Button Constant Displays

vbOKOnly OK button only

vbOKCancel OK and Cancel buttons

vbAbortRetryIgnore Abort, Retry and Ignore buttons

vbYesNoCancel Yes, No and Cancel buttons

vbYesNo Yes and No buttons

vbRetryCancel Retry and Cancel buttons

vbCritical Critical Message icon

vbQuestion Warning Query icon

vbExclamation Warning Message icon

vbInformation Information Message icon

The vbCritical option and below are not actually buttons. They are for emphasis and can be combined with one of the choices above vbCritical:

MsgBox "This is a message",vbOkOnly + vbCritical,"Critical"

MsgBox "This is a message", vbYesNo + vbQuestion,"Question"

Page 131: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 130 —

MsgBox "This is a message",vbRetryCancel + vbExclamation,"Exclamation"

MsgBox "This is a message", vbYesNoCancel + vbInformation, "Information"

Besides just showing a message, you sometimes need a decision to be made by the user:

Select Case MsgBox("File Exists. Overwrite?", _

vbYesNoCancel + vbQuestion, _

"Exporting Data to a File")

Case vbYes

Case vbNo

Case vbCancel

End Select

MsgBox, when used as a function as we shown have above, returns the button that is clicked by the user. The return values can be:

vbOK

vbCancel

vbAbort

vbRetry

vbIgnore

vbYes

vbNo

Page 132: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 131 —

Using Multiple Modules

You could put all procedures for all your gINT Rules Code in one module. However, this could become quite awkward to work with. You might have different database structures that all have a SAMPLE table but require different code procedures. You might also have code for various library tables.

A better method to organize your procedures is to have separate modules. The problem then becomes what to do with procedures and declarations that are needed between modules. We don't want to have them repeated. Normally gINT Rules Code runs only one module. You can have it include other modules by inserting the following in the declarations section of the main module:

'#LibInclude xxxxx

where "xxxxx" is the name of the module to include. You can include multiple modules, just have a separate line per module. With this structure, you could have one module that stores procedures and declarations that are used by procedures in other modules. These would be declared "Public". For example:

Public Declare Function XXX Lib "YYY.DLL" (…) As Type

Public gsDataA() As String

Public Sub MyProc(…)

End Sub

Public Function MyProcFnD(…) As Double

End Function

These Functions and Subs can then be used by procedures in any other module. The variables declared as Public can be read and modified by any procedure in any module. Auxiliary modules that contain these common procedures and declarations do not need a Sub Main. However if there is a Sub Main it is executed when the auxiliary module is loaded before execution of your designated code procedure begins. You can place initialization code for the module there. If you use a Sub Main in an auxiliary module, you must declare it Private.

If you read through the language help available in the Code window you will find references to the following two native instructions:

'#Include: xxxxx

'#Uses xxxxx

These two perform the same function as '#LibInclude but refer to modules stored as disk files. You can certainly use them. The only difference is where the included modules are

Page 133: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 132 —

stored, on disk or in the gINT Library.

If external modules are referenced in your gINT Rules modules ("#Uses" metacommand in the Declaration section), you can set a full path to the module:

'#Uses "c:\program files\gint\Modules\MyModule.bas"

or relative path. For example:

'#Uses "Modules\MyModule.bas"

This tells the program that "MyModule.bas" is located in the "Modules" folder under the folder of the current library. The following:

'#Uses "MyModule.bas"

says that "MyModule.bas" is located in the same path as the current library.

Running External DLLs

Procedures in DLLs (Dynamic Link Libraries) can be accessed exactly like they are in any other programming language. In the Declarations section of a code module, you must declare each DLL procedure as follows:

Declare Function Name Lib "DLL Name.DLL" (argument list) As Type

Declare Sub Name Lib "DLL Name.DLL" (argument list)

For example:

Public Declare Function MyFunction Lib "MYDLL.DLL" (pdXyz As Double, _

piAbc As Integer) _

As Double

Note: The wrapping and indentations are optional; the above could appear on one line.

You can even access all the available Windows API procedures. There are also commercially available libraries of procedures in DLLs that you can purchase. You just need the declaration specifications and documentation of the procedures.

The GINT.DLL file that is shipped with the program has many dozens of procedures that we use in coding gINT. However, we will not publish the declarations or documentation of these procedures. The reason for this is that if we do, then we have to be very careful not to change them in a way that would break existing code in our clients' procedures. We change and update our DLLs regularly so exposing them limits us as to what we can do with them.

There are methods of discovering the declarations of procedures in DLLs. If you do so and use our procedures, you do so at your own risk. We do not guarantee that we will not change them in a way that would be detrimental to your code. Also, it is planned to eliminate GINT.DLL in a future release of the program.

Page 134: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 133 —

External Object References

Many programs expose object models so that they can be used by other programs. To access these objects, in the Code window, select the Edit References menu option. The following dialog box will appear:

It might take awhile for the dialog box to finally appear. It must first scan your system for all registered objects. It then places all the object references that are already selected and puts them at the top of the list. If an object exists on your system but does not appear in the list because it is not registered, you can add it to the list by browsing for the file using the Browse button.

You can select as many references as desired. Those selected are then available to you for creation of objects in your code. For example, following is an example of using the Excel object:

Dim xlsApp As Excel.Application

Set xlsApp = CreateObject("Excel.Application")

xlsApp.Quit

Set xlsApp = Nothing

CreateObject is a built-in function in the gINTRules Code interpreter. Once created, you then have access to all properties and methods exposed by the Excel object. You can open and modify existing spreadsheet files or create new ones. You need to refer to the documentation for the specific application that you are using for descriptions of their

Page 135: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 134 —

properties and methods.

These references are stored with the active module. If you need a particular object reference in more than one module, you must set it in each module where it is needed. For these external references to work, the external object must exist on your system.

For example, you have created a gINT Rules procedure that makes use of the Excel object. You give this procedure to someone else in your office and they don't have Excel. Your code will not work.

A special reference is that of the Microsoft DAO 3.6 Object Library. This is needed if you want to create your own datasets within your code or manipulate database objects in any way. You will have this library on your system because it is shipped with gINT. gINT uses it for its own database manipulations. If you do not perform your direct database manipulations, you do not need to have this reference. However, the database methods and properties of the gINTRules object will not be exposed during your code editing. Currently there are only two: gINTRules.CurrentProject and gINTRules.GridData.ParentRecord. If you were to type these two in a module where there was a DAO reference, typing a period at the end of the specification will display a list of the properties and methods available to you with these objects. Without the reference, nothing will be displayed.

You can type the property or method after the period and the code will work but it is much more convenient to have the list. This avoids mistyping the property or method.

Running Other Programs

Using the "Shell" command, you can launch any Windows program from within your code. Search for "Shell" in the Code Window Language Help for details. For example:

Shell "write.exe",vbNormalFocus

This would launch Windows WRITE (which actually launches WORDPAD in Windows 2000 and XP). Using the AppActivate and SendKeys commands (see Language Help) in conjunction with Shell, you can actually control another Windows program. A useful Windows API function for launching an application is FindExecutable:

Declare Function FindExecutable Lib "shell32.dll" Alias "FindExecutableA" _

(ByVal lpFile As String, _

ByVal lpDirectory As String, _

ByVal lpResult As String) _

As Long

This will find the application associated to a particular file type on the computer. For example, find the program that is associated with the "PDF" or "XLS" files. Please see the Windows API documentation for details.

This is available with most programming language products and there are also many books on the subject. The Microsoft Knowledge Base located at www.microsoft.com has

Page 136: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 135 —

documentation and articles on the specific API procedures and sample source code.

See the ExecuteProgram method of the gINTRules for a more direct method of launching programs.

Rerunning Code

You have written a gINT Rules procedure for checking and manipulating data in an Input table. Dozens of boreholes of data have been input in this table and results calculated by the code procedure. Now you realize that your code is wrong and that the existing data need to be resaved through the new code.

This is a simple process. Make the necessary code modifications and then, while in the table with the new code, select the gINT Rules Recalculate current table menu option. All the data in the current table will be rerun through the updated procedure. All errors will be written to a log file and displayed at the end of the process. If there were no errors, nothing will be displayed at the end.

The procedures that are run in this process are those associated with the following events:

• gINT Rules Pre-process on Save

• Native Code Procedure on Save

• gINT Rules Procedure on Save

• gINT Rules Procedure After Save

The gINT Rules Recalculate current table menu option will be enabled only in tables that either have a gINT Rules code procedure associated with it or is one of the built-in gINT lab testing tables that executes code embedded in the program.

If you show errors via a message box or dialog box in your code, these will interrupt the batch process. It is better to write error messages via the gINTRules.ErrorMessage property. These will be accumulated and then shown at the end of the recalculation process.

Importing Data and Convert Projects

You wish to import data into a table where you have written a gINT Rules code procedure. On import the program performs its normal importing process without regard to your code. Data are saved to the database, unless there were problems with certain records.

After the normal import process is completed, the program then runs all imported datasets through your code procedures. Any errors will appear in the normal post-import log file. So you don't have to import data that are calculated by your code.

Page 137: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 136 —

The procedures that are run in this process are those associated with the following events:

• gINT Rules Pre-process on Save

• Native Code Procedure on Save

• gINT Rules Procedure on Save

• gINT Rules Procedure After Save

• gINT Rules Procedure Leaving Tab

If you show errors via a message box or dialog box in your code, these will interrupt the batch process. It is better to write error messages via the gINTRules.ErrorMessage property. These will be accumulated and then shown at the end of the import process.

This process occurs whether you are importing data or running the Convert Projects utility.

On import, gINT always arranges the order of the tables in a manner that ensures that a parent table is always imported before a child. This is crucial since child records cannot be imported unless an associated parent record exists.

If you have gINT Rules procedures that depend on data from one table to populate another, it is possible that the algorithm used by gINT for table order may not work, that is, the table that has the code to do the calculation is imported before the table that has the data on which to do the calculations. If you have such a condition (rare as it might be), you can override the import order using a correspondence file with a <<Sequence>> list in the file header. Search Help for "Using a Sequence List" for details.

Page 138: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 137 —

gINT Rules Add-Ins

Description

You have the ability of adding your own commands in any gINT application that supports gINT Rules (currently Input and Library Data). These custom commands will appear under an "Add-Ins" menu right of the "gINT Rules" menu in the applications where custom commands are assigned. Each custom command is associated with a gINT Rules procedure. These specifications are stored in your library and can be imported and exported via the Utilities:Lib Merge/Copy application.

This facility extends the functionality of your gINT interface by performing user-defined tasks. For example:

• Automate import of CPT data.

• Generate a series of reports based on the data in the current project.

• Create your own Excel import and export procedures.

• Query the project data and generate statistics that are available instantly in Input.

The list is endless. Look for tasks that require multiple steps in gINT. These can be encapsulated into an Add-In.

If you have a command whose function is strictly for a particular table in the project database, you need to have code at the top of the gINT Rules Procedure that prevents execution from another table. For example:

If UCase(gINTRules.GridData.TableName) <> "MY TABLE" Then

MsgBox "This command only applies to 'My Table', _

vbOkOnly, _

"My Cmd Name"

Exit Sub

End If

The gINT Rules code that would be associated with commands that run under the Add-Ins menu work like any other code. However, they do have the added feature of being able to run gINT scripts. See the documentation on the gINTRules.RunScript method for details.

See all the gINT Rules Samples on the Web site whose names start with a “GRA” prefix. These are all gINT Rules Add-Ins.

Page 139: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 138 —

The Add-Ins Manager

To create an Add-In, you will of course have to create a procedure that will be called when the menu item is selected. The Add-Ins menus are created and maintained using the gINT Rules Add-Ins Manager menu option. The following dialog appears:

Column Required Description

Unique Name Yes A name of your choosing. The list is sorted by this field. The purpose of this field is mainly for third-party developers. If they update their commands, merging in their updated library will update only their entries.

If you are distributing Add-Ins, make sure these names will not be duplicated by another source. For example, add a prefix to each that identifies that they are from you: "John A. Smith Cmd 1" or "ACME Corporation Menu ABC-XYZ 2".

If you are on the receiving end of distributed Add-Ins, don't change these names. If the distributor updates you, the updates will overwrite the previous menus if the previous menus retained their original names.

Description No For your use only for documentation.

Page 140: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 139 —

Column Required Description

Command Menu Label

Yes The text that appears in the menu. To give the user keyboard access to the menu item (“hot” key), insert an ampersand (&) before a letter. At run time, this letter is underlined, and the user can access the item by pressing ALT and the access key. For example, in "M&y Command", the "y" will be underlined. If you need an ampersand in the label, double it. For example, "C&heck xxx && yyy" will appear as "Check xxx & yyy" in the menu and the "h" character will be the access character. If a hot key is not assigned in a gINT Rule Add-In, the program automatically assigns one to one of the characters in the command label. It ensures that the hot key is not duplicated. If all the characters in the command label are used in the commands above the current command, no hot key is assigned.

Two or more command labels of the same name cannot be under the same submenu within the same application. Note that this rule only applies to the Add-Ins Manager dialog. If you were to merge in a command that duplicates another under the same submenu and application, they will both appear. You can then go into the Add-Ins Manager and change the name of one to make it clear the differences between the two.

Separator Line After

N/A Inserts a menu separator line after that menu item. (Requires licensing for gINT 8.2 or later)

Short Cut No This is a drop down list of all allowable, user-defined short cut combinations. Missing from this list are any short cuts used by gINT. In addition, some are missing that are not used in the program but we have reserved them. You cannot have the same two short cuts in the same application. If you merge in Add-Ins that replicate short cuts in the same application, the duplicates are removed. Further, if we do add a new short cut to gINT, the short cut is automatically removed from the drop down list and from any Add-Ins that use it.

Under Submenu

No If blank, the Command Menu Label will appear directly under the "Add-Ins" menu. If a value is supplied, the specified submenu will appear under the "Add-Ins" menu and the Command Menu Label will appear in a list right of the submenu. An access character can be applied to the submenu name. See the description of "Command Menu Label" for details.

Application(s) Yes These are the application or applications under which the command will appear. You can select one or more.

gINT Rules Procedure

Yes The gINT Rules procedure that will be executed when the command is selected.

Page 141: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 140 —

Column Required Description

Save Reqd N/A If marked, if there is a save pending, the data must be saved before the command is executed. For commands that might need to manipulate the current data on screen in the database, this attribute must be set, otherwise the command will not be working with the most current information. For commands that manipulate data in the current screen, this attribute must not be set.

Last Updated N/A Read-only field updated by gINT with the current date and time whenever a record is added or modified.

Sample Usage

We wish to create the following menus under the Input application:

Add-Ins

Accounting --> Project Summary

Monthly Invoice

Update Acc't DB

Import CPT --> ACME CPT Inc.

Penetrators Ltd.

XYZ Corp.

Data Problems Data Problems

The above would have a setup similar to the following:

Note the numbers right of “Accounting” in the “Unique Name” column. This was done to force the sort order. We have also added short cuts to each command. This is optional. All of these commands perform actions on the saved data, therefore, the "Save Reqd" attribute was set for all of them.

Note also that the “Separator Line After” option was marked for the “Monthly Invoice” menu. See the result below under the “Accounting” submenu.

Page 142: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 141 —

The above setup results in the following menus:

Page 143: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 142 —

Interaction with Field Rules

When gINT Rules and Field Rules are both used, the program executes the gINT Rules first and then checks Field Rules. This can take some programming burden off of gINT Rules. For example, you could write gINT Rules code that checks that values are between certain ranges and then format them to a certain number of decimal places.

Instead, you can put those specifications in Field Rules. Besides being faster and easier, this also gives the user the ability to make changes to these parameters without changing the gINT Rules code. This order is followed whether data are manually input or they are imported.

Page 144: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 143 —

The Basic Process

The following procedure will lead you through the set up of your initial gINT Rules code. The constructs that you will be using will be explained in the Code Samples topics. You will notice that the Code Samples initially show different variable names than those shown below. Code Samples takes you through different levels of the code construction process starting simply and then adding refinements.

The process below uses the code that the CODE SAMPLES ultimately arrive at. We strongly recommend that you work through the CODE SAMPLES to better understand the following process. Move to Input and select the File gINT Rules Code menu option. The following dialog box appears:

First you will create an auxillary procedures module. In this module will be stored procedures that are called by the main procedures that will do the bulk of the work. These auxillary procedures could be stored in the same module as the main procedures but separating them makes a more maintainable configuration.

Page 145: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 144 —

Name the module under the "Module Name" column in the dialog box and, optionally, give a description. Then click on the "Code" tab of the dialog box:

The horizontal line near the top of the code editor separates the Declarations section (above) from the procedures. On new modules, gINT always inserts "Option Explicit" in the Declarations section of the module. This tells the compiler that every variable used in the code must be declared (Dim, Const, Static, Private, Public).

Without this option, you could type variable names anywhere in the code without declaring them. For new programmers this option may seem like an inconvenience but to those who remember what it was like without this option, it is a great blessing. We strongly recommend using this option. This option also finds misspelled variable names which would be difficult to track down otherwise. Now paste in the following into the Declarations section below the "Option Explicit" line:

'Commonly used field names

Public Const gs_Depth As String = "Depth"

Public Const gs_HoleDepth As String = "HoleDepth"

Public Const gs_PointID As String = "PointID"

Public glNumRows As Long

Page 146: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 145 —

Public gsDataA() As String

One common procedure that will be used by all of the final versions of the main procedures in the CODE SAMPLES is the following:

Page 147: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 146 —

Public Function InitFieldsFnB(ParamArray pvFieldsV() As Variant) _

As Boolean

'Purpose:

' Determine the positions of fields in the data array.

' If any or not found, report the missing field or fields

' and abort further code execution.

'Input:

' pvFieldsV(): Elements 0, 2, 4,... are the field names.

'Output:

' pvFieldsV(): Elements 1, 3, 5,... are the field positions.

'Returns:

' True if fields were not found, False if all were found.

'*****************************************************

Const s_FieldSeparator As String = ", "

Dim iInd As Integer

Dim iPsField As Integer

Dim sMissingFields As String

'------------------

InitFieldsFnB = False

sMissingFields = ""

With gINTRules.GridData

For iInd = 0 To UBound(pvFieldsV) Step 2

iPsField = .FieldCol(CStr(pvFieldsV(iInd)))

If iPsField > 0 Then

pvFieldsV(iInd + 1) = iPsField

Else

sMissingFields = sMissingFields & _

s_FieldSeparator & _

CStr(pvFieldsV(iInd))

End If

Next iInd

If Len(sMissingFields) > 0 Then

sMissingFields = Mid$(sMissingFields, Len(s_FieldSeparator) + 1)

Page 148: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 147 —

MsgBox "The following field(s) are missing " & _

"from this table." & vbCrLf & _

Space$(5) & sMissingFields & vbCrLf & _

"Cannot perform the save checks " & _

"and calcs without it/them." & vbCrLf & _

"Data will be saved as-is.", _

vbOkOnly, "Field Checking"

InitFieldsFnB = True

End If

End With

End Function

Paste this into the code editor below the Declarations section. Click the Save button at the lower right and then and click on the List tab. Add a new module. This will contain the main procedures that are called from gINT. Name it whatever you wish and then click on the "Code" tab. Insert the following line above the "Option Explicit" line:

'#LibInclude "xxx common procedures"

Change "xxx common procedures" to whatever you named the first module. The name must be in quotes. This tells the program that the auxillary module is to be loaded with the main module.

For all modules that will be called from gINT you must define a Sub Main. All control flows first through this procedure. In Sub Main you will place your initialization, main calling, and termination code. Paste the following below the Declarations section:

Public Sub Main

With gINTRules.GridData

'Put the grid data into a working string data array.

gsDataA = .DataArray

glNumRows = UBound(gsDataA, 2)

CallByName Me, gINTRules.ProcedureName, vbMethod

'Put the modified data array back into the input grid.

.DataArray = gsDataA

'Success is True if there were no errors.

gINTRules.Success = CBool(.ErrorCol = 0)

End With

End Sub

The array variable gsDataA is defined in the Declarations section of the auxillary module as

Page 149: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 148 —

"Public" and is therefore available to all procedures in all modules that include the "'#LibInclude …" that reference the auxillary module.

There are only five lines of code in the procedure, the first copies the data from the current grid in Input to the global string array for manipulation by the other procedures (defined as "Public" in the auxillary module), the second determines the number of rows in the array and places that value in another Public variable defined in the auxillary module, the third calls the procedure that is assigned in the table properties of the current table (see below).

On returning from the called procedure, the fourth copies the data back into the grid. The last line tells gINT if the data was correct. If not (there was an error column assigned), gINT will not allow the save to proceed.

Beyond Sub Main, create as many procedures as desired. For example, you could have a code procedure for checking data in the SAMPLE table and to perform calculations and another for the CPT table, etc. At minimum, just define the procedures, so that they can be assigned to the appropriate tables. Now paste the following procedure template below Sub Main:

Page 150: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 149 —

Public Sub xxx

'*****************************************************

'Date and written by

'Description:

' xxx

'*****************************************************

Const s_Field1 = "Field Name 1"

Const s_Field2 = "Field Name 2"

...

Const s_FieldN = "Field Name N"

Dim iPsField1 As Integer

Dim iPsField2 As Integer

...

Dim iPsFieldN As Integer

Dim lRow as Long

...

'-----------------------

'Obtain pointers to the field data within the data array.

If InitFieldsFnB(s_Field1, iPsField1, _

s_Field2, iPsField2, _

..., _

s_FieldN, iPsFieldN) _

Then

'One or more of the required fields missing from the table.

Exit Sub

End If

With gINTRules.GridData

'Check each row. Rows and columns are 1-based.

For lRow = 1 To glNumRows

Core work done here

...

Next lRow

End With

End Sub

Page 151: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 150 —

To make this procedure functional you will need to do the following:

1. Change the Sub name from "xxx" to a name that reflects the procedure function.

2. Replace "Date and written by" to the creation date and your name or initials.

3. Supply a description of the procedure.

The "Const" section lays out the field names that you will be using in the procedure. This is not necessary. You could type in the names as you need them in the code. Using constant definitions lays out in one place the fields that you will need. If a field name changes, you will only need to change it in one place instead of searching for all occurrences of the name.

If you have fields that you will be using repeatedly in multiple procedures, define them as "Public" constants in the Declaration section of the auxillary module. Note that we have already done that above for the PointID, Depth, and HoleDepth fields.

4. Declare the column position variables, one for each field name defined in the "Const" section.

5. Change the arguments in the call to InitFieldsFnB to match your field name and column position declarations.

6. Replace the "Core work done here" with your coding.

Following is a sample procedure:

Public Sub WaterContentDensity

'*****************************************************

'28Oct2003 kj

'Description:

'gINT requires that the height and diameter for the density

'calculations be in millimeters. This procedure:

'1. Allows input of diameter and height in inches.

'2. Provides up to 3 values for each diameter and

' height and takes the average.

'This procedure is designed to run in t he gINT supplied WC DENSITY table

'in its Lab Testing group.

'*****************************************************

Const s_Field_Dia1 = "Diameter 1"

Const s_Field_Dia2 = "Diameter 2"

Const s_Field_Dia3 = "Diameter 3"

Const s_Field_DiamMM = "Diameter"

Page 152: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 151 —

Const s_Field_Ht1 = "Height 1"

Const s_Field_Ht2 = "Height 2"

Const s_Field_Ht3 = "Height 3"

Const s_Field_HtMM = "Height"

Dim dSum As Double

Dim iCount As Integer

Dim iDiamMM As Integer

Dim iHtMM As Integer

Dim iPsDiam1 As Integer

Dim iPsDiam2 As Integer

Dim iPsDiam3 As Integer

Dim iPsDiamMM As Integer

Dim iPsHt1 As Integer

Dim iPsHt2 As Integer

Dim iPsHt3 As Integer

Dim iPsHtMM As Integer

Dim lRow As Long

'------------------------

'Determine the field positions of the necessary fields in the array.

If InitFieldsFnB(s_Field_DiamMM, iPsDiamMM, _

s_Field_Dia1, iPsDiam1, _

s_Field_Dia2, iPsDiam2, _

s_Field_Dia3, iPsDiam3, _

s_Field_HtMM, iPsHtMM, _

s_Field_Ht1, iPsHt1, _

s_Field_Ht2, iPsHt2, _

s_Field_Ht3, iPsHt3) _

Then

'One or more of the above fields are missing from the current table.

Exit Sub

End If

For lRow = 1 To glNumRows

Page 153: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 152 —

'Sum the diameters in inches and determine the number of values.

dSum = 0

iCount = 0

Call RunningTotal(iPsDiam1, lRow, iCount, dSum)

Call RunningTotal(iPsDiam2, lRow, iCount, dSum)

Call RunningTotal(iPsDiam3, lRow, iCount, dSum)

If iCount Then

'Determine the average and convert to millimeters.

gsDataA(iPsDiamMM, lRow)= Format$(CStr(25.4 * dSum / _

CDbl(iCount)),"0.0")

End If

'Sum the heights in inches and determine the number of values.

dSum = 0

iCount = 0

Call RunningTotal(iPsHt1,lRow, iCount,dSum)

Call RunningTotal(iPsHt2,lRow, iCount,dSum)

Call RunningTotal(iPsHt3,lRow, iCount,dSum)

If iCount Then

'Determine the average and convert to millimeters.

gsDataA(iPsHtMM, lRow)= Format$(CStr(25.4 * dSum / _

CDbl(iCount)),"0.0")

End If

Next lRow

End Sub

7. Save your work and either leave the dialog box or leave the dialog box open or

minimize it, as you wish. Bring up the table properties dialog box for the tables that will use one of the defined procedures, move to the "gINT Rules" tab, and click the browse button right of the appropriate gINT Rules procedure property. Select the appropriate module from the Type drop-down list and then select the procedure from the second drop-down list.

Note that modules without a Public Sub Main will not appear in this list. They contain only auxillary procedures, not procedures that can be called directly from gINT.

You can repeat the steps above for each table in your project file or for each Library Table in your library file. The DATA DESIGN Project Database and Library Tables applications also support assigning gINT Rules Procedures in the table properties dialog box.

Page 154: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 153 —

Now move to a table where you have assigned a procedure and supply some test data. Bring up the gINT Rules Code dialog box, move to the appropriate module and procedure and write and test your code. While in the code editor, you can run the code by pressing F5, or by clicking the Start/Resume button (right facing, solid triangle). Data are not saved using these methods but your code will be run and the results written back to the grid.

Alternatively, you can click the Save button . This will also run your code and save the data as well. You can also change the data in the grid while the dialog box is up. You can even move to another table. If you leave Input or Library Data, the dialog box is closed.

Note that before gINT invokes the gINT Rules code:

• It checks that required fields have data.

• It compacts the grid, that is, empty rows are eliminated.

• It sorts the rows by the key field or fields.

With these checks already performed by the program, you do not have to write code to check for these items.

Page 155: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 154 —

Code Samples

Introduction

We will be presenting code procedures for four types of data tables, sample, CPT, lithology, and chemistry. We will be taking you through a number of iterations of the code to help illustrate the development of various concepts. You can download the final code from our Web site at www.gintsoftware.com/support_gintrules.html. The code below is contained in the gINT Rules sample project GR001.

The code below assumes an initial setup like the one described in the The Basic Process section, that is, with an auxillary module containing the declarations and the InitFieldsFnB procedure and a main module containing the Sub Main configured as that section describes.

Note that there are as many ways to write code as there are programmers (actually more!). The code that is presented below is just one way to accomplish the tasks. Feel free to experiment and write the code in the manner that you feel is best.

Setting Up

First we will follow all the steps in The Basic Process section. We will name the auxillary module “GR001 COMMON PROCEDURES” and the main module “GR001”. Remember that the #LibInclude line must hold the new auxillary module name. We will skip the insertion of the generic Public Sub XX in the main module.

Sample Data

Overview

You have a SAMPLE table set up as follows:

We wish to do the following:

• Check that the sample data are not deeper than the hole depth. If so, ask if the hole depth should be changed to the current deepest sample and, if so, change it.

Page 156: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 155 —

• Calculate percent recovery, solid core recovery, and rock quality designation from their respective lengths and the overall sample length.

• Ensure that percent recovery is greater than or equal to the percent solid core recovery which must be greater than or equal to the rock quality designation.

• Allow the user to input either the lengths or the final percentages. If both exist, ignore the percentages and recalculate from the lengths.

First Code Iteration

In the GR001 (main) module we will insert a new procedure under the Sub Main.

Public Sub Sample

'*****************************************************

'27Jul2003 sc

'Purpose:

'1. Check that the Sample data are Not deeper than the hole depth.

' If so, ask If the hole depth should be changed To the current deepest

' sample and, if so, change it.

'2. Calculate percent recovery, solid core recovery, And rock quality

' designation from their respective lengths And the overall

' Sample length.

'3. Ensure that percent recovery is greater than or equal to the percent

' solid core recovery which must be greater than or equal to the

' rock quality designation.

'4. Allow the user to input either the lengths Or the final percentages.

' If both exist, ignore the percentages and recalculate

' from the lengths.

'Input, Output:

' None, uses module level array to pass data and the gINTRules object

'*****************************************************

Dim bNoSampleLen As Boolean

Dim dDepth As Double

Dim dHoleDepth As Double

Dim dMaxDepth As Double

Dim dSampleLen As Double

Dim iPercent As Integer

Dim iPsDepth As Integer

Page 157: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 156 —

Dim iPsRecLen As Integer

Dim iPsRecPC As Integer

Dim iPsRQDLen As Integer

Dim iPsRQDPC As Integer

Dim iPsSampleLen As Integer

Dim iPsSCRLen As Integer

Dim iPsSCRPC As Integer

Dim lRow As Long

Dim lRowDeepestDepth As Long

Dim sLen As String

Dim sRec As String

Dim sRQD As String

Dim sSCR As String

'-----------------------

With gINTRules.GridData

'Obtain pointers to the field data within the data array.

iPsDepth = .FieldCol("Depth") 'feet

iPsSampleLen = .FieldCol("Length") 'inches

iPsRecLen = .FieldCol("Rec Length") 'inches

iPsRecPC = .FieldCol("Rec") '%

iPsSCRLen = .FieldCol("SCR Length") 'inches

iPsSCRPC = .FieldCol("SCR") '%

iPsRQDLen = .FieldCol("RQD Length") 'inches

iPsRQDPC = .FieldCol("RQD") '%

'Check each row. Rows and columns are 1-based.

For lRow = 1 To glNumRows

'Check to see if there is a value for the sample length.

'Don't generate an error message unless it is required

'in a calculation.

sLen = gsDataA(iPsSampleLen, lRow)

If Len(sLen) > 0 Then

dSampleLen = CDbl(sLen)

bNoSampleLen = False

Page 158: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 157 —

Else

dSampleLen = 0

bNoSampleLen = True

End If

'Find the deepest depth.

'Not necessarily the depth of the last sample.

'E.g., Sample at 5 with a length of 60" but other sample data at 7.

dDepth = CDbl(gsDataA(iPsDepth, lRow)) + (dSampleLen / 12)

If dDepth > dMaxDepth Then

dMaxDepth = dDepth

lRowDeepestDepth = lRow

End If

'Calculate recovery percentage from recovery length

sLen = gsDataA(iPsRecLen,lRow)

If Len(sLen) > 0 Then

If bNoSampleLen Then

.ErrorCol = iPsSampleLen

.ErrorRow = lRow

gINTRules.ErrorMessage = _

"Sample Length is required to calculate " & _

"Recovery, SCR, and RQD percentages"

Exit For

End If

iPercent = CInt(100 * CDbl(sLen) / dSampleLen)

If iPercent > 100 Then

.ErrorCol=iPsRecLen

.ErrorRow=lRow

gINTRules.ErrorMessage = _

"Recovery Length is greater than the Sample Length."

Exit For

End If

gsDataA(iPsRecPC,lRow) = CStr(iPercent)

End If

Page 159: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 158 —

'Calculate solid core recovery percentage

'from solid core recovery length

sLen = gsDataA(iPsSCRLen,lRow)

If Len(sLen) > 0 Then

If bNoSampleLen Then

.ErrorCol = iPsSampleLen

.ErrorRow = lRow

gINTRules.ErrorMessage = _

"Sample Length is required to calculate " & _

"Recovery, SCR, and RQD percentages"

Exit For

End If

iPercent = CInt(100 * CDbl(sLen) / dSampleLen)

If iPercent > 100 Then

.ErrorCol = iPsSCRLen

.ErrorRow = lRow

gINTRules.ErrorMessage = _

"SCR Length is greater than the Sample Length."

Exit For

End If

gsDataA(iPsSCRPC,lRow) = CStr(iPercent)

End If

'Calculate RQD percentage from RQD length

sLen = gsDataA(iPsRQDLen,lRow)

If Len(sLen) > 0 Then

If bNoSampleLen Then

.ErrorCol = iPsSampleLen

.ErrorRow = lRow

gINTRules.ErrorMessage = _

"Sample Length is required to calculate " & _

"Recovery, SCR, and RQD percentages"

Exit For

End If

Page 160: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 159 —

iPercent = CInt(100 * CDbl(sLen) / dSampleLen)

If iPercent > 100 Then

.ErrorCol = iPsRQDLen

.ErrorRow = lRow

gINTRules.ErrorMessage = _

"RQD Length is greater than the Sample Length."

Exit For

End If

gsDataA(iPsRQDPC,lRow) = CStr(iPercent)

End If

'Check that Rec% >= SCR% >= RQD%.

sRec = gsDataA(iPsRecPC, lRow)

sSCR = gsDataA(iPsSCRPC, lRow)

sRQD = gsDataA(iPsRQDPC, lRow)

If Len(sSCR) > 0 Then

If Len(sRec) > 0 Then

If CDbl(sSCR) > CDbl(sRec) Then

.ErrorCol = iPsSCRPC

.ErrorRow = lRow

gINTRules.ErrorMessage = _

"SCR % must be less than or equal to the Recovery %."

Exit For

End If

End If

End If

If Len(sRQD) > 0 Then

If Len(sSCR) > 0 Then

If CDbl(sRQD) > CDbl(sSCR) Then

.ErrorCol = iPsRQDPC

.ErrorRow = lRow

gINTRules.ErrorMessage = _

"RQD % must be less than or " & _

"equal to the Solid Core Recovery %."

Page 161: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 160 —

Exit For

End If

End If

If Len(sRec) > 0 Then

If CDbl(sRQD) > CDbl(sRec) Then

.ErrorCol = iPsRQDPC

.ErrorRow = lRow

gINTRules.ErrorMessage = _

"RQD % must be less than or equal to the Recovery %."

Exit For

End If

End If

End If

Next lRow

If .ErrorCol > 0 Then

Exit Sub 'Error found above. Stop processing.

End If

'Make sure the deepest depth in the data is

'less than or equal to the hole depth.

dHoleDepth = CDbl(.ParentRecord.Fields("HoleDepth").Value)

If dMaxDepth > dHoleDepth Then

Begin Dialog UserDialog 400,119,"Data Depths" ' %GRID:10,7,1,1

OKButton 170,91,80,21

TextBox 20,7,370,42,.txtMessage,1

CheckBox 20,63,370,14, _

"Mark here to change the hole depth to the max depth", _

.chkChangeDepth

End Dialog

Dim dlgHoleDepth As UserDialog

dlgHoleDepth.txtMessage = _

"The maximum data depth (" & CStr(pdMaxDepth) & ") " & _

"is greater than the hole depth " & _

Page 162: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 161 —

"(" & CStr(dHoleDepth) & ")."

Dialog dlgHoleDepth

If CBool(dlgHoleDepth.chkChangeDepth) Then

'User marked the check box.

'Change the POINT HoleDepth to the deepest depth in these data.

With .ParentRecord

.Edit

.Fields("HoleDepth").Value = dMaxDepth

.Update

End With

Else

'User did not mark the check box.

'Abort the save and return focus to the row with

'the deepest depth.

'No message needs to be passed back.

.ErrorCol = iPsDepth

.ErrorRow = lRowDeepestDepth

End If

End If

End With

End Sub

Second Code Iteration: Encapsulating the Percent Calculations

This code works but you can see that there are large blocks of repetitive code that are not that different. These can be encapsulated into other procedures. We can create a function to calculate the percentages. We would store this procedure in the auxillary module (GR001 COMMON PROCEDURES).

Page 163: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 162 —

Public Function PercentFromLengthFnB(ByVal pbNoOverallLen As Boolean, _

ByVal pdOverallLen As Double, _

ByVal plRow As Long, _

ByVal piPsCurrLen As Integer, _

ByVal piPsPercent As Integer, _

ByRef psPercent As String) _

As Boolean

'*****************************************************

'28Jul2003 sc

'Description:

' Convert a length to a percentage based on the overall length.

' Used for calculating percent recovery, solid core recovery, and RQD.

'Input:

' pbNoOverallLen: True if no overall length supplied.

' pdOverallLen: Overall length.

' plRow: Current row in the array being calculated.

' piPsCurrLen: Position in the array of the length that is to

' be converted to a percentage.

' piPsPercent: Position in the array where the percentage is to

' be stored.

'Output:

' psPercent: Final percentage value as a string

' Final percentage is also stored in module level data array.

'Returns:

' True if error was encountered, False otherwise.

'*****************************************************

Dim iPercent As Integer

Dim sLen As String

'-----------------

PercentFromLengthFnB = False

psPercent = ""

sLen = gsDataA(piPsCurrLen, plRow)

If Len(sLen) = 0 Then

Exit Function 'Nothing to do

End If

Page 164: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 163 —

PercentFromLengthFnB = True

With gINTRules.GridData

If pbNoOverallLen Then

.ErrorCol = piPsCurrLen

.ErrorRow = plRow

gINTRules.ErrorMessage = _

"Overall Length is required to calculate percentage."

Exit Function

End If

iPercent = CInt(100 * CDbl(sLen) / pdOverallLen)

If iPercent > 100 Then

.ErrorCol = piPsCurrLen

.ErrorRow = plRow

gINTRules.ErrorMessage = _

"Fractional Length is greater than the Overall Length."

Exit Function

End If

End With

psPercent = CStr(iPercent)

gsDataA(piPsPercent,plRow) = psPercent

PercentFromLengthFnB = False

End Function

The sections that calculate the three percentages now become:

'Calculate recovery percentage from recovery length

If PercentFromLengthFnB(bNoSampleLen, _

dSampleLen, _

lRow, _

iPsRecLen, _

iPsRecPC, _

sRec) _

Then

Exit For

End If

Page 165: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 164 —

'Calculate solid core recovery percentage from solid core recovery length

If PercentFromLengthFnB(bNoSampleLen, _

dSampleLen, _

lRow, _

iPsSCRLen, _

iPsSCRPC, _

sSCR) _

Then

Exit For

End If

'Calculate RQD percentage from RQD length

If PercentFromLengthFnB(bNoSampleLen, _

dSampleLen, _

lRow, _

iPsRQDLen, _

iPsRQDPC, _

sRQD) _

Then

Exit For

End If

The above also returns the calculated results (sRec, sSCR, and sRQD) so the following lines in the main procedure:

sRec = gsDataA(iPsRecPC, lRow)

sSCR = gsDataA(iPsSCRPC, lRow)

sRQD = gsDataA(iPsRQDPC, lRow)

are no longer needed.

Although the above looks like we haven’t saved anything in coding we have actually replaced all of the previous code with, effectively, three lines of code. If you decide to change the way you perform the calculations, with the above approach you only need to change it in one place, the new function, instead of three.

Third Code Iteration: Encapsulating the check against Hole Depth

The last section of the original code checks to ensure that the deepest depth in the data does not exceed the hole depth in the POINT table. You will probably want to run this test in tables other than SAMPLE.

Instead of copying the code in every module where it is needed, we can create a function

Page 166: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 165 —

that can be called from any procedure. Note that this procedure will be changed in the next code sample (CPT) to make it more general. We would put this procedure in the auxillary module (GR001 COMMON PROCEDURES).

Page 167: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 166 —

Public Function HoleDepthCheckFnB(ByVal pdMaxDepth As Double, _

ByVal piPsDepth As Integer, _

ByVal plRowDeepestDepth As Long) _

As Boolean

'Purpose:

' Checks the deepest data depth in a table that is a direct child of

' POINT, for a particular borehole does not exceed the hole depth

' specified for the borehole in the POINT table. If the hole depth

' is exceeded, user has the choice of correcting the data or replacing

' the HoleDepth in the POINT table with the deepest depth in the

' current data.

'Input:

' pdMaxDepth: The maximum depth in the data.

' piPsDepth: Position in the data array of the Depth data.

' plRowDeepestDepth: Row number containing the deepest depth.

'Output:

' None. The passed in data are not modified by this procedure.

' User can update the HoleDepth in the POINT table as well.

'Returns:

' True if error was encountered, False otherwise.

'*****************************************************

Dim dHoleDepth As Double

'-----------------------

HoleDepthCheckFnB = False

With gINTRules.GridData

dHoleDepth = CDbl(.ParentRecord.Fields(gs_HoleDepth).Value)

If pdMaxDepth > dHoleDepth Then

Begin Dialog UserDialog 400,119,"Data Depths" ' %GRID:10,7,1,1

OKButton 170,91,80,21

TextBox 20,7,370,42,.txtMessage,1

CheckBox 20,63,370,14, _

"Mark here to change the hole depth to the max depth", _

.chkChangeDepth

End Dialog

Dim dlgHoleDepth As UserDialog

Page 168: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 167 —

dlgHoleDepth.txtMessage = _

"The maximum data depth (" & CStr(pdMaxDepth) & ") " & _

"is greater than the hole depth " & _

"(" & CStr(dHoleDepth) & ")."

Dialog dlgHoleDepth

If dlgHoleDepth.chkChangeDepth Then

'User marked the check box.

'Change the POINT HoleDepth to the deepest depth in these data.

With .ParentRecord

.Edit

.Fields(gs_HoleDepth).Value = pdMaxDepth

.Update

End With

Else

'User did not mark the check box.

'Abort the save and return focus to the row

'with the deepest depth.

'No message needs to be passed back.

.ErrorCol = piPsDepth

.ErrorRow = plRowDeepestDepth

HoleDepthCheckFnB = True

End If

End If

End With

End Function

One other change was made in this iteration. The "HoleDepth" literal was replaced with a global constant gs_HoleDepth. This is good practice. Avoid literal values where possible (see the NAMING CONVENTIONS AND PROGRAMMING STYLE section). This is In the Declarations section of the auxillary module (GR001 COMMON PROCEDURES):

Private Const gs_HoleDepth As String = "HoleDepth"

The code in the calling procedure now becomes:

'Make sure the deepest depth in the data is

'less than or equal to the hole depth.

If HoleDepthCheckFnB(dMaxDepth, iPsDepth, lRowDeepestDepth) Then

Exit Sub

Page 169: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 168 —

End If

End With

End Sub

You may wonder why we need the Exit Sub when the next thing that will be done is to exit. It isn’t necessary, we could write it as:

HoleDepthCheckFnB dMaxDepth, iPsDepth, lRowDeepestDepth

End With

End Sub

In this case we don’t care about the return value since we are going to exit anyway. Doing it this way is tempting. Don’t do it! What if you later add some new code after this call? So now the HoleDepthCheckFnB is not the last item in the procedure and you don’t want to go into the new code if an error occurred in that call. So it is a good practice to maintain the original construction with the Exit Sub even if it looks unnecessary.

Hooking the code to the Save Event

While in the SAMPLE table, select the Tables Properties menu item, move to “gINT Rules” tab and click the browse button right of the “gINT Rules Procedure on Save” property. Click on “GR001” and then select “Sample” and click OK:

Whenever a save occurs in the SAMPLE table, this procedure will be called.

Page 170: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 169 —

CPT Data

Overview

You have two tables, CPT DETAILS and CPT READINGS set up as a split screen:

CPT DETAILS (captioned above as just "CPT") is a PointID table which is a one-to-one child of the POINT table. CPT READINGS, is a one-to-many child of CPT DETAILS. The Friction Ratio field in the child is a read-only field that will be calculated from the sleeve friction and tip resistance.

The Max Sleeve Friction, Max Tip Resistance, and Max Friction Ratio fields in the parent are also read-only and will be populated by the code in the child table.

We wish to do the following:

• Calculate the friction ratio for each CPT READINGS record.

• Check that the CPT READINGS data are not deeper than the hole depth. If so, ask if the hole depth should be changed to the deepest CPT depth and, if so, change it.

Page 171: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 170 —

• Determine the maximums for the friction, resistance, and ratio and poke these values into the appropriate fields in the parent table.

Code

In the GR001 COMMON PROCEDURES module we will add a new function:

Public Function MaxValFnD(ByVal pdX As Double, _

ByVal pdY As Double) _

As Double

'*****************************************************

'07Aug2006 sc

'Description:

' Determines the maximum of two double precision numbers.

'Input:

' pdX: First number.

' pdY: Second number.

'Output:

' None

'Returns:

' Maximum of first and second numbers.

'*****************************************************

Dim dMax As Double

'-----------------

If pdX > pdY Then

dMax = pdX

Else

dMax = pdY

End If

MaxValFnD = dMax

End Function

This will allow us to easily determine maximums on the Sleeve Friction, Tip Resistance, and Friction Ratio.

Page 172: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 171 —

Public Sub CPTReadings()

'*****************************************************

'28Jul2003 sc

'Description:

'1. Calculate the friction ratio for each CPT READINGS record.

'2. Check that the CPT READINGS data are not deeper than the hole depth.

' If so, ask if the hole depth should be changed to the deepest CPT

' depth and, if so, change it.

'3. Determine the maximums for the friction, resistance, and ratio and

' poke these values into the appropriate fields in the parent table.

'Input, Output:

' None, uses global array to pass data and the gINTRules object

'*****************************************************

Const s_Field_FrictionRatio As String = "Friction Ratio"

Const s_Field_SleeveFriction As String = "Sleeve Friction"

Const s_Field_TipResistance As String = "Tip Resistance"

Const s_Field_MaxFrictionRatio As String = "Max Friction Ratio"

Const s_Field_MaxSleeveFriction As String = "Max Sleeve Friction"

Const s_Field_MaxTipResistance As String = "Max Tip Resistance"

Dim bClearParent As Boolean

Dim dFriction As Double

Dim dMaxDepth As Double

Dim dMaxFriction As Double

Dim dMaxRatio As Double

Dim dMaxTip As Double

Dim dRatio As Double

Dim dTip As Double

Dim iPsDepth As Integer

Dim iPsFriction As Integer

Dim iPsRatio As Integer

Dim iPsTip As Integer

Dim lRow As Long

'-----------------------

Page 173: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 172 —

If glNumRows = 0 Then

bClearParent = True

GoTo ExitHere

Else

bClearParent = False

End If

'Obtain pointers to the field data within the data array.

If InitFieldsFnB(gs_Depth, iPsDepth, _

s_Field_SleeveFriction, iPsFriction, _

s_Field_TipResistance, iPsTip, _

s_Field_FrictionRatio, iPsRatio) _

Then

'One or more of the required fields missing from the table.

Exit Sub

End If

dMaxFriction = -9E99

dMaxTip = -9E99

dMaxRatio = -9E99

'Check each row. Rows and columns are 1-based.

For lRow = 1 To glNumRows

'Calculate Friction Ratio for each record.

dFriction = CDbl(gsDataA(iPsFriction,lRow))

dTip = CDbl(gsDataA(iPsTip,lRow))

dRatio = CDbl(Format$(100 * dFriction / dTip, "0.0"))

gsDataA(iPsRatio, lRow) = CStr(dRatio)

dMaxFriction = MaxValFnD(dMaxFriction, dFriction)

dMaxTip = MaxValFnD(dMaxTip, dTip)

dMaxRatio = MaxValFnD(dMaxRatio, dRatio)

Next lRow

'Make sure the deepest depth in the data is

'less than or equal to the hole depth.

'gINT passes in the data array sorted by depth so the

'maximum depth is in the last row.

Page 174: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 173 —

dMaxDepth = CDbl(gsDataA(iPsDepth, glNumRows))

If HoleDepthCheckFnB(dMaxDepth, iPsDepth, glNumRows) Then

Exit Sub

End If

ExitHere:

'Stuff the Max fields into the parent record.

With gINTRules.GridData.ParentRecord

.Edit

If bClearParent Then

.Fields(s_Field_MaxSleeveFriction).Value = Null

.Fields(s_Field_MaxTipResistance).Value = Null

.Fields(s_Field_MaxFrictionRatio).Value = Null

Else

.Fields(s_Field_MaxSleeveFriction).Value = dMaxFriction

.Fields(s_Field_MaxTipResistance).Value = dMaxTip

.Fields(s_Field_MaxFrictionRatio).Value = dMaxRatio

End If

.Update

End With

'Forces the resaving of all records,

'even those not changed by the user.

gINTRules.GridData.ForceSave = True

'Need this line to see the changes to the parent record.

gINTRules.GridData.RefreshParent = True

End Sub

Note the “.Value” at the end of the “.Fields” assignments above. “.Value” value is the default property and could be left off. However, .NET does not recognize default properties and it would have to be added if the code is ported to .NET. In any case, it is good programming practice not to rely on default properties, that is, always explicitly reference the property.

A number of new concepts are introduced in this procedure:

Page 175: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 174 —

Early Exit for no data condition:

At the top of the procedure is:

If glNumRows = 0 Then

bClearParent = True

GoTo ExitHere

Else

bClearParent = False

End If

That is, if there are no data, specify that the parent calculated fields are to be cleared and then jump to the exit code. With the sample table procedure, it didn’t matter if there were no rows with data, nothing harmful would occur. In this procedure, we are stuffing the maximum values of the three data columns in the parent record. Without the above test, or something like it, the code would stuff those parent fields with the initialization values (-9E99 = -9x1099).

Note that to clear the parent record fields you must set them to “Null” because they are numeric fields. If they were text fields you would set them to empty (“”).

Updated HoleDepthCheckFnB Procedure

The original HoleDepthCheckFnB procedure assumed that the hole depth was stored in the parent table. That is not the case with the CPT READINGS table. The parent is CPT DETAILS. HoleDepth is stored in the POINT table. We have rewritten the procedure to be more general. Originally the hole depth was determined from:

dHoleDepth = CDbl(.ParentRecord.Fields(gs_HoleDepth).Value)

Now it is done with a more general approach:

With gINTRules.GridData

sSql = "Select " & gs_HoleDepth & _

" From POINT" & _

" Where " & gs_PointID & " = '" & _

.ForeignKeyValues(gs_PointID) & "'"

Set dsHoleDepth = _

gINTRules.CurrentProject.OpenRecordset(sSql,dbOpenDynaset)

dHoleDepth = CDbl(dsHoleDepth(gs_HoleDepth).Value)

dsHoleDepth is a recordset object. If the user selects to update the hole depth, that is now done with:

With dsHoleDepth

.Edit

dsHoleDepth(gs_HoleDepth).Value = pdMaxDepth

Page 176: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 175 —

.Update

End With

At the end of the procedure, we need to clean up with:

dsHoleDepth.Close

Set dsHoleDepth = Nothing

One special note: The two instances of:

dsHoleDepth(gs_HoleDepth).Value

could be written as:

dsHoleDepth(gs_HoleDepth)

The “Value” property of this object is the “default” and can be left off. However, .NET does not recognize default properties and will require explicit reference to “Value”. If you port your code to .NET (see Converting to a DLL) the “.Value” will be required. In any case, it is considered good programming practice to always explicitly reference the property you are addressing and not to relie on defaults.

Hooking the code to the Save Event

While in the CPT READINGS table (put focus in the lower grid), select the Tables Properties menu item, move to “gINT Rules” tab and click the browse button right of the “gINT Rules Procedure on Save” property. Click on “GR001” and then select “CPTReadings” and click OK:

Whenever a save occurs in the CPT READINGS table, this procedure will be called.

Page 177: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 176 —

Lithology Data

Overview

You define layers with a top and bottom depth and a graphic as below:

The data at 3 and 16 feet are detail descriptions, the rest layer descriptions. For layer descriptions, you want to be able to skip typing in the Bottom values and have a procedure that inserts them for you. See the "Purpose" section below for details of the algorithm.

In addition, you want to run the maximum depth check as in the other two procedures above. There are no new concepts with this code. See the comments embedded in the code for details of the operation.

Code Public Sub Lithology

'*****************************************************

'29Jul2003 sc

'Description:

'1. Inserts Bottom depth values on records where there is a

' Graphic (layer records).

' Does this by using the Depth value on the next record that

' has a Graphic value (next layer record) for the Bottom depth.

' For the bottom-most layer it uses the Hole Depth for the

' Bottom value. Only does this where there is no Bottom value.

' Data array is sorted when passed into this procedure.

'2. Check that the data are not deeper than the hole depth.

' If so, ask if the hole depth should be changed to the current

Page 178: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 177 —

' deepest layer and, if so, change it.

'Input, Output:

' None, uses global array to pass data and the gINTRules object

'*****************************************************

Const s_Field_Bottom As String = "Bottom"

Const s_Field_Graphic As String = "Graphic"

Dim dDepth As Double

Dim dMaxDepth As Double

Dim iPsDepth As Integer

Dim iPsBottom As Integer

Dim iPsGraphic As Integer

Dim lRow As Long

Dim lRow2 As Long

Dim lRowDeepestDepth As Long

Dim sHoleDepth As String

'------------------------

'Obtain pointers to the field data within the data array.

If InitFieldsFnB(gs_Depth, iPsDepth, _

s_Field_Bottom, iPsBottom, _

s_Field_Graphic, iPsGraphic) _

Then

'One or more of the required fields missing from the table.

Exit Sub

End If

With gINTRules.GridData

'Forces the resaving of all records, even those not changed

'by the user.

.ForceSave = True

sHoleDepth = CStr(.ParentRecord.Fields(gs_HoleDepth).Value)

dMaxDepth = -9E99

Page 179: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 178 —

'Check each row. Rows and columns are 1-based.

For lRow = 1 To glNumRows

If Len(gsDataA(iPsBottom,lRow)) > 0 Then

dDepth = CDbl(gsDataA(iPsBottom,lRow))

If dDepth > dMaxDepth Then

dMaxDepth = dDepth

lRowDeepestDepth = lRow

End If

Else

dDepth=CDbl(gsDataA(iPsDepth,lRow))

If dDepth > dMaxDepth Then

dMaxDepth = dDepth

lRowDeepestDepth = lRow

End If

If Len(gsDataA(iPsGraphic,lRow)) > 0 Then

'No need to check max depth against the assigned bottom depths.

'They will either be taken from a Depth value (checked above)

'or from the Hole Depth, which is never greater than itself.

'On a layer record.

'Find the next layer record.

For lRow2 = lRow + 1 To glNumRows

If Len(gsDataA(iPsGraphic,lRow2)) > 0 Then

'Fill Bottom value with Depth value of the

'next layer record.

gsDataA(iPsBottom,lRow) = gsDataA(iPsDepth,lRow2)

Exit For

End If

Next lRow2

If Len(gsDataA(iPsBottom,lRow)) = 0 Then

'Found no layer records after the current record.

'Fill the Bottom with the Hole Depth.

gsDataA(iPsBottom,lRow) = sHoleDepth

End If

End If

Page 180: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 179 —

End If

Next lRow

'Make sure the deepest depth in the data is

'less than or equal to the hole depth.

'Deepest depth could be in the Depth or Bottom fields.

If HoleDepthCheckFnB(dMaxDepth, iPsDepth, lRowDeepestDepth) Then

Exit Sub

End If

End With

End Sub

Hooking the code to the Save Event

While in the LITHOLOGY table, select the Tables Properties menu item, move to “gINT Rules” tab and click the browse button right of the “gINT Rules Procedure on Save” property. Click on “GR001” and then select “Lithology” and click OK:

Whenever a save occurs in the LITHOLOGY table, this procedure will be called.

Page 181: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 180 —

Chemistry Data

Overview

We have set up a table to record chemistry data during an investigation:

The Chemical field is a lookup to a library table:

Page 182: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 181 —

The Unit and Exceeds Spec fields in the Input table are read only and are filled in by the code outlined below. The Unit is obtained by looking up the Unit associated with the Chemical in the GR001 CHEMICALS library table.

The Result is compared to the Exceedence Limit in the library table to determine whether or not to mark the Exceeds Spec check box. See the "Purpose" header of the code below for further details. With this procedure we have added a new, general purpose procedure, AddToList. We would add this to the auxillary module (GR001 COMMON PROCEDURES). The description is in the "Purpose" header.

Public Sub AddToList(ByVal psListSeparator As String, _

ByVal psNewListElement As String, _

ByRef psList As String)

'*****************************************************

'Description:

' Adds a new element to a separated text string list.

' If the item already exists, it is not added.

' Procedure is case insensitive, that is, "AbC", "abc", and "ABC"

' are all considered to be the same element.

'Input:

' psListSeparator: The text that separates the elements.

' psNewListElement: New element to be added.

'Output:

' psList: The updated list.

'*****************************************************

Page 183: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 182 —

'Don't add empty values to list

If Len(psNewListElement) = 0 Then

Exit Sub

End If

If Len(psList) > 0 Then

If InStr(psListSeparator & _

UCase$(psList) & _

psListSeparator, _

psListSeparator & _

UCase$(psNewListElement) & _

psListSeparator) > 0 _

Then

'Item already in list. Do nothing.

Else

psList = psList & psListSeparator & psNewListElement

End If

Else

'New list

psList = psNewListElement

End If

End Sub

Code Public Sub Chemistry

'*****************************************************

'06Aug2003 sc

'Description:

'1. Insert units into the read-only Units column for each chemical

'2. Determine if the chemical result is greater than the Exceedence Limit

' for that chemical. If the result is ">###", the value after the ">"

' is compared to the Exceedence Limit. All other non-numeric values

' are treated as 0, for example, "<###" or "ND".

'3. Check that the data are not deeper than the hole depth.

' If so, ask if the hole depth should be changed to the current deepest

' depth and, if so, change it.

'Units and Exceedence Limits read from the Library Table GR 001

Page 184: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 183 —

CHEMICALS.

'Input, Output:

' None, uses global array to pass data and the gINTRules object

'*****************************************************

Const s_Field_Chemical As String = "Chemical"

Const s_Field_ExceedsSpec As String = "Exceeds Spec"

Const s_Field_Result As String = "Result"

Const s_Field_Unit As String = "Unit"

Const s_LibTable As String = "GR001 CHEMICALS"

Const s_LibFieldUnit As String = "Unit"

Const s_LibFieldLimit As String = "Exceedence Limit"

Const s_NotFoundListSep As String = ", "

Dim bExceedsSpec As Boolean

Dim bUnitFoundForCurrChemical As Boolean

Dim bNoDataFoundInLibTable As Boolean

Dim dMaxDepth As Double

Dim iPsChemical As Integer

Dim iPsDepth As Integer

Dim iPsExceedsLimit As Integer

Dim iPsResult As Integer

Dim iPsUnit As Integer

Dim lRow As Long

Dim sChemical As String

Dim sChemicalsNotFound As String

Dim sExceedenceLimit As String

Dim sResult As String

Dim sUnit As String

'------------------------

'Obtain pointers to the field data within the data array.

If InitFieldsFnB(gs_Depth, iPsDepth, _

s_Field_Chemical, iPsChemical, _

Page 185: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 184 —

s_Field_Result, iPsResult, _

s_Field_Unit, iPsUnit, _

s_Field_ExceedsSpec, iPsExceedsLimit) _

Then

'One or more of the required fields missing from the table.

Exit Sub

End If

With gINTRules.GridData

'Forces the resaving of all records, even those not changed

'by the user.

.ForceSave = True

sChemicalsNotFound = ""

bNoDataFoundInLibTable = True

'Check each row. Rows and columns are 1-based.

For lRow=1 To glNumRows

sChemical = gsDataA(iPsChemical,lRow)

If gINTRules.LibraryTableDataGetFnB(s_LibTable, _

sChemical, _

s_LibFieldUnit, _

sUnit) _

Then

'Could not access the field in the library table.

'Either the chemical is not in the library table,

'the units field is not in that table, or

'the table itself does not exist.

Call AddToList(s_NotFoundListSep, _

sChemical, _

sChemicalsNotFound)

sUnit=""

bUnitFoundForCurrChemical = False

Else

bUnitFoundForCurrChemical = True

bNoDataFoundInLibTable = False

End If

gsDataA(iPsUnit,lRow) = sUnit

Page 186: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 185 —

If gINTRules.LibraryTableDataGetFnB(s_LibTable, _

sChemical, _

s_LibFieldLimit, _

sExceedenceLimit) _

Then

'Could not access the field in the library table.

'Either the chemical is not in the library table,

'the units field is not in that table, or

'the table itself does not exist.

If bUnitFoundForCurrChemical Then

'Don't add the chemical to the list if the unit

'was not found. In that case, the chemical was

'added above.

Call AddToList(s_NotFoundListSep, _

sChemical, _

sChemicalsNotFound)

bExceedsSpec = False

End If

Else

If Len(sExceedenceLimit) > 0 Then

sResult = gsDataA(iPsResult,lRow)

If Left$(sResult,1) = ">" Then

sResult = Mid$(sResult,2)

End If

bExceedsSpec = Val(sResult) > Val(sExceedenceLimit)

Else

bExceedsSpec = False

End If

bNoDataFoundInLibTable = False

End If

gsDataA(iPsExceedsLimit,lRow) = CStr(CInt(bExceedsSpec))

Next lRow

If .ErrorCol > 0 Then

Page 187: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 186 —

Exit Sub 'Error found above. Stop processing.

End If

If bNoDataFoundInLibTable Then

MsgBox "Could not find information on any of the chemicals " & _

"in the " & s_LibTable & " library table. " & _

"Either:" & vbCrLf & _

"1. The chemicals are not in the table." & vbCrLf & _

"2. The " & s_LibFieldUnit & " and/or " & _

s_LibFieldLimit & " fields do not exist " & _

"in the table." & vbCrLf & _

"3. The table does not exist.", _

vbOkOnly + vbExclamation, s_LibTable

ElseIf Len(sChemicalsNotFound) > 0 Then

MsgBox "Could not find information on the following chemicals " & _

"in the " & s_LibTable & " library table." & vbCrLf & _

sChemicalsNotFound & vbCrLf & _

"Either:" & vbCrLf & _

"1. The chemicals are not in the table." & vbCrLf & _

"2. The " & s_LibFieldUnit & " and/or " & _

s_LibFieldLimit & " fields do not exist in the table.", _

vbOkOnly + vbExclamation, s_LibTable

End If

'Make sure the deepest depth in the data is

'less than or equal to the hole depth.

'gINT passes in the data array sorted by depth so the

'maximum depth is in the last row.

dMaxDepth = CDbl(gsDataA(iPsDepth, glNumRows))

If HoleDepthCheckFnB(dMaxDepth, iPsDepth, glNumRows) Then

Exit Sub

End If

End With

End Sub

Page 188: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 187 —

Hooking the code to the Save Event

While in the CHEMISTRY table, select the Tables Properties menu item, move to “gINT Rules” tab and click the browse button right of the “gINT Rules Procedure on Save” property. Click on “GR001” and then select “Chemistry” and click OK:

Whenever a save occurs in the CHEMISTRY table, this procedure will be called.

Creating an Auxiliary Module

We have created the three general purpose procedures AddToList, HoleDepthCheckFnB, and PercentFromLengthFnB. You might wish to use these procedures in other modules. Further, there is a DLL function declaration and some module level variables and constants that could be used by other modules as well. Instead of copying these items into new modules, a very bad practice since it leads to redundant code, create a new module to store these globally required items. We have done this in GR001 COMMON PROCEDURES.

See Using Multiple Modules for details on how this is done. We have created a COMMON PROCEDURES module to store these procedures. The final code sample can be seen in the file from our Free Reports Web page (www.gintsoftware.com/support_gintrules.html).

What To Do if Fields Do Not Exist

In the initialization code of all the table save procedures we created above, we determined the position in the data array of each of the fields from which we need to retrieve data. This method allows the fields to be in any order. What happens if the user removed one or more of the fields?

We probably want to abort further operations, tell the user that calculations couldn't be performed because fields are missing, and allow the save to continue but without any manipulation by the code.

Page 189: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 188 —

First we need to determine that a field is missing. We could do the following:

iPsSCRLen=.FieldCol("SCR Length")

If iPsSCRLen = 0 then

MsgBox "Field " & "SCR Length is missing. " & _

"Cannot perform the calculations.", ,"Sample Data Save"

Exit Sub

End If

This is way too much code for each procedure, especially since the number of fields could be quite large. Instead, we have created a procedure that can perform the initialization, checks, and message, if necessary. This function is in the COMMON PROCEDURES module and is shown in the The Basic Process section.

Following is the code in our SAMPLE table calculations that uses the new function:

If InitFieldsFnB("Depth", iPsDepth, _

"Length", iPsSampleLen, _

"Rec Length", iPsRecLen, _

"Rec", iPsRecPC, _

"SCR Length", iPsSCRLen, _

"SCR", iPsSCRPC, _

"RQD Length", iPsRQDLen, _

"RQD", iPsRQDPC) _

Then

Exit Sub

End If

Initializing Common Variables

Whenever possible, it is best to initialize variables that could be used by multiple procedures in one central location. The obvious place in gINT Rules is the Sub Main procedure. In the above examples we are doing that with the grid data:

With gINTRules

gsDataA = .GridData.DataArray

As it was declared Public, gsDataA is now available to all procedures in all modules and saves the redundant code in each procedure to initialize it.

Another commonly used variable in our code samples is the number of records in the data array which is UBound(gsDataA, 2). Instead of repeating this function in all procedures, we can declare glNumRows as a public variable in the Declarations section of the COMMON

Page 190: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 189 —

PROCEDURES module and initialize it in Sub Main:

With gINTRules

gsDataA = .GridData.DataArray

glNumRows = UBound(gsDataA, 2)

We could have declared the "number of rows" variable private in the main code module since it is only used there at present. Always look for opportunities like these to reduce your coding and maintenance.

Defining Field Variables as Constants

In all the main procedures we have had to access specific fields in the database. Instead of hardcoding their names within the code, it is good practice to declare them as constants in the header of the procedures and then use the constant names instead of the actual names. For example:

Const s_Field_Dia1 As String = "Diameter 1"

Const s_Field_Dia2 As String = "Diameter 2"

Const s_Field_Dia3 As String = "Diameter 3"

Const s_Field_DiamMM As String = "Diameter"

Const s_Field_Ht1 As String = "Height 1"

Const s_Field_Ht2 As String = "Height 2"

Const s_Field_Ht3 As String = "Height 3"

Const s_Field_HtMM As String = "Height"

This does two things for you. First it places all required database fields in one place. You can quickly see what fields are required. Secondly, if a field name changes, you don't have to look for it in the code and retype it in every location where it is used. Just change it in this one location. This is easier and avoids typographical errors.

The const type declaration (“As String” in the above example) is not required but is considered good programming practice.

If you have fields that are needed in multiple procedures, declare those constants in either the module Declarations section as "Private" (available to all procedures in the module) or in the auxillary module Declarations section as "Public" (available to all procedures in all modules that include the auxillary module).

Page 191: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 190 —

Converting to a DLL

Introduction

After you have completed your programming project in gINT Rules you want to have other people use it. Currently there is no security on your code, that is, anyone can access your code, make changes, and add to it. The only exception to this is if the people that will be using the code are running the gINT Logs program. They will not have access to the gINT Rules editor. They can only run your code.

If only a small group will be using the code, security may not be an issue. If you are in a corporate environment and will be distributing the modules to many offices, or you are a commercial developer that will be selling your program to gINT users, you definitely need security.

The best way is to port your code, or write it from the beginning, in an external program and then link that program into gINT Rules. You would be creating a DLL (dynamic link library) and are therefore free to program in whatever environment you are most comfortable. Any programming language that can create a 32-bit Windows DLL that is COM compatible will work.

In this section we will walk you through the process of porting the code we have created above in gINT Rules to a Microsoft Visual Basic DLL. If you want to work through the process, you can download GR001 from the Web site. It will be needed in porting the code to the DLL projects.

We will use Visual Basic .NET 2005. The process will be conceptually the same using other languages but the implementation details will be different. Please refer to your language documentation for specifics.

The final DLL with source code is located under the gINT Rules page on our Web site (www.gintsoftware.com/support_gintrules.html).

Process Summary

The following summary will mean little to you if you have never created and implemented DLL programs. It is meant as a brief overview of the process, described in detail in the following sections, and as a quick reference when you constructing your own DLLs.

• Create a VB.NET DLL (Class Library) project.

• Except for the name property, leave the properties of the class module supplied by .NET as-is.

Page 192: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 191 —

• Create a new class module that will have a "Private" instancing property. In this class you will store all your main procedures. They must be Public. If porting from gINT Rules, remove and rewrite any code that is gINT Rules specific, that is, code that is not recognized by .NET.

• Assign all required external references (Project Properties References menu option). You must include the gINT object.

• Create as many additional modules as needed to store auxiliary procedures. If porting from gINT Rules, remove and rewrite any code that is gINT Rules specific, that is, code that is not recognized by .NET.

• In the Declaration section of a module (not any of the classes or forms), insert “Public gINTRules As gINT.clsGintRulesData".

• In the class module supplied by .NET insert the following: Public Sub AAAA(pgINTRules As gINT.clsGintRulesData)

Dim objBBBB As clsBBBB

'--------------------------------

Set objBBBB = New clsBBBB

Set gINTRules = pgINTRules

With gINTRules.GridData

'Put the grid data into a working string data array.

gsDataA = .DataArray

glNumRows = UBound(gsDataA, 2)

CallByName objBBBB, gINTRules.ProcedureName, VbMethod

.DataArray = gsDataA 'Put the modified data array back into

'the input grid.

'Success is True if there were no errors.

gINTRules.Success = CBool(.ErrorCol = 0)

End With

Set objBBBB = Nothing

End Sub

Where AAAA is the name of your procedure that will be called by gINT Rules and BBBB is the name of the class module that contains your main procedures. Compile the DLL and then copy it to a separate folder. This will be the binary compatibility copy.

Page 193: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 192 —

• In the Project:XXXX Properties dialog box, move to the "Component" tab and set the binary compatibility to the copy created in the previous step. Then recompile the DLL. This process will maintain your DLL GUID.

• In the gINT Rules Code dialog box, create a new module. In the code window select Edit:References and set the reference to the DLL. If it is registered it will show up in the list and you just need to mark it. If not registered browse for the DLL to add it to the list.

• Still in the code window for the new module, insert the following: Sub Main

Dim objCCCC As DDDD.clsEEEE

'--------------------------

Set objCCCC=New DDDD.clsEEEE

objCCCC.AAAA gINTRules

Set objCCCC=Nothing

End Sub

where:

AAAA = The name of the externally public procedure in your DLL (same AAAA as in the example above).

CCCC = A name for the object that will reference the DLL.

DDDD = The name of your DLL.

EEEE = The name of the main class module in the DLL, that is, the one where your externally public procedure (AAAA above) resides.

Change the gINT Rules property for each table that needs to call the DLL. Click the browse button right of the property. Select the new module and select the "Main" procedure (the only choice) and click OK. In the property field change "Main" to the procedure name in the DLL that is to be called.

Page 194: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 193 —

Building a VB.NET DLL

Setting up the VB.NET Project

Start a new project and select the Class Library option:

We are calling this project “GR001_NET” to match the gINT Rules sample project name on our Web site and to distinguish it from the VB6 DLL we created in an earlier version of gINT. Set the Name to your preference and click the OK button.

Highlight the project name in the Solution Explorer:

and then select the File:Save menu item (Ctrl+S) and save to the folder of your choice.

Use the Solution Explorer to add the references that will be needed. Right click on the “References” folder and select Add Reference. Alternatively, use the Project Properties References menu option. Under the “.NET” tab, select

Page 195: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 194 —

“Microsoft.BisualBasic.Compatibility” component.

This library allows you to maintain your original coding in gINT Rules with minimal changes. For example, the “Mid$” and similar functions are replaced by more powerful .NET constructs. Therefore, you could skip this step but that would require more extensive reworking of the original gINT Rules code since .NET would not recognize these functions. Click Ok.

Page 196: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 195 —

Right click on the “References” folder and select the “Add Reference” option once more. Move to the “COM” tab and select “gINT” and then click Ok.

We need this reference to gINT to access the gINT Rules object, its properties, methods, and sub-objects.

The References folder should now contain the gINT COM object (DAO and gINT) and VB Compatibility:

Page 197: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 196 —

Still in the Solution Explorer window, right click on the project folder (GR001_NET) and select the “Properties” option:

Page 198: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 197 —

Now click on the “References” tab:

In the lower pane, mark the “dao” and “Microsoft.VisualBasic.Compatibility” check box.

Page 199: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 198 —

Now move to the “Compile” tab:

Mark “Register for COM interop” check box at the bottom of the tab. This enables interacting with a “COM” (Component Object Model) program such as gINT.

Now close the properties window by clicking on the “X” at the upper right.

Page 200: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 199 —

Back in the Solution Explorer window, rename the default “Class1.vb” to “clsGR001_NET.vb”.

This class will be the interface to gINT and will act as the equivalent of the Sub Main procedure in gINT Rules and will contain the Sub Main code (with some modifications). Note that in the code window, the class declaration changed automatically from “Class1” to “clsGR001_NET” after the module was renamed.

Page 201: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 200 —

Three new modules need to be added. In the Solution Explorer, right click on “GR001_NET”, select the “Add” menu and then “Class”.

Change the “Name” from “Class1.vb” to “clsInputChecks.vb” and click the Add button. This module will eventually contain all the procedures that were in the GR001 module in the gINT Rules project except for Sub Main.

Page 202: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 201 —

Right click once more on “GR001_NET” in the Solution Explorer, select the “Add” menu and the “Module”. It is VERY important that this be a module, not a class. Overwise the public declarations will not be recognized outside of the module.

Name it CommonProcedures.vb. We will be storing all procedures in the gINT Rules GR001 COMMON PROCEDURES module in this module.

Page 203: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 202 —

Once more in the “Add” menu but this time select “Windows Form”.

Name it frmHoleDepthWarning.vb. This will be the hole depth warning dialog.

The resulting Solution Explorer should look like:

Page 204: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 203 —

Inserting the gINT Rules Code to the .NET Project

In gINT switch your library to GR001.GLB, move to Input, and then select the gINT Rules gINT Rules Code menu item. Then select the GR001 module and move into the Code tab.

Page 205: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 204 —

Select all of the code for Sub Main and copy/paste it to the new clsGR001_NET.vb class module that you created as part of the .Net project above.

Now change the first line from Sub Main so that it reads

Public Sub InputChecks(ByRef pgINTRules As gINT.clsGintRulesData)

We will be coming back to this. There will be other changes to this procedure but first we will import the rest of the code.

Copy all procedures in module GR001, except for Sub Main and the Declarations section, into clsInputChecks.

Except for the “Option Explicit” line, copy all the code from the GR001 COMMON PROCEDURES module to the new CommonProcedures module.

In the declarations section of CommonProcedures add a comma to the gsDataA declaration:

Public gsDataA(,) As String

Unlike previous version of VB, VB.NET requires declaration of the number of dimensions of the array (two in this case). The comma indicates this.

Finally, add the following in the declaration section:

Public gINTRules As gINT.clsGintRulesData

The Declaration Section should now look like:

Module CommonProcedures

'Commonly used field names

Public Const gs_Depth As String = "Depth"

Page 206: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 205 —

Public Const gs_HoleDepth As String = "HoleDepth"

Public Const gs_PointID As String = "PointID"

Public glNumRows As Long

Public gsDataA(,) As String

Public gINTRules As gINT.clsGintRulesData

Now go back to clsGR001_NET.vb and revise Public Sub InputChecks. First add the following code under the Sub declaration:

Dim objInputChecks As New clsInputChecks

gINTRules = pgINTRules

Change the assignment of gsDataA to read:

gsDataA = VB6.CopyArray(.DataArray)

Change the CallByName call to read:

CallByName(objInputChecks, gINTRules.ProcedureName, _

CallType.Method)

Change the assignment of .DataArray to read: .DataArray = VB6.CopyArray(gsDataA)

The resulting code should be: Public Class clsGR001

Public Sub InputChecks(ByRef pgINTRules As gINT.clsGintRulesData)

Dim objInputChecks As New clsInputChecks

'---------------------------------------

gINTRules = pgINTRules

With gINTRules.GridData

'Put the grid data into a working string data array.

gsDataA = VB6.CopyArray(.DataArray)

glNumRows = UBound(gsDataA, 2)

CallByName(objInputChecks, gINTRules.ProcedureName, _

CallType.Method)

'Put the modified data array back into the input grid.

.DataArray = VB6.CopyArray(gsDataA)

'Success is True if there were no errors.

gINTRules.Success = CBool(.ErrorCol = 0)

Page 207: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 206 —

End With

End Sub

End Class

Rewriting the InitFieldsFnB function

The InitFieldsFnB function in CommonProcedures requires significant changes. .Net does not allow a parameter array passed by reference. Note that the environment automatically changed the “ByRef” to “ByVal”. Also, Variant data types are not supported in .NET and the environment automatically changed “As Variant” to “As Object”.

The original code required that the parameter array be modified and passed back. One way around this is by changing the function argument from a parameter array to just an Object array which will be passed ByRef. The declaration will then be:

Public Function InitFieldsFnB(ByRef pvFieldsV() As Object) _

As Boolean

Replace Function Input/Output comments with: 'Input:

' pvFieldsV(): Field names.

'Output:

' pvFieldsV(): Field array positions.

‘ Replaces the input names.

The For…Next loop needs to be changed to: For iInd = 0 To UBound(pvFieldsV)

iPsField = .FieldCol(CStr(pvFieldsV(iInd)))

If iPsField > 0 Then

pvFieldsV(iInd) = iPsField

Else

sMissingFields = sMissingFields & _

s_FieldSeparator & _

CStr(pvFieldsV(iInd))

End If

Next iInd

All of the code that uses InitFieldsFnB must also be changed. All changes are in clsInputChecks. First move to Sub Sample. Replace:

If InitFieldsFnB(gs_Depth, iPsDepth, _

s_Field_Length, iPsSampleLen, _

s_Field_RecLength, iPsRecLen, _

Page 208: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 207 —

s_Field_Rec, iPsRecPC, _

s_Field_SCRLength, iPsSCRLen, _

s_Field_SCR, iPsSCRPC, _

s_Field_RQDLength, iPsRQDLen, _

s_Field_RQD, iPsRQDPC) _

Then

'One or more of the required fields missing from the table.

Exit Sub

End If

with: Dim vObjA() As Object = {gs_Depth, _

s_Field_Length, _

s_Field_RecLength, _

s_Field_Rec, _

s_Field_SCRLength, _

s_Field_SCR, _

s_Field_RQDLength, _

s_Field_RQD}

'Obtain pointers to the field data within the data array.

If InitFieldsFnB(vObjA) Then

'One or more of the required fields missing from the table.

Exit Sub

End If

iPsDepth = CInt(vObjA(0))

iPsSampleLen = CInt(vObjA(1))

iPsRecLen = CInt(vObjA(2))

iPsRecPC = CInt(vObjA(3))

iPsSCRLen = CInt(vObjA(4))

iPsSCRPC = CInt(vObjA(5))

iPsRQDLen = CInt(vObjA(6))

iPsRQDPC = CInt(vObjA(7))

Page 209: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 208 —

In the CPTReadings procedure, replace: If InitFieldsFnB(gs_Depth, iPsDepth, _

s_Field_SleeveFriction, iPsFriction, _

s_Field_TipResistance, iPsTip, _

s_Field_FrictionRatio, iPsRatio) _

Then

'One or more of the required fields missing from the table.

Exit Sub

End If

with:

Dim vObjA() As Object = {gs_Depth, _

s_Field_SleeveFriction, _

s_Field_TipResistance, _

s_Field_FrictionRatio}

If InitFieldsFnB(vObjA) Then

'One or more of the required fields missing from the table.

Exit Sub

End If

iPsDepth = CInt(vObjA(0))

iPsFriction = CInt(vObjA(1))

iPsTip = CInt(vObjA(2))

iPsRatio = CInt(vObjA(3))

Replace the assignment of dRatio to read: dRatio = CDbl(VB6.Format$(100 * dFriction / dTip, "0.0"))

The Format function is very different in .Net. Alternatively you could change the arguments of the Format function to match .NET requirements.

Moving to the Lithology procedure, replace: If InitFieldsFnB(gs_Depth, iPsDepth, _

s_Field_Bottom, iPsBottom, _

s_Field_Graphic, iPsGraphic) _

Then

'One or more of the required fields missing from the table.

Exit Sub

End If

Page 210: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 209 —

with: Dim vObjA() As Object = {gs_Depth, _

s_Field_Bottom, _

s_Field_Graphic}

'Obtain pointers to the field data within the data array.

If InitFieldsFnB(vObjA) Then

'One or more of the required fields missing from the table.

Exit Sub

End If

iPsDepth = CInt(vObjA(0))

iPsBottom = CInt(vObjA(1))

iPsGraphic = CInt(vObjA(2))

In the Chemistry procedure, replace: If InitFieldsFnB(gs_Depth, iPsDepth, _

s_Field_Chemical, iPsChemical, _

s_Field_Result, iPsResult, _

s_Field_Unit, iPsUnit, _

s_Field_ExceedsSpec, iPsExceedsLimit) _

Then

'One or more of the required fields missing from the table.

Exit Sub

End If

with: Dim vObjA() As Object = {gs_Depth, _

s_Field_Chemical, _

s_Field_Result, _

s_Field_Unit, _

s_Field_ExceedsSpec}

'Obtain pointers to the field data within the data array.

If InitFieldsFnB(vObjA) Then

'One or more of the required fields missing from the table.

Exit Sub

Page 211: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 210 —

End If

iPsDepth = CInt(vObjA(0))

iPsChemical = CInt(vObjA(1))

iPsResult = CInt(vObjA(2))

iPsUnit = CInt(vObjA(3))

iPsExceedsLimit = CInt(vObjA(4))

Rewriting the Hole Depth Warning Dialog

The UserDialog in the original gINT Rules code is specific to the language interpreter used by gINT Rules and is not recognized by .NET. We must create a VB.Net dialog.

In the frmHoleDepthWarning form, insert three controls:

• lblHoleDepthWarning: Label control that shows the warning text. • chkHoleDepthWarning: Checkbox control which the user marks to change the hole

depth. • cmdHoleDepthWarning: Ok command button.

Also change the Text property of the form appropriately.

In the properties window for this form, set the “StartPosition” property to “CenterScreen”.

The code in this form is in the following form procedures:

cmdHoleDepthWarning_Click: Drop down the upper left combo box and select cmdHoleDepthWarning Events. Drop down the upper right combo box and select the Click event. Insert the following comment lines and the one line of code:

'On clicking the Ok button, hide the form to return

'control back to the caller but leave the form active.

'The caller will need to query the state of the

'checkbox and will then unload the form.

Page 212: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 211 —

Me.Hide()

We will now insert a new procedure. Insert the following at the bottom of the code window but above the last "End Class" line:

Private Shared mfrmFormDefInstance As frmHoleDepthWarning

Private Shared mbInitializingDefInstance As Boolean

Public Shared Property DefInstance() _

As frmHoleDepthWarning

Get

If mfrmFormDefInstance Is Nothing OrElse _

mfrmFormDefInstance.IsDisposed _

Then

mbInitializingDefInstance = True

mfrmFormDefInstance = New frmHoleDepthWarning

mbInitializingDefInstance = False

End If

DefInstance = mfrmFormDefInstance

End Get

Set(ByVal pfrmValue As frmHoleDepthWarning)

mfrmFormDefInstance = pfrmValue

End Set

End Property

In the calling procedure (CommonProcedures:HoleDepthCheckFnB), the UserDialog code is replaced with:

Page 213: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 212 —

If pdMaxDepth > dHoleDepth Then

With frmHoleDepthWarning.DefInstance

.lblHoleDepthWarning.Text = _

"The maximum data depth (" & CStr(pdMaxDepth) & ") " & _

"is greater than the hole depth " & "(" & _

CStr(dHoleDepth) & ")."

.ShowDialog() 'Launch the dialog.

If CBool(.chkHoleDepthWarning.CheckState) Then

'User checked the box that said to change the hole depth.

'Change the POINT HoleDepth to the deepest depth

'in these data.

With dsHoleDepth

.Edit()

dsHoleDepth.Fields(gs_HoleDepth).Value = dHoleDepth

.Update()

End With

Else

'Abort the save and return focus to the row with

'the deepest depth.

'No message needs to be passed back.

gINTRules.GridData.ErrorCol = piPsDepth

gINTRules.GridData.ErrorRow = plRowDeepestDepth

HoleDepthCheckFnB = True

End If

frmHoleDepthWarning.DefInstance.Close()

End With

End If

Clearing Remaining Errors and Warnings

If you look at the Error List pane at the bottom of the screen you will find five with the message:

Variable 'xxxx' is passed by reference before it has been assigned a value. A null reference exception could result at runtime.

To clear these errors, we need to initialize five string variables to empty (“”). In

Page 214: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 213 —

clsInputChecks.Sample:

sRec = ""

sSCR = ""

sRQD = ""

For lRow = 1 To glNumRows

and clsInputChecks.Chemistry:

sUnit = ""

sExceedenceLimit = ""

For lRow = 1 To glNumRows

You will also see the following error:

Name 'dbOpenDynaset' is not declared.

In CommonProcedures.HoleDepthCheckFnB, change the OpenRecordset second argument from “dbOpenDynaset” to:

…OpenRecordset(sSql, dao.RecordsetTypeEnum.dbOpenDynaset)

Finally, there should be just three errors of the same type remaining:

'Null' is not declared. 'Null' constant is no longer supported; use 'System.DBNull' instead.

These refer to the following code in clsInputChecks.CPTReadings:

If bClearParent Then

.Fields(s_Field_MaxSleeveFriction).Value = Null

.Fields(s_Field_MaxTipResistance).Value = Null

.Fields(s_Field_MaxFrictionRatio).Value = Null

If you follow the advice of the error message, you get the following error:

'DBNull' is a type in 'System' and cannot be used as an expression.

The code actually needs to be rewritten as follows:

If bClearParent Then

.Fields(s_Field_MaxSleeveFriction).Value = DBNull.Value

.Fields(s_Field_MaxTipResistance).Value = DBNull.Value

.Fields(s_Field_MaxFrictionRatio).Value = DBNull.Value

Page 215: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 214 —

Late Binding

There are two declared references to gINT in this project:

Public Sub InputChecks(ByRef pgINTRules As gINT.clsGintRulesData)

Public gINTRules As gINT.clsGintRulesData

Declaration of these variables as gINT.clsGintRulesData gives the DLL all the information it needs to execute your gINTRules code. However, this locks your DLL into working with a specific configuration of the gINTRules object. If the configuration changes, then your DLL may not load, even if those changes have nothing to do with the parts of gINTRules that you are accessing. There are things that gINT Software can do to help ensure that this incompatibility does not occur. However, the task is complex in the COM environment. To ensure that your DLL will run with other builds of the gINT program, the above two lines of code can be rewritten as:

Public Sub InputChecks(ByRef pgINTRules As Object)

Public gINTRules As Object

This method is called “late binding” (the previous method is called “early binding”). With this method, your DLL obtains the information it needs about the gINT Rules object when the DLL is loaded. This is slower than early binding but should be imperceptible. A bigger disadvantage to late binding is that intellisense will not work in your .NET coding, that is, typing “gINTRules.” will not show the list of properties, methods, and objects associated with the gINTRules object. You would need to type these items yourself. If you type something incorrectly, there is no way for the .NET compiler to flag the error until you actually run the code.

Page 216: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 215 —

During code writing you want to early bind. For final release you want to late bind. One way to do this is to have two versions of the above two lines; one for early and one for late binding. You would REM one set or the other depending on the situation. Another way is to insert a compiler constant:

“DEBUG” would be set to either “-1” (True) or “0” (False). You would then rewrite each of the two lines like the following:

#If DEBUG Then

Public Sub InputChecks(ByRef pgINTRules As gINT.clsGintRulesData)

#Else

Public Sub InputChecks(ByRef pgINTRules As Object)

#End If

#If DEBUG Then

Public gINTRules As gINT.clsGintRulesData

#Else

Public gINTRules As Object

#End If

Page 217: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 216 —

Compiling the DLL

At this point you should have nothing in the Error List and you are ready to create your DLL. First, select the Build:Configuration Manager menu and make sure the “Active Solution Configuration” is set to “Release”. Then make sure the “DEBUG” compiler variable (see the “Late Binding” section above) is set to “0” (False). Finally, select the Build:Build Solution menu which will construct a number of files. The following are distributed:

• GR001_NET.DLL: This contains the executable code.

• GR001_NET.TLB: The type library provides definitions that are visible to COM programs, such as gINT. This makes the .NET DLL visible to gINT.

• Interop.gINT.DLL: This “run-time callable wrapper” (RCW) makes the necessary structures in gINT visible to the .NET DLL.

• Interop.Scripting.DLL: gINT uses the Microsoft scripting run-time library and this RCW makes that library visible to the .NET DLL. This DLL will only be created during the compilation process if it is needed. Therefore, if it does not appear, do not be concerned.

If you include other COM references in your DLL, other “Interop.XXX.DLL” files will be created and must be distributed with the DLL. Distribution of the DLL is covered in a subsequent section.

Obfuscating the the DLL

There are commercial and freeware versions of decompilers that can extract human-readable .NET sourcecode from .NET DLLs. If you want to protect your DLL from such applications you will need to “obfuscate” it. A number of commercial applications exist for that purpose. Search the Internet for “Obfuscate .NET” for a long list.

Using the DLL in gINT Rules

In the gINT Rules dialog we create a new module. We called it "GR001 DLL".

In the code window, we need to reference the DLL. Select the Edit:References menu item.

Page 218: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 217 —

The GR001 reference will appear in the list.

There will only be one procedure in this module. Here is the complete module code:

Option Explicit Sub Main Dim objGR As GR001.clsGR001 '-------------------------- Set objGR = New GR001.clsGR001 objGR.InputChecks gINTRules Set objGR = Nothing End Sub

The code does the following:

• Defines an object variable as the public class of the DLL.

• Instantiates the object with the Set…New statement.

• Calls the public procedure with the gINTRules object as its argument. This is the statement that invokes the DLL's code.

• Destroys the DLL object.

The last step is to point gINT to the new module when saving data. In the table properties dialog of each table that will use the DLL: SAMPLE, LITHOLOGY, CPT, and CHEMISTRY, click the browse button right of the "gINT Rules Procedure on Save" property and select the new module. The right side list will only show the "Main" procedure. If there are any other procedures this would never appear. It only appears when there is just Sub Main. Select "Main" and click Ok. Back in the gINT Rules Procedure on Save property you

Page 219: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 218 —

will have:

GR001 Dll!main

Change "main" to the procedure appropriate to the current table, that is, Sample, CPTReadings, etc.

You have now completed the process.

Special Note to Add-On Developers

There is one special consideration for those that will be selling gINT add-on products and distributing their programs in DLLs. If you are charging for each installation the chances are that not everyone in the organization will have your product installed on their system. Let’s say your DLL makes use of data in a common table such as PROJECT and one of your save procedures is run in that table. If you use the standard DLL gINT Rules code as shown above, the user will not be able to save.

Sub Main

Dim objGR As XXXXX.clsYYYYY

'--------------------------

Set objGR = New XXXXX.clsYYYYY

objGR.InputChecks gINTRules

Set objGR = Nothing

End Sub

If the DLL "XXXXX" does not exist, a compiler error will be thrown and the save is aborted. The only way out is for the user to undo changes. Unfortunately the error occurs on compilation of the above code in the Dim statement and therefore error trapping cannot be used.

To accommodate this situation, rewrite the the above as:

Sub Main

Dim objGR As Object

'------------------

On Error GoTo ErrorHandler

Set objGR = CreateObject("XXXXX.clsYYYYY")

objGR.InputChecks gINTRules

Set objGR=Nothing

Exit Sub

'=============

Page 220: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 219 —

ErrorHandler:

gINTRules.Success = True

gINTRules.ErrorMessage = "XXXXX is not installed." & vbCrLf & _

"XXXXX calculations were not performed."

End Sub

On trying to create the object, the DLL will not be found and control goes to the error handler. It is important to set the Success flag to True. Without this line gINT will think that there was an error in the procedure and will not allow the save. You don't have to show the message but you have to set the Success flag.

Debugging within the .NET Environment

1. Make sure the Debug:Start External Program and the References:Program Reference match

2. If there is a problem, clean and then rebuild.

3. Show how to expose configuration manager if not already shown.

4. Build:Configuration Manager. Select “Debug” in “Active solution configuration”. Must reset for distribution.

Page 221: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 220 —

You can have gINT use the .NET code environment instead of the DLL. This allows you to step through the code during the debugging stage. To do so, in the Solution Explorer, right click on GR001_NET and select Properties. Move to “Debug” tab and set the “Configuration” property to “Debug”. Then mark the “Start external program” option and click the browse button right of that field. Select the GINT8.EXE file in your main gINT program folder.

On running the DLL (Debug menu and then Start or just press the F5 function key), gINT will be launched. On exercising your gINT Rules code that accesses the DLL, the code environment will be working, not the DLL.

Network Trust Issues within the .NET Environment

The .Net runtime provides many new layers of security functionality. Depending on your network configuration, you may encounter problems running your new gINT Rules DLL related to security or trust issues. You may need to involve your IT department or System Administrator to resolve these security/trust issues.

If you are installing your gINT Rules DLL to local computers, you can skip this section.

Page 222: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 221 —

One way to resolve such trust issues is to use the Microsoft .Net Framework Configuration tool to set permissions on your new gINT Rules DLL so that it is “trusted”. To do this, open the Control Panel/Administrative Tools, and select the Microsoft .Net Framework 2.0 Configuration.

Page 223: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 222 —

The following window appears:

Page 224: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 223 —

Double-Click “Configure Code Access Security Policy” and then “Increase Assembly Trust”:

Page 225: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 224 —

Select “Make changes to this computer” and click Next.

Page 226: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 225 —

Click Browse and navigate the file dialog to the location of the gINT Rules DLL that you created above. Select the DLL and click Open.

Page 227: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 226 —

When you return to the previous form, click Next. Now select the Trust level you wish to accord this assembly.

The exact meaning of the four levels of trust described here are beyond the scope of this document. In general, assemblies that you write yourself and assemblies that come from gINT Software are more trustworthy than are those downloaded from some other website on the Internet.

Since you are the author of the gINT Rules DLL, it is likely that Full Trust is appropriate. Set the slider to Full Trust and click Next. Finally, click Finish after reviewing the summary.

This process will need to be repeated on each computer where the new gINT Rules DLL will be used.

Page 228: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 227 —

Appendices

Compatibility with Visual Basic

The code that is written in gINT Rules, with a few exceptions, will run in VBA and Microsoft Visual Basic with little or no modification. Following are the main differences between gINT Rules and VBA:

Items Available in VBA But Not Supported in gINT Rules

• Event driven execution. gINT Rules is procedural, except for User Dialogs which do have event driven options. See the CREATING AND USING DIALOGS topic.

• Expressions in procedure calls. For example, the following would work in VBA: Call MyProcedure(MyFunctionFnS(dMyVariable))

• The function MyFunctionFnS is first called and then the return value is passed to MyProcedure. In gINT Rules, this would lead to a "Type Mismatch" error. It needs to be written as: sResult = MyFunctionFnS(dMyVariable)

Call MyProcedure(sResult)

• Multiple statements on one line separated by colons (":").

• Conditional compilation

• Resume at current line

• The following statements are not supported in gINT Rules: ο Clipboard Object

ο Collection Object

ο Financial functions

ο GoSub

ο GoSub..Return

ο Line Numbers

ο LinkExecute

ο LinkPoke

ο LinkRequest

ο LinkSend

ο LoadPicture

Page 229: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 228 —

ο On..GoSub

ο On..Goto

ο With Events

Items Available in gINT Rules Not Supported in VBA

If you are planning to port your gINT Rules code to VBA or Visual Basic, do not use the following gINT Rules features:

• CallersLine

• Clipboard function

• DDEExecute

• DDEInitiate

• DDEPoke

• DDERequest

• DDETerminate

• DDETerminateAll

• MacroDir

• MacroRun

• MacroRunThis

• PortInt

• User dialogs

• Wait instruction

Naming Conventions and Programming Style

A consistent style of writing code is essential for long-term success. A rational, consistent manner of writing leads to easier maintenance and the ability to easily understand code that you have written months or years before. It also can speed up the learning curve when a new programmer becomes involved.

Certain rules can actually reduce your programming errors and help you find problems in the code, in particular, the naming of variables. For example, in the middle of a large procedure you see a variable named "MyVariable". What do you know about it by looking at the name? Absolutely nothing!

If it was called "psMyVariable", following the conventions outlined below, you would know that it is a string variable that was passed into the current procedure as a parameter. You could then go to the procedure header and see if it was passed ByVal (changes will not be

Page 230: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 229 —

passed back to the calling procedure) or ByRef (changes made in the current procedure will be passed back).

We at gINT Software have developed our own set of conventions over the years. These are not static. However, we make changes only after considering them very carefully. We have hundreds of thousands of lines of code to maintain and numerous programmers. Each programmer needs to be able to look at code written by someone else, perhaps years ago, and understand quickly what the code does and how it does it. Below we share these rules with you. Feel free to modify them to your needs and preferences. Whatever rules you decide on, follow them!

Dynamic Variables

Dynamic variables can have their values change (as opposed to constants which are covered below). Each variable name can be made up of 4 parts:

<scope><type><name><array suffix>

Examples:

Name Description

gsMyVariable Global string dynamic variable.

piMyVectorV Integer vector passed into a procedure.

dbMyDatabase Database object local to a procedure

Scopes

All scope prefixes are lower case.

Scope Prefix

Global g

Module level m

Parameter passed in function/sub/property argument list

p

Static x

Local procedure none

Page 231: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 230 —

Types

All types are lower case.

Standard

Type Prefix

Boolean b

Byte y

Currency c

Date/Time e

Double d

Integer i

Long l

Single n

String s

Structure (user-defined type) t

Variant v

Database (Data access objects [DAO])

Object Prefix

Container con

Database db

DBEngine dbe

Document doc

Dynaset ds

Field fld

Group grp

Page 232: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 231 —

Object Prefix

Index ix

Parameter prm

Querydef qd

Recordset rs

Snapshot sn

Table tb

Tabledef td

User usr

Workspace wsp

Note that dynaset, snapshot, and table objects are all declared as recordset. However, the above prefixes are used so as to know what type of recordset was created.

Page 233: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 232 —

Controls

Control Prefix

Check Box chk

Combo Box cbo

Command Button cmd

Frame fra

Label lbl

List Box lst

Option Button opt

Panel pnl

Picture Box pic

Text Box txt

Names

The core variable name will be upper and lower case as appropriate with the first character always being upper case. Do not use underscores ("_") in these names. They are reserved for constants (see below).

Array Suffixes

Suffixes are upper case. "V" is used for vectors (1 dimension array) and "A" for arrays (multi-dimensional). For example:

sArrayV(): One dimensional, local string array.

plArrayA(): Multi-dimensional, passed in, long array.

Constants

Mixed case with "_" used as text separators. There is always one underscore after the type prefix. Add additional underscores where appropriate. Examples:

s_Constant_Example: Local string constant

gd_Constant_Example: Global double-precision constant

Note that built-in Windows API constants and those of third party software shall NOT be renamed to match this convention. Leave as they are.

Page 234: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 233 —

Functions

Functions are written in mixed case, end with "Fn" and the type code for the return type with first type letter in caps. For example:

Function MyFunctionFnI(<argument list>) As Integer

Function MyFunctionFnS(<argument list>) As String

Function MyFunctionFnD(<argument list>) As Double

Indentations

Procedure and subprocedure header and end statements at far left. Code starts one tab in. Tab stops every 2 characters. Dim's and Const's follow normal indentation except in DECLARATIONS sections where they are at far left.

Case lines indented one tab stop in from the Select Case:

Select Case sAbc

Case "A"

Case "B"

Case "C"

Case Else

End Select

Declarations

Declare all variables and their types.

Option Explicit in all modules.

Top to bottom order where Const, Static, and Dim are used:

Const

Static

Dim

Page 235: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 234 —

Example:

Const s_My_Const As String = "ABC"

Static xsMyVariable As String

Dim sMyVariable As String

'-------------------------

End the Dim section with a comment following by dashes. Order the above sections alphabetically by data type and, where there is a significant number of declarations, leave a blank line between types:

Dim bNoSampleLen As Boolean

Dim dDepth As Double

Dim dHoleDepth As Double

Dim dMaxDepth As Double

Dim iPsDepth As Integer

Dim iPsRecLen As Integer

Dim iPsRecPC As Integer

Dim iPsRQDLen As Integer

Dim iPsRQDPC As Integer

Dim iPsSCRLen As Integer

Dim iPsSCRPC As Integer

Dim lRow As Long

Dim lRowDeepestDepth As Long

Dim sRec As String

Dim sRQD As String

Dim sSCR As String

Dim snTemp As Recordset

'-----------------------

Note that if sorted strictly alphabetically, "snTemp" should have been placed between "sLen" and "sRec". However, snTemp is a different data type and is therefore placed in its own group.

Page 236: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 235 —

Procedure Argument List

Write each procedure argument on its own line:

Private Function MyFunctionFnB(ByVal piArg1 As Integer, _

ByVal plArg2 As Long, _

ByRef psArg3 As String) _

As Boolean

In the case of functions, line up the "As …" under the beginning of the procedure name, as in the above example with “As Boolean”. Order the arguments in the following manner:

• Arguments that are not modified by the procedure.

• Arguments that are modified by the procedure.

That is, the first group of arguments is just data which the procedure uses to perform some tasks. The second group contains results passed back to the caller. With optional parameters it may not be possible to maintain this order since optional arguments must always be last.

We recommend explicitly inserting the ByVal and ByRef attributes for each argument.

Procedure Headers

All procedures will begin with headers, which include the following sections:

'*****************************************************

'Created by: date initials

'Description: What the procedure does.

'Input: Each argument that is passed into the procedure. Arguments

' are on a separate line with inline comments.

'Output: Each argument altered by the function or sub.

' Arguments are on a separate line with inline comments.

'Return: Explanation of the value returned by functions

'*****************************************************

String Concatenation

& and + Operators:

Always use the & operator when concatenating strings and the + operator only when adding numerical values.

Long strings

When creating a long string, use the underscore line-continuation character to create multiple lines of code so that you can read or debug the string easily. Align the quotation

Page 237: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 236 —

marks and place the & operator at the end of the previous line. Example:

sMsg = "This is a paragraph that will be " & _

"in a message box. The text is " & _

"broken into several lines of code " & _

"in the source code, making it easier " & _

"for the programmer to read and debug."

If and IIf

Although single line If’s are allowed, we recommend always using multi-line If’s. For example, write:

If lAbc > lXyz Then dMno = 25.4

as:

If lAbc > lXyz Then

dMno = 25.4

End If

For long If conditions, wrap onto multiple lines using the line-continuation character and place the "Then" under the "If":

If (lAbc > lXyz) And _

(sDef = "Hello") And _

bJkl _

Then

End If

Use the IIf (Immediate If) function sparingly. Remember that all the parameters are always evaluated. This could lead to problems. Generally only use the IIf when the two return parameters are literals. Example:

sAbc = IIf(bArrive, "Hello", "Goodbye")

Avoid Literal Values

Where possible, store values into variables or constants and do not use them literally. For example, the dialog facility within this VBA compiler returns a numeric value when the dialog box is closed by the user indicating which button was clicked:

iResult = Dialog(dlgMyDialogName)

If iResult = -1 Then…

What does "-1" mean? It happens to mean they clicked the OK button (0 = the Cancel button). Instead of the above, you could set up two module level constants to store these values and then use the constants. We recommend module level instead of local for a

Page 238: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 237 —

procedure because you will probably be using them for different dialog boxes in different procedures. In the Declarations section of the module you would have something like:

Private Const mi_Ok_Button As Integer = -1

Private Const mi_Cancel_Button As Integer = 0

Then the above code would be rewritten as:

iResult = Dialog(dlgMyDialogName)

If iResult = mi_Ok_Button Then…

That is much clearer.

Special Notes

Creating Records with Extended Keys

If you create records in a record structure that has extended text-type keys, you must insert a value for all of these fields. Nulls are not allowed. You must insert "" (empty) for no value.

Creating a Table in Code

The following will create a simple, non-gINT table in a gINT project, that is, a valid ACCESS table but one that will be ignored by gINT:

Dim sSql As String

Dim sTableName as string

'------------------

sTableName = …

sSql = "Create Table [" & sTableName & "] (GintRecID COUNTER CONSTRAINT PrimaryKey PRIMARY KEY, PointID Text (255))"

gINTRules.CurrentProject.Execute sSql

sSql = "CREATE INDEX GINTINDEX on [" & sTableName & "] (PointID)"

gINTRules.CurrentProject.Execute sSql

Notes:

1. This is valid code, but the new objects are not seen, and cannot be used in subsequent code, unless Refresh statements are executed:

Page 239: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 238 —

gINTRules.CurrentProject.TableDefs.Refresh

gINTRules.CurrentProject.TableDefs(sTableName).Fields.Refresh

2. If the code above is run in the gINT Rules development window, stepping through, you can see that the table has been created. However if you simultaneously open the project in Microsoft Access the new table can not be seen - it is evidently in some temporary workspace created by the Rules code engine - beyond the control of gINT. When the Rules procedure is assigned to real-time execution as a Table Property event or as an Add-in, the new table is real and can be seen in Microsoft Access.

Clearing Numeric Fields

If you are directly assigning a value to a numeric field in a recordset, you cannot assign an empty text variable, you must assign the special "Null" value. For example, you have a parent-child grid and the child performs some calculation which assigns a value to a numeric field in the parent. Let's call the field "My Parent Field". Further, let us assume that the value that will be assigned to the parent field is stored in a text variable called "sValue". If there are not sufficient data to calculate the value, "sValue" is assigned an empty value and you want the "My Parent Field" cleared. The code below will not work if "sValue" is empty.

With gINTRules.GridData

.ParentRecord.Edit

.ParentRecord.Fields("My Parent Field").Value = sValue

.ParentRecord.Update

.RefreshParent = True

End With

A "Data Conversion" error will result. The assignment must be:

.ParentRecord.Fields("My Parent Field").Value = _

IIf(Len(sValue) > 0, sValue, Null)

This says that if "sValue" has a length (is not empty), then assign it to the field, otherwise assign "Null". Note that this will still fail if "sValue" not empty but is not a number. Therefore, a better method is to use:

.ParentRecord.Fields("My Parent Field").Value = _

IIf(IsNumeric(sValue), sValue, Null)

Considerations for Porting to VB.NET 2005

Introduction

If you plan to ultimately port your gINT Rules code to VB.NET, there are many things you

Page 240: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 239 —

can do to make the port easier and a number of modifications that must be made within VB.NET after porting the code. This section outlines these two classes of porting considerations. Even if you do not plan to port your code, we recommend following the suggestions in the Writing your Code Correctly the First Time section below. These suggestions are good programming practice.

See the Converting to a DLL section for in depth discussions of the porting process.

We realize that this section does not present an exhaustive list. We will be expanding it as we find other modifications. We would appreciate any that you have found that are not listed in this section and we will add your findings to these lists. We would especially appreciate pointing out code in our gINT Rules samples that do not conform to the Writing your Code Correctly the First Time section recommendations. We would like to correct those code segments.

Writing your Code Correctly the First Time

The language compiler used by gINT follows VBA (Visual Basic for Applications) quite closely, including many short cuts that VB.NET no longer supports. So code that works perfectly well in gINT Rules will be flagged as errors or warnings in .NET. This is especially true if you have set Option Strict On in .NET.

There are many things you can do to so that most of your code comes across with no error or warnings.

Explicitly Set Data Type to the expected Type

With Option Strict implicit data conversions are not supported. In gINT Rules the following will work:

If Len(sText) Then

Do Something

Else

Do Something Else

End If

“Len(sText)” returns a value of type Long (equivalent to Integer in .NET). “If” is expecting a Boolean data type. VBA makes this conversion for you. .NET will flag this with the error “Option Strict On disallows implicit conversions from 'Integer' to 'Boolean'”. The above needs to be rewritten as:

If Len(sText) > 0 Then

This construct will return a True or False, exactly what the “If” expects. Alternatively, you could use:

If CBool(Len(sText)) Then

The “CBool” function converts the argument to a Boolean. If the “Len” function returns “0”,

Page 241: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 240 —

“False” will be returned, otherwise “True”.

Following are some other common examples of this construct:

Original Code Rewrite As

sValue = IIf(Len(sText), _

“Something”, _

“Something Else”)

sValue = IIf(Len(sText) > 0, _

“Something”, _

“Something Else”)

Do While iPointer Do While iPointer > 0

If Instr(sText, “ABC”) Then If Instr(sText, “ABC”) > 0 Then

iPercent = 100 * dLen / _

pdOverallLen

iPercent = CInt(100 * dLen / _

pdOverallLen)

Declare all Constants with a Data Type

The following is accepted in gINT Rules:

Const i_MyConst = 6

This will be flagged as an error in .NET. Rewrite as:

Const i_MyConst As Integer = 6

Declare all Variables with a Data Type

The following declaration:

Dim MyVariable

Is interpreted as a variable of “Variant” type by gINT Rules. This type is not supported .NET and would be interpreted as an “Object” type. This may or may not cause the code to behave differently. In any case, it is best to explicitly declare the variable by a specific type that is not a Variant.

Declare all Procedure Arguments ByVal or ByRef

If you write the following procedure declaration:

Public Sub MyProcedure(psAbc As String)

VBA assumes that psAbc is passed ByRef, that is, any changes made to psAbc in the procedure are passed back to the caller. When you copy the above to .NET it assumes the opposite, that is, psAbc is passed ByVal. In this case any changes made to psAbc in this procedure will not be passed back to the calling procedure. If the caller is expecting a changed value, this is will obviously break your code. So explicitly declare all your procedure arguments ByVal or ByRef.

Page 242: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 241 —

Initialize all Variables

String variables are initialized to “Empty” ( = “”) after being declared in VBA. In .NET the initial value of strings is “Nothing” which is not the same. Some operations on “Nothing” strings could result in an error condition, whereas the same operation on an “Empty” string would succeed. This is also true with object variables (strings are objects in .NET). String and object variables that are used in expressions before being initialized will generate warnings in .NET like the following:

Variable 'MyVariable' is used before it has been assigned a value. A null reference exception could result at runtime.

The way around this problem while still in the gINT Rules environment is to initialize all string variables to “Empty”, that is:

sMyVariable = “”

In general, it is good programming practice to initialize all variables, string or otherwise. In .NET this is easier since a value can be assign in the declaration, for example:

Dim sMyVariable As String = “”

What you need to do after Porting the Code

Certain code changes necessary to be compatible with .NET cannot be made until after the code is ported. Here are some of them.

Data Types

All the data types in VBA, except for the “Variant” type, are supported in .NET. However, two types have changed. The “Integer” type in VBA is an 8 bit value (range of -32K to 32K) whereas in .NET it is a 16 bit value (range of -2 billion to 2 billion). The equivalent of the gINT Rules “Integer” type would be a “Short” type in .NET.

The “Long” type in gINT Rules is a 16 bit value but is a 32 bit value (range -1018 to 1018) in .NET. The equivalent of the gINT Rules “Long” type would be an “Integer” type in .NET.

In most cases this will not harm the workings of your code; you will just be using variables that take more memory than necessary to hold your data. However, there are cases where the code will not function if these variable declarations are not changed properly.

The following Windows API call works fine in gINT Rules:

Public Declare Function GetTempFileName _

Lib "kernel32" Alias "GetTempFileNameA" _

(ByVal lpszPath As String, _

ByVal lpPrefixString As String, _

ByVal wUnique As Long, _

ByVal lpTempFileName As String) _

Page 243: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 242 —

As Long

This will fail in .NET because the Windows API is expecting a 16 bit value in the wUnique argument. A “Long” in .NET is 32 bit. Further, the function will also return a 16 bit value but the above declaration in .NET says it will return a 32 bit value. The above must be rewritten as:

Public Declare Function GetTempFileName _

Lib "kernel32" Alias "GetTempFileNameA" _

(ByVal lpszPath As String, _

ByVal lpPrefixString As String, _

ByVal wUnique As Integer, _

ByVal lpTempFileName As String) _

As Integer

A better solution to fixing the above declaration is to eliminate Windows API calls completely and use the native .NET functionality.

gINT Rules Enumerations

gINT Rules uses a number of enumerated values. For example, the gINTRules.FolderPath properties will return certain gINT folders. For example:

sProjectsFolder = gINTRules.FolderPath(gINT_fpProjects)

“gINT_fpProjects” is an enumerated constant. If the above code is placed in a .NET project, it will not work. You must tell .NET where to find the enumerated value as follows:

sProjectsFolder = _

gINTRules.FolderPath(gINT.gINTFolderPath.gINT_fpProjects)

When you are writing the code in .NET this is not an issue, the Intellisence functionality will show you the proper choices as below:

So if you have ported such a line of code from gINT Rules and .NET says it doesn’t know the variable, delete it and let .NET show you the list.

Use of the Database Field “Null” Value

In clearing a numeric or date/time field in a database table, you would set that field to “Null” in VBA. For example:

rsRecordsetObject.Fields(sFieldName).Value = Null

Page 244: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 243 —

“Null” is not recognized by .NET. The above needs to use “DBNull.Value”:

rsRecordsetObject.Fields(sFieldName).Value = DBNull.Value

Option Strict Considerations

“Option Strict” is a settting that forces strict adherence data typing rules

gsDataA = CType(VB6.CopyArray(.DataArray), String(,))

System.Windows.Forms.MessageBox.Show("XXX", "yyy", Windows.Forms.MessageBoxButtons.OK, Windows.Forms.MessageBoxIcon.Exclamation)

Multiple Dimension Arrays

The following code in VBA works:

Dim sMyArrayA() As String

ReDim sMyArrayA(0 To 5, 0 To 10)

In .NET multiple dimension arrays need to be indicated as such within the initial declaration. Therefore, the .NET declaration would be:

Dim sMyArrayA(,) As String

If the array had three dimensions, the following would need to be used:

Dim sMyArrayA(,,) As String

The Use of User-Defined Types

VBA user-defined types are structures in .NET. Types are no longer supported by .NET. For example, the following code in VBA:

Public Type MyType

sName As String

iPointer As Integer

dValue As Double

End Type

is not recognized by .NET. It can be made functional in .NET by changing the two instances of “Type” to “Structure”. Structures are not one to one replacements for types. They have much more functionality than VBA types. See .NET documentation for details.

File Streams

Following is a code segment in VBA format that opens a text file, reads each line, and then closes the file:

Page 245: gINT Rules for gINT Version V8i - Bentley Communities · gINT Rules for gINT Version V8i gINT V8i User Guide DAA039590-1/0001

— 244 —

hFile = FreeFile

Open sFileName For Input As #hFile

Do Until EOF(hFile)

Line Input #hFile, sLine

…code that does something with each line from the file

Loop

Close #hFile

This structure is no longer supported in .NET. Instead, you must use an IO (Input/Output) “stream”. Following is one way to rewrite the above in .NET:

Dim srSourceFile As System.IO.StreamReader

srSourceAGS = System.IO.File.OpenText(sSourceFilePathAndName)

sLine = srSourceFile.ReadLine()

While Not sLine Is Nothing

…code that does something with each line from the the file

sLine = srSourceFile.ReadLine()

Loop

srSourceFile.Close()

The same types of changes apply to writing to a text file.

Using Native .NET Functionality

.NET is a rich environment with many libraries of built-in functions. Many of the procedures written in VBA can be replaced with native .NET functions. For example, the MaxValFnD procedure written for the CPT data processing above can be replaced with the Math.Max function. In the GRA001 sample gINT Rules project on the gINT Web site, the UniqueFileNameFnS function can be replaced with the .NET System.IO.Path.GetTempFileName function.

Native .NET procedures eliminate code that you have to maintain and generally speed up code execution. Use them whenever possible.